dai*_*oor 5 mysql sql performance select sql-order-by
早上好,
我有一个包含几百万行的表,我需要查看按时间戳排序的数据。
当我尝试这样做时
SELECT * FROM table ORDER BY date DESC offset 0 LIMIT 200
Run Code Online (Sandbox Code Playgroud)
MySQL 将对所有数据进行排序,然后以 200 行进行响应,这是一个性能问题。因为每次我想滚动页面时都订购所有东西是不明智的!
您对我们如何提高性能有任何想法吗?
首先,您需要根据日期字段创建索引。这允许按顺序检索行,而不必在每次发出请求时对整个表进行排序。
其次,对结果集的研究越深入,基于索引的分页就会变得越慢。为了显示:
ORDER BY indexedcolumn LIMIT 0, 200速度非常快,因为它只需要扫描索引的 200 行。
ORDER BY indexedcolumn LIMIT 200, 200相对较快,但需要扫描索引的 400 行。
ORDER BY indexedcolumn LIMIT 660000, 200非常慢,因为它需要扫描索引的 660,200 行。
注意:即便如此,这仍然可能比根本没有索引要快得多。
您可以通过几种不同的方式解决这个问题。
实施基于值的分页,以便您根据上一页上最后一个结果的值进行分页。例如:
WHERE indexedcolumn>[lastval] ORDER BY indexedcolumn LIMIT 200将 [lastval] 替换为当前页面的最后一个结果的值。该索引允许随机访问特定值,并从该值向前或向后进行。
只允许用户查看前 X 行(例如 1000)。如果他们想要的值是第 2529 个值,那么这就不行了。
考虑一些逻辑方法来分解大表,例如按第一个字母、年份等,这样用户就不必遇到数百万行的整个结果集,而是需要首先深入到特定的子集,这将是一个较小的集合并且排序速度更快。
如果您将 WHERE 和 ORDER BY 组合在一起,您需要在索引设计中反映这一点,以使 MySQL 能够继续从排序索引中受益。例如,如果您的查询是:
SELECT * FROM mytable WHERE year='2012' ORDER BY date LIMIT 0, 200
Run Code Online (Sandbox Code Playgroud)
然后,您的索引需要按顺序位于两列(年份、日期)上。
如果您的查询是:
SELECT * FROM mytable WHERE firstletter='P' ORDER BY date LIMIT 0, 200
Run Code Online (Sandbox Code Playgroud)
然后您的索引需要按顺序位于两列(第一个字母,日期)上。
这个想法是,只要您将前面的列指定为条件中的常量(单个值),多列上的索引就允许按任何列进行排序。因此,如果您将 A 和 B 指定为 WHERE 条件中的常量,则 A、B、C、D 和 E 上的索引允许按 C 排序。A 和 B 不能是范围。