您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 项目/工程管理 > MySQL分页优化实测效果明显
分页优化通常,我们会采用ORDERBYLIMITstart,offset的方式来进行分页查询。例如下面这个SQL:SELECT*FROM`t1`WHEREftype=1ORDERBYidDESCLIMIT100,10;或者像下面这个不带任何条件的分页SQL:SELECT*FROM`t1`ORDERBYidDESCLIMIT100,10;一般而言,分页SQL的耗时随着start值的增加而急剧增加,我们来看下面这2个不同起始值的分页SQL执行耗时:yejr@imysql.comSELECT*FROM`t1`WHEREftype=1ORDERBYidDESCLIMIT500,10;…10rowsinset(0.05sec)yejr@imysql.comSELECT*FROM`t1`WHEREftype=6ORDERBYidDESCLIMIT935500,10;…10rowsinset(2.39sec)可以看到,随着分页数量的增加,SQL查询耗时也有数十倍增加,显然不科学。今天我们就来分析下,如何能优化这个分页方案。一般滴,想要优化分页的终极方案就是:没有分页,哈哈哈~~~,不要说我讲废话,确实如此,可以把分页算法交给Sphinx、Lucence等第三方解决方案,没必要让MySQL来做它不擅长的事情。当然了,有小伙伴说,用第三方太麻烦了,我们就想用MySQL来做这个分页,咋办呢?莫急,且待我们慢慢分析,先看下表DDL、数据量、查询SQL的执行计划等信息:yejr@imysql.comSHOWCREATETABLE`t1`;CREATETABLE`t1`(`id`int(10)unsignedNOTNULLAUTO_INCREMENT,...`ftype`tinyint(3)unsignedNOTNULL,(`id`))ENGINE=InnoDBDEFAULTCHARSET=utf8;yejr@imysql.comselectcount(*)fromt1;+----------+|count(*)|+----------+|994584|+----------+yejr@imysql.comEXPLAINSELECT*FROM`t1`WHEREftype=1ORDERBYidDESCLIMIT500,10\G***************************1.row***************************id:1select_type:SIMPLEtable:t1type:indexpossible_keys:NULLkey:PRIMARYkey_len:4ref:NULLrows:510Extra:Usingwhereyejr@imysql.comEXPLAINSELECT*FROM`t1`WHEREftype=1ORDERBYidDESCLIMIT935500,10\G***************************1.row***************************id:1select_type:SIMPLEtable:t1type:indexpossible_keys:NULLkey:PRIMARYkey_len:4ref:NULLrows:935510Extra:Usingwhere可以看到,虽然通过主键索引进行扫描了,但第二个SQL需要扫描的记录数太大了,而且需要先扫描约935510条记录,然后再根据排序结果取10条记录,这肯定是非常慢了。针对这种情况,我们的优化思路就比较清晰了,有两点:、尽可能从索引中直接获取数据,避免或减少直接扫描行数据的频率2、尽可能减少扫描的记录数,也就是先确定起始的范围,再往后取N条记录即可据此,我们有两种相应的改写方法:子查询、表连接,即下面这样的:#采用子查询的方式优化,在子查询里先从索引获取到最大id,然后倒序排,再取10行结果集#注意这里采用了2次倒序排,因此在取LIMIT的start值时,比原来的值加了10,即935510,否则结果将和原来的不一致yejr@imysql.comEXPLAINSELECT*FROM(SELECT*FROM`t1`WHEREid(SELECTidFROM`t1`WHEREftype=1ORDERBYidDESCLIMIT935510,1)LIMIT10)tORDERBYidDESC\G***************************1.row***************************id:1select_type:PRIMARYtable:derived2type:ALLpossible_keys:NULLkey:NULLkey_len:NULLref:NULLrows:10Extra:Usingfilesort***************************2.row***************************id:2select_type:DERIVEDtable:t1type:ALLpossible_keys:PRIMARYkey:NULLkey_len:NULLref:NULLrows:973192Extra:Usingwhere***************************3.row***************************id:3select_type:SUBQUERYtable:t1type:indexpossible_keys:NULLkey:PRIMARYkey_len:4ref:NULLrows:935511Extra:Usingwhere采用INNERJOIN优化,JOIN子句里也优先从索引获取ID列表,然后直接关联查询获得最终结果,这里不需要加10yejr@imysql.comEXPLAINSELECT*FROM`t1`INNERJOIN(SELECTidFROM`t1`WHEREftype=1ORDERBYidDESCLIMIT935500,10)t2USING(id)\G***************************1.row***************************id:1select_type:PRIMARYtable:derived2type:ALLpossible_keys:NULLkey:NULLkey_len:NULLref:NULLrows:935510Extra:NULL***************************2.row***************************id:1select_type:PRIMARYtable:t1type:eq_refpossible_keys:PRIMARYkey:PRIMARYkey_len:4ref:t2.idrows:1Extra:NULL***************************3.row***************************id:2select_type:DERIVEDtable:t1type:indexpossible_keys:NULLkey:PRIMARYkey_len:4ref:NULLrows:973192Extra:Usingwhere然后我们来对比下这2个优化后的新SQL执行时间:@imysql.comSELECT*FROM(SELECT*FROM`t1`WHEREid(SELECTidFROM`t1`WHEREftype=1ORDERBYidDESCLIMIT935510,1)LIMIT10)TORDERBYidDESC;...rowsinset(1.86sec)#采用子查询优化,从profiling的结果来看,相比原来的那个SQL快了:28.2%yejr@imysql.comSELECT*FROM`t1`INNERJOIN(SELECTidFROM`t1`WHEREftype=1ORDERBYidDESCLIMIT935500,10)t2USING(id);...10rowsinset(1.83sec)#采用INNERJOIN优化,从profiling的结果来看,相比原来的那个SQL快了:30.8%我们再来看一个不带过滤条件的分页SQL对比:#原始SQLyejr@imysql.comEXPLAINSELECT*FROM`t1`ORDERBYidDESCLIMIT935500,10\G***************************1.row***************************id:1select_type:SIMPLEtable:t1type:indexpossible_keys:NULLkey:PRIMARYkey_len:4ref:NULLrows:935510Extra:NULLyejr@imysql.comSELECT*FROM`t1`ORDERBYidDESCLIMIT935500,10;...10rowsinset(2.22sec)#采用子查询优化yejr@imysql.comEXPLAINSELECT*FROM(SELECT*FROM`t1`WHEREid(SELECTidFROM`t1`ORDERBYidDESCLIMIT935510,1)LIMIT10)tORDERBYidDESC;***************************1.row***************************id:1select_type:PRIMARYtable:derived2type:ALL:NULLkey_len:NULLref:NULLrows:10Extra:Usingfilesort***************************2.row***************************id:2select_type:DERIVEDtable:t1type:ALLpossible_keys:PRIMARYkey:NULLkey_len:NULLref:NULLrows:973192Extra:Usingwhere***************************3.row***************************id:3select_type:SUBQUERYtable:t1type:indexpossible_keys:NULLkey:PRIMARYkey_len:4ref:NULLrows:935511Extra:Usingindexyejr@imysql.comSELECT*FROM(SELECT*FROM`t1`WHEREid(SELECTidFROM`t1`ORDERBYidDESCLIMIT935510,1)LIMIT10)tORDERBYidDESC;…10rowsinset(2.01sec)#采用子查询优化,从profiling的结果来看,相比原来的那个SQL快了:10.6%#采用INNERJOIN优化yejr@imysql.comEXPLAINSELECT*FROM`t1`INNERJOIN(SELECTidFROM`t1`ORDERBYidDESCLIMIT935500,10)t2USING(id)\G***************************1.row***************************id:1sel
本文标题:MySQL分页优化实测效果明显
链接地址:https://www.777doc.com/doc-2889275 .html