在系统中需要进行分页操作的时候,我们通常会使用
LIMIT
加上偏移量 的办法实现,同时加上合适的ORDER BY
子句。如果有对应的索引,通常效率会不错,否则,MySQL
需要做大量的文件排序操作。
一个非常常见又令人头疼的问题是,在偏移量非常大的时候,例如,可 能是LIMIT 1000
,
20
这样的查询,这时
MySQL
需要查询
10020
条记录然 后只返回最后20
条,前面
10 000
条记录都将被抛弃,这样的代价非常高。如果所有的页面被访问的频率都相同,那么这样的查询平均需要访问半个表的数据。要优化这种查询,要么是在页面中限制分页的数量,要么是优化大偏移量的性能。
优化此类分页查询的一个最简单的办法就是尽可能地使用索引覆盖扫描,而不是查询所有的行。然后根据需要做一次联接操作再返回所需的列。在偏移量很大的时候,这样做的效率会有非常大的提升。考虑下面的查询:
create index inx_stu_name_cla on student_info(student_id,name,class_id);
select student_id,name,class_id FROM student_info ORDER BY name LIMIT 1000000,100;
延迟联接
如果这个表非常大,那么这个查询最好改写成下面的样子:
SELECT s1.student_id,s1.name,s1.class_id FROM student_info s1
INNER JOIN (select id FROM student_info ORDER BY name LIMIT 1000000,100) s2
USING(id);
这种
“
延迟联接
”
之所以有效,是因为它允许服务器在不访问行的情况下 检查索引中尽可能少的数据,然后,一旦找到所需的行,就将它们与整 个表联接,以从该行中检索其他列。类似的技术也适用于带有LIMIT
子 句的联接。