所以我有一个表,可能有数百万行,
user | points
---------------
user1 | 10
user2 | 12
user3 | 7
...
并且想要SELECT * FROM mytable ORDER BY points LIMIT 100, 1000
现在工作正常,但速度非常慢(在大表上),因为它拒绝使用任何类型的索引,而是执行全表扫描。我怎样才能使它更有效率?
我的第一个(明显的)想法是在 points DESC
上使用索引,但后来我发现 MySQL 根本不支持这些。
接下来,我尝试反转 points 的符号,这意味着基本上在 -points 上有一个升序索引,这也没有帮助,因为它不使用索引进行排序
最后,我尝试使用 force index
,这几乎没有产生任何性能改进,因为它仍然获取整个表,但不排序(在 EXPLAIN
中使用 filesort: false )
我确信这一定是一个已解决的问题,但我没有在网上找到任何有用的信息。任何提示将不胜感激。
最佳答案
从查询中获得更好性能的一些方法。
从不从不使用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 *
不是好的工程实践(除非您非常喜欢该查询以至于想再次使用它又一次)。
关于mysql - 有效地选择前 n 行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41818357/