有效地选择前n行

时间:2017-01-24 01:02:23

标签: mysql

所以我有一张桌子,可能有数百万行,

user   | points
---------------
user1  | 10
user2  | 12
user3  | 7
...

并希望SELECT * FROM mytable ORDER BY points LIMIT 100, 1000 现在它工作正常,但速度非常慢(在巨大的表上),因为它拒绝使用任何类型的索引,但执行全表扫描。我怎样才能提高效率呢?

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

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

最后,我尝试使用force index,这几乎没有产生任何性能提升,因为它仍然提取整个表,但没有排序(在EXPLAIN中使用filesort:false)

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

1 个答案:

答案 0 :(得分:2)

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

永远从不使用SELECT *。这是一个菜鸟的错误。它基本上告诉查询计划器它需要给你一切。 始终枚举结果集中所需的列。这是您想要的查询(假设您没有过分简化您的问题)。

 SELECT user, points
   FROM table
  ORDER BY points
  LIMIT 100,1000

使用复合索引。对于查询,(points, user)上的复合索引将允许使用部分索引扫描来满足您的查询。这应该比全表排序更快。 MySQL可以向后或向前扫描索引,因此您无需担心降序

要添加正确的索引,请使用这样的命令。

ALTER TABLE table ADD INDEX points_user (points, user);

修改即可。反对在这里使用SELECT *的建议是基于(1)我未经证实的怀疑,即所讨论的表格过于简单并且在现实生活中有其他列,以及(2)有时索引必须与查询匹配的不方便的现实正是为了获得最佳性能结果。

我坚持认为,根据经验,在具有性能敏感性的查询中使用SELECT *并非良好的工程实践(除非您非常喜欢查询,否则您希望一次又一次地回到它)。