6

早上好,

我有一个包含几百万行的表,我需要查看按时间戳排序的数据。

当我试图这样做时

SELECT * FROM table ORDER BY date DESC offset 0 LIMIT 200

MySQL 将对所有数据进行排序,然后将响应 200 行,这是一个性能问题。因为每次我想滚动页面时都订购所有东西是不明智的!

您对我们如何提高性能有任何想法吗?

4

1 回答 1

4

首先,您需要根据日期字段创建索引。这允许按顺序检索行,而不必在每次发出请求时对整个表进行排序。

其次,对结果集的深入研究越深入,基于索引的分页就越慢。为了显示:

  • ORDER BY indexedcolumn LIMIT 0, 200速度非常快,因为它只需要扫描 200 行索引。

  • ORDER BY indexedcolumn LIMIT 200, 200比较快,但是需要扫描400行的索引。

  • ORDER BY indexedcolumn LIMIT 660000, 200非常慢,因为它需要扫描 660,200 行索引。

    注意:即便如此,这可能仍然比没有索引要快得多。

您可以通过几种不同的方式解决此问题。

  1. 实现基于值的分页,因此您基于上一页上最​​后一个结果的值进行分页。例如:

    WHERE indexedcolumn>[lastval] ORDER BY indexedcolumn LIMIT 200将 [lastval] 替换为当前页面的最后一个结果的值。索引允许随机访问特定值,并从该值向前或向后进行。

  2. 只允许用户查看前 X 行(例如 1000)。如果他们想要的值是第 2529 个值,那就不好了。

  3. 考虑一些分解大表的逻辑方式,例如按第一个字母、年份等,这样用户就不必遇到数百万行的整个结果集,而是需要先深入到特定的子集,这将是一个更小的集合和更快的排序。

如果您将 WHERE 和 ORDER BY 组合在一起,您需要在索引设计中反映这一点,以使 MySQL 能够继续从索引中受益以进行排序。例如,如果您的查询是:

SELECT * FROM mytable WHERE year='2012' ORDER BY date LIMIT 0, 200

然后,您的索引将需要按该顺序位于两列(年份、日期)上。

如果您的查询是:

SELECT * FROM mytable WHERE firstletter='P' ORDER BY date LIMIT 0, 200

然后,您的索引将需要按该顺序位于两列(首字母、日期)上。

这个想法是,只要您将先前的列指定为条件中的常量(单个值),多列上的索引就允许按任何列进行排序。因此,如果您将 A 和 B 指定为 WHERE 条件中的常量,则 A、B、C、D 和 E 上的索引允许按 C 排序。A 和 B 不能是范围。

于 2013-10-24T03:33:14.337 回答