介绍
分页在我们日常开发中是非常常见的需求,我们通常会用LIMIT加上偏移量的办法实现。但是大家有没有考虑过当偏移量大的时候分页SQL的执行效率呢?下面以一个例子来模拟优化的过程。
业务需求
要求查询出某一个商品的前10条评论。
我们写出的SQL可能会是这个样子:
对SQL进行优化
使用EXPLAIN进行分析:
建立联合索引:
建立组合索引的时候,区分度最高的在左边。有一个例外就是存在非等号和等号混合判断条件时,在建立索引的时候,把等号条件的列前置。如where a>? and b=? 那么即使a的区分度更高,也必须把b放在索引的最前列。
目前数据库没有数据,如果有数据可以根据索引的区分度来选择优先级。同时要注意上面提到的非等号和等号混合判断条件的问题。
建立联合索引后对SQL进行一次分析,可以看到type由ALL变成ref:
问题的关键在于:MySQL并不是跳过offset(偏移量)行,而是取offset+N行,然后返回放弃钱offset行,返回N行,
假如offset特别大的时候效率就特别低下。
接下来对SQL语句的结构进行优化:
还可以这样写:
这样让MySQL扫描了更少的页面,获取要访问的记录后再根据关联列回表查询关联的列。将随机I/O变成了顺序I/O。