假设有一个千万量级的表,取第1000到1010条数据;
select * from table limit 1000,10;
这条SQL非常快就可以完成,然而下面这条SQL就非常慢了
select * from table limit 1000000,10;
mysql会查询1000010条数据,然后将前1000000条放弃,只取后10条。
在这里通常有三种方式来优化大数据分页问题:
1.不允许查询那么多页之后的数据
这种方式是从业务上解决的,不过通常也是最常用以及最通用的,谁会查看100w条之后的10条数据呢?
2.通过主键id来作为上一页的最后一个值
在这里我们假设id都是连续且中间没有断的。那么上面那条sql就可以改为
select * from table where id > 1000000 limit 10;
这条sql非常快,因为id索引是B+树,很快就可以找到id=1000000的那个节点,然后向后取10条记录即可,而且都是顺序IO,速度非常快。(关于B+树索引和顺序IO我会在下一期给大家讲解相关知识点)。这种方式不是很通用。
3.延迟关联
思想是延迟对列的访问,sql如下
select a.*
from table a
inner join (
select id
from table
limit 1000000, 10
) t on t.id = a.id
这样即使扫描了1000010条记录,也是在id索引树上扫描扫描的,索引树在内存中,不需要回表查询其他列的信息。只有最后10条数据需要回表。
总结
第一种是最好的方案;第二种通用性很差,但是性能最好;第三种通用性很好,性能其次,还是需要扫描1000010条数据(但是扫描的是内存中的B+树)。