分页查询优化
1 示例表:
2 CREATETABLE`employees`(
3 `id`int(11)NOTNULLAUTO_INCREMENT,
4 `name`varchar(24)NOTNULLDEFAULT''COMMENT'姓名',
5 `age`int(11)NOTNULLDEFAULT'0'COMMENT'年龄',
6 `position`varchar(20)NOTNULLDEFAULT''COMMENT'职位',
7 `hire_time`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'入职时间',
8 PRIMARYKEY(`id`),
9 KEY`idx_name_age_position`(`name`,`age`,`position`)USINGBTREE
10 )ENGINE=InnoDBAUTO_INCREMENT=1DEFAULTCHARSET=utf8COMMENT='员工记录表';
11
很多时候我们业务系统实现分页功能可能会用如下sql实现
1 mysql>select*fromemployeeslimit10000,10;
表示从表employees中取出从10001行开始的10行记录。看似只查询了10条记录,实际这条SQL是先读取10010
条记录,然后抛弃前10000条记录,然后读到后面10条想要的数据。因此要查询一张大表比较靠后的数据,执行效率
是非常低的。
>>常见的分页场景优化技巧:
1、根据自增且连续的主键排序的分页查询
首先来看一个根据自增且连续主键排序的分页查询的例子:
1 mysql>select*fromemployeeslimit90000,5;
该SQL表示查询从第90001开始的五行数据,没添加单独orderby,表示通过主键排序。我们再看表employees,因
为主键是自增并且连续的,所以可以改写成按照主键去查询从第90001开始的五行数据,如下:
1 mysql>select*fromemployeeswhereid>90000limit5;
查询的结果是一致的。我们再对比一下执行计划:
1 mysql>EXPLAINselect*fromemployeeslimit90000,5;
1 mysql>EXPLAINselect*fromemployeeswhereid>90000limit5;
显然改写后的SQL走了索引,而且扫描的行数大大减少,执行效率更高。