Mysql 高效地选择前n行

Mysql 高效地选择前n行,mysql,Mysql,我有一张桌子,可能有几百万行 user | points --------------- user1 | 10 user2 | 12 user3 | 7 ... 并希望从mytable中按点数顺序选择*限制为1001000 现在,它工作正常,但在大型表上的速度非常慢,因为它拒绝使用任何类型的索引,而是执行完整的表扫描。我怎样才能提高效率 我第一个明显的想法是在points DESC上使用索引,但后来我发现MySQL根本不支持这些 接下来,我尝试反转登录点,这意味着本质上在点上有一个升

我有一张桌子,可能有几百万行

user   | points
---------------
user1  | 10
user2  | 12
user3  | 7
...
并希望从mytable中按点数顺序选择*限制为1001000 现在,它工作正常,但在大型表上的速度非常慢,因为它拒绝使用任何类型的索引,而是执行完整的表扫描。我怎样才能提高效率

我第一个明显的想法是在points DESC上使用索引,但后来我发现MySQL根本不支持这些

接下来,我尝试反转登录点,这意味着本质上在点上有一个升序索引,这也没有帮助,因为它不使用索引进行排序

最后,我尝试使用force索引,这几乎没有带来任何性能改进,因为它仍然获取整个表,但在EXPLAIN中没有使用filesort:false进行排序


我相信这一定是一个解决了的问题,但我没有在网上找到任何有用的信息。任何提示都将不胜感激。

一些从查询中获得更好性能的方法


切勿使用SELECT*。这是新手犯的错误。它基本上告诉查询计划器它需要为您提供一切。始终枚举结果集中所需的列。这是您想要的查询,假设您没有过度简化您的问题

 SELECT user, points
   FROM table
  ORDER BY points
  LIMIT 100,1000
使用复合索引。在您的查询中,对于点的复合索引,用户将允许使用部分索引扫描来满足您的查询。这应该比全表排序快。MySQL可以向后或向前扫描索引,所以您不需要担心降序

要添加正确的索引,请使用如下命令

ALTER TABLE table ADD INDEX points_user (points, user);
编辑。反对在此处使用SELECT*的建议是基于1我未经证实的怀疑,即所讨论的表过于简单,并且在现实生活中有其他列,以及2不方便的现实,即有时索引必须精确匹配查询才能获得最佳性能结果


根据经验,我坚持我的观点,在查询中使用SELECT*对性能敏感是不好的工程实践,除非您非常喜欢该查询,并且希望一次又一次地返回该查询。

如果您的表中有数百万行,那么对于您正在运行的硬件来说,您可能有太大的数据库。然而,结构本身可能与此有很大关系。您的数据库只是用户/点吗?如中所示,主键是varchar?或者?这个“top n”是怎么回事?@草莓我认为MySql不支持top n,是吗?top 10=按点数排序DESC LIMIT 10阅读此部分,尤其是关于性能问题的部分。它基本上告诉查询计划器它需要为您提供一切什么?规划者当然知道有两列,所以你的查询在查询优化者看来是完全相同的。@zerkms这也是我的思路,但显然它确实起到了作用。无论如何,使用复合索引似乎已经解决了我的问题@CBenni这是一个mysql覆盖索引,对吗?我不敢相信SELECT*vs SELECT user,在这种特殊情况下,点会改变任何东西。关于SELECT*vs SELECT列,有很多讨论,我喜欢的是@JorgeCampos,它与SELECT*vs通过显式枚举选择非常相同的列无关。那些只提到选择更少的列,这直观上更有效,传输的内容更少