MySQL根据特定顺序分页大数据
Posted
技术标签:
【中文标题】MySQL根据特定顺序分页大数据【英文标题】:MySQL paging large data based on a specific order 【发布时间】:2013-10-09 22:09:05 【问题描述】:早安,
我有一个包含几百万行的表,我需要查看按时间戳排序的数据。
当我尝试这样做时
SELECT * FROM table ORDER BY date DESC offset 0 LIMIT 200
mysql 将对所有数据进行排序,然后响应 200 行,这是一个性能问题。因为每次我想滚动页面时都订购所有东西是不明智的!
您对我们如何提高性能有任何想法吗?
【问题讨论】:
你能解释一下为什么offset 0
吗?
记录是否总是按时间顺序添加到表中?在这种情况下,只需将自动增量整数列 RowNumber
添加到表中,为其添加索引,然后使用 WHERE RowNumber BETWEEN 0 AND 200
。
@7alhashmi 0 只是变量的一个例子,它可能是任何东西!它是一个寻呼系统!
@Dan 未排序,我无法编辑表格!
如果您因为没有权限而无法编辑表格,请创建自己的表格并将数据导入其中。能够在排序依据的列上添加索引非常重要。
【参考方案1】:
首先,您需要根据日期字段创建索引。这允许按顺序检索行,而不必在每次发出请求时对整个表进行排序。
其次,基于索引的分页越深入结果集就越慢。举例说明:
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
那么您的索引将需要按该顺序位于两列(年份、日期)上。
如果您的查询是:
SELECT * FROM mytable WHERE firstletter='P' ORDER BY date LIMIT 0, 200
那么您的索引将需要按顺序位于两列(首字母、日期)上。
这个想法是,只要您在条件中将先前的列指定为常量(单个值),多列上的索引就允许按任何列进行排序。因此,如果您将 A 和 B 指定为 WHERE 条件中的常量,则 A、B、C、D 和 E 上的索引允许按 C 排序。 A 和 B 不能是范围。
【讨论】:
看起来这是唯一的解决方案,但我可以使用它,因为我无法访问数据库!如果您无法访问甚至无法真正访问数据库,那么与某些客户合作会非常困难!我什至尝试创建一个虚拟数据库并在其中导入数据,但该解决方案不适用于客户端,因此我们放弃了该功能! ...尽可能简单:) @thomasrutter:谢谢你的解释。一个简单的问题:当值是时间戳并且我们可以在不同的行中具有相同的时间戳值时,我们如何使用基于值的分页 -> 在这种情况下,LIMIT 子句会产生问题。 必须在唯一列或列组合上完成。如果顺序永远不会改变(即不能修改时间戳),那么考虑使用自动增量 ID 并仅对该列进行排序。或者您可以对多个列进行排序,例如ORDER by timestamp DESC, unique_ID DESC
,以便在时间戳冲突的情况下按ID 排序。您需要传入两个变量。以上是关于MySQL根据特定顺序分页大数据的主要内容,如果未能解决你的问题,请参考以下文章