




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、MySQL分页优化通常,我们会采用ORDER BY LIMIT start, offset 的方式来进行分页查询。例如下面这个SQL:SELECT * FROM t1 WHERE ftype=1 ORDER BY id DESC LIMIT 100, 10;或者像下面这个不带任何条件的分页SQL:SELECT * FROM t1 ORDER BY id DESC LIMIT 100, 10;一般而言,分页SQL的耗时随着 start 值的增加而急剧增加,我们来看下面这2个不同起始值的分页SQL执行耗时: SELECT * FROM t1 WHERE ftype=1
2、ORDER BY id DESC LIMIT 500, 10;10 rows in set (0.05 sec) SELECT * FROM t1 WHERE ftype=6 ORDER BY id DESC LIMIT , 10;10 rows in set (2.39 sec)可以看到,随着分页数量的增加,SQL查询耗时也有数十倍增加,显然不科学。今天我们就来分析下,如何能优化这个分页方案。 一般滴,想要优化分页的终极方案就是:没有分页,哈哈哈,不要说我讲废话,确实如此,可以把分页算法交给Sphinx、Lucence等第三方解决方案,没必要让MySQL来做它不擅
3、长的事情。 当然了,有小伙伴说,用第三方太麻烦了,我们就想用MySQL来做这个分页,咋办呢?莫急,且待我们慢慢分析,先看下表DDL、数据量、查询SQL的执行计划等信息: SHOW CREATE TABLE t1;CREATE TABLE t1 ( id int(10) unsigned NOT NULL AUTO_INCREMENT,. ftype tinyint(3) unsigned NOT NULL,. PRIMARY KEY (id) ENGINE=InnoDB DEFAULT CHARSET=utf8;select count(
4、*) from t1;+-+| count(*) |+-+| |+-+EXPLAIN SELECT * FROM t1 WHERE ftype=1 ORDER BY id DESC LIMIT 500, 10G* 1. row * id: 1 select_type: SIMPLE table: t1 type: indexpossible_keys: NULL key: PRIMARY key_len: 4 ref: NULL rows: 510 Extra: Using EXPLAIN SELECT * FROM t1 W
5、HERE ftype=1 ORDER BY id DESC LIMIT , 10G* 1. row * id: 1 select_type: SIMPLE table: t1 type: indexpossible_keys: NULL key: PRIMARY key_len: 4 ref: NULL rows: Extra: Using where可以看到,虽然通过主键索引进行扫描了,但第二个SQL需要扫描的记录数太大了,而且需要先扫描约条记录,然后再根据排序结果取10条记录,这肯定是非常慢了。 针对这种情况,我们的优化思路就比较清晰了,有两点:1、尽可能从索引中直接获取数据,避免或减少直
6、接扫描行数据的频率2、尽可能减少扫描的记录数,也就是先确定起始的范围,再往后取N条记录即可据此,我们有两种相应的改写方法:子查询、表连接,即下面这样的:#采用子查询的方式优化,在子查询里先从索引获取到最大id,然后倒序排,再取10行结果集#注意这里采用了2次倒序排,因此在取LIMIT的start值时,比原来的值加了10,即,否则结果将和原来的不一致 EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE id ( SELECT id FROM t1 WHERE ftype=1 ORDER BY id DESC LIMIT , 1)
7、 LIMIT 10) t ORDER BY id DESCG* 1. row * id: 1 select_type: PRIMARY table: type: ALLpossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 10 Extra: Using filesort* 2. row * id: 2 select_type: DERIVED table: t1 type: ALLpossible_keys: PRIMARY key: NULL key_len: NULL ref: NULL rows: Extra: Using
8、 where* 3. row * id: 3 select_type: SUBQUERY table: t1 type: indexpossible_keys: NULL key: PRIMARY key_len: 4 ref: NULL rows: Extra: Using where#采用INNER JOIN优化,JOIN子句里也优先从索引获取ID列表,然后直接关联查询获得最终结果,这里不需要加10 EXPLAIN SELECT * FROM t1 INNER JOIN ( SELECT id FROM t1 WHERE ftype=1 ORDER BY id
9、DESC LIMIT ,10) t2 USING (id)G* 1. row * id: 1 select_type: PRIMARY table: type: ALLpossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: Extra: NULL* 2. row * id: 1 select_type: PRIMARY table: t1 type: eq_refpossible_keys: PRIMARY key: PRIMARY key_len: 4 ref: t2.id rows: 1 Extra: NULL* 3. row
10、 * id: 2 select_type: DERIVED table: t1 type: indexpossible_keys: NULL key: PRIMARY key_len: 4 ref: NULL rows: Extra: Using where然后我们来对比下这2个优化后的新SQL执行时间: SELECT * FROM (SELECT * FROM t1 WHERE id ( SELECT id FROM t1 WHERE ftype=1 ORDER BY id DESC LIMIT , 1) LIMIT 10) T ORDER BY id DESC;
11、.rows in set (1.86 sec)#采用子查询优化,从profiling的结果来看,相比原来的那个SQL快了:28.2% SELECT * FROM t1 INNER JOIN ( SELECT id FROM t1 WHERE ftype=1 ORDER BY id DESC LIMIT ,10) t2 USING (id);.10 rows in set (1.83 sec)#采用INNER JOIN优化,从profiling的结果来看,相比原来的那个SQL快了:30.8%我们再来看一个不带过滤条件的分页SQL对比:#原始SQLyejrimysql.
12、com EXPLAIN SELECT * FROM t1 ORDER BY id DESC LIMIT , 10G* 1. row * id: 1 select_type: SIMPLE table: t1 type: indexpossible_keys: NULL key: PRIMARY key_len: 4 ref: NULL rows: Extra: NULL SELECT * FROM t1 ORDER BY id DESC LIMIT , 10;.10 rows in set (2.22 sec)#采用子查询优化 EXPLA
13、IN SELECT * FROM (SELECT * FROM t1 WHERE id ( SELECT id FROM t1 ORDER BY id DESC LIMIT , 1) LIMIT 10) t ORDER BY id DESC;* 1. row * id: 1 select_type: PRIMARY table: type: ALLpossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 10 Extra: Using filesort* 2. row * id: 2 select_type: DERIVED tab
14、le: t1 type: ALLpossible_keys: PRIMARY key: NULL key_len: NULL ref: NULL rows: Extra: Using where* 3. row * id: 3 select_type: SUBQUERY table: t1 type: indexpossible_keys: NULL key: PRIMARY key_len: 4 ref: NULL rows: Extra: Using SELECT * FROM (SELECT * FROM t1 WHERE id ( SELECT
15、id FROM t1 ORDER BY id DESC LIMIT , 1) LIMIT 10) t ORDER BY id DESC;10 rows in set (2.01 sec)#采用子查询优化,从profiling的结果来看,相比原来的那个SQL快了:10.6%#采用INNER JOIN优化 EXPLAIN SELECT * FROM t1 INNER JOIN ( SELECT id FROM t1ORDER BY id DESC LIMIT ,10) t2 USING (id)G* 1. row * id: 1 select_type: PRIMARY
16、 table: type: ALLpossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: Extra: NULL* 2. row * id: 1 select_type: PRIMARY table: t1 type: eq_refpossible_keys: PRIMARY key: PRIMARY key_len: 4 ref: t1.id rows: 1 Extra: NULL* 3. row * id: 2 select_type: DERIVED table: t1 type: indexpossible_keys: N
17、ULL key: PRIMARY key_len: 4 ref: NULL rows: Extra: Using SELECT * FROM t1 INNER JOIN ( SELECT id FROM t1ORDER BY id DESC LIMIT ,10) t2 USING (id);10 rows in set (1.70 sec)#采用INNER JOIN优化,从profiling的结果来看,相比原来的那个SQL快了:30.2%至此,我们看到采用子查询或者INNER JOIN进行优化后,都有大幅度的提升,这个方法也同样适用于较小的分页,虽然LIMIT开始的start 位置小了很多,SQL执行时间也快了很多,但采用这种方法后,带WHERE条件的分页分别能提高查询效率:24.9%、156.5%,不带WHERE条件的分页分别提高查询效率:554.5%、11.7%,各位可以自行进行测试验证。单从提升比例说,还是挺可观的,确保这些优化方法可以适用于各种分页模式,就可以从一开始就是用。 我们来看下各种场景相应的提升比例是多少:大分页,带WHERE大分页,不带WHERE大分页
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025商场摊位租赁合同范本
- 2025健身房合作合同范本模板
- 2025合同绩效评估与奖惩机制
- 2025标准版合同租赁协议
- 2025桐乡市茶叶收购合同范本
- 2025劳动合同法律法规要点梳理
- 2024年环磷酰胺原料药项目资金申请报告代可行性研究报告
- 2025年中国合同法范本
- 2025年中国农业银行教育贷款合同范本
- 2025多方协作合同协议范本
- 临床研究样本量计算器 CRESS V1.3
- 直播电商运营实务PPT完整全套教学课件
- 医患沟通技巧培训
- 消化系统药 抗消化性溃疡药 (护用药理学)
- 山东省青岛市第一中学 年自主招生考试数学试题( )
- GB/T 4798.1-1986电工电子产品应用环境条件贮存
- GB/T 20388-2006纺织品邻苯二甲酸酯的测定
- 银行结售汇统计案例分析
- 语文五年级下册教学课件部编版-第六单元 习作:神奇的探险之旅
- 行车吊装作业安全风险分级清单
- 电梯日常巡视记录表(日检查表)
评论
0/150
提交评论