在 mysql 中使用 limit 可以实现快速分页,但是如果数据到了几百万时我们的 limit 语句必须优化才能有效的合理的实现分页了,否则查询效率会很慢,甚至可能卡死你的服务器。
如 select * from table limit 0,20 这个没有问题,当 limit 10000,20 的时候数据读取就很慢。limit 10000,20 的意思扫描满足条件的 10020 行,扔掉前面的 10000 行,返回最后的 20 行,问题就在这里。
总结
1.当偏移量比较小的时候,经试验验证直接使用 limit 的方式和第二种方式相差不大。但是当偏移量比较大的时候,使用第二种方式的效率明显优于第一种。
2.当一个数据库表过于庞大,limit offset, length 中的 offset 值又很大的时候,可以考虑增加 order by,但是 order by 字段需要建立索引。
3.如果使用子查询去优化 limit 的话,则子查询必须是连续的,某种意义来讲,子查询不应该有 where 条件,where 会过滤数据,使数据失去连续性。
如 select * from table limit 0,20 这个没有问题,当 limit 10000,20 的时候数据读取就很慢。limit 10000,20 的意思扫描满足条件的 10020 行,扔掉前面的 10000 行,返回最后的 20 行,问题就在这里。
优化此类分页查询的一个最简单的办法就是尽可能地使用索引覆盖扫描,而不是查询所有的列。然后根据需要做一次关联操作再返回所需的列。对于偏移量很大的时候,这样的效率会提升非常大。考虑下面的查询:
SELECT id, TitleChn FROM Literature ORDER BY Jid LIMIT 100000, 20;
如果这个表非常大,那么这个查询最好改写成下面的这样子:
SELECT id, TitleChn FROM Literature
INNER JOIN (
SELECT id FROM Literature ORDER BY Jid<span style="font-family: Arial, Helvetica, sans-serif;"> </span>LIMIT 100000, 20
) AS li USING(id);
这里的“延迟关联”将大大提升查询效率,它让 mysql 扫描尽可能少的页面,获取需要访问的记录后再根据关联列回原表查询需要的所有列。这个技术也可以用于优化关联查询中的 limit 子句。总结
1.当偏移量比较小的时候,经试验验证直接使用 limit 的方式和第二种方式相差不大。但是当偏移量比较大的时候,使用第二种方式的效率明显优于第一种。
2.当一个数据库表过于庞大,limit offset, length 中的 offset 值又很大的时候,可以考虑增加 order by,但是 order by 字段需要建立索引。
3.如果使用子查询去优化 limit 的话,则子查询必须是连续的,某种意义来讲,子查询不应该有 where 条件,where 会过滤数据,使数据失去连续性。