MySQL查询优化explain 电脑资料_第1页
MySQL查询优化explain 电脑资料_第2页
MySQL查询优化explain 电脑资料_第3页
MySQL查询优化explain 电脑资料_第4页
MySQL查询优化explain 电脑资料_第5页
免费预览已结束,剩余9页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、MySQL查询优化explain -电脑资料2019-01-01在分析査询性能时,考虑EXPLAIN 键字同样很管用,。EXPLAIN关键字一般放在SELECT査询语句的前面,用于描述MySQL如何执行 査询操作.以及MySQL成功返回结果集需要执行的行数。explain可以帮助我 们分析select语句,让我们知道查询效率低下的原因,从而改进我们查询,让查 询优化器能够更好的工作。-X MySQL査询优化器是如何工作的MySQL查询优化器有儿个U标,但是其中最主要的U标是尽可能地使用索 引,并且使用最严格的索引来消除尽可能多的数据行。最终U标是提交SELECT 语句查找数据行,而不是排除数据

2、行。优化器试图排除数据行的原因在于它排除 数据行的速度越快,那么找到与条件匹配的数据行也就越快。如果能够首先进行 最严格的测试,查询就可以执行地更快。EXPLAIN的每个输出行提供一个表的相关信息,并且每个行包括下面的 列:项说明idMySQL Query Optimizer选定的执行中査询的序列号。表示査询中执 行select子句或操作表的顺序,id值越大优先级越高,越先被执行。id相同, 执行顺序山上至下。select_type查询类型说明SIMPLE简单的select查询,不使用union及子查 询PRIMARY最外层的select查询UXIOXUXIOX中的第二个或随后的select

3、查询,不依赖于外部查询的结果集DEPENDENT UXIOXUXIOX中的第二个或随后 的select查询,依 赖于外部查询的结果集SUBQUERY子查询中的第一个 select查询,不依赖于外 部查询的结果集DEPENDENT SUBQUERY子查询中的第 一个select查询,依赖于外部 查询的结果集DERIVED用于from子句里有子 查询的情况。MySQL会递归执行这些子查询,把结果放在临时表里。 UNCACHEABLE SUBQUERY结果集不能被缓存的子査询,必须重新为外 层査询的每 一行进行评估。UNCACHEABLE UNIONUNION中的第二个或随后的select查询, 属

4、 于不可缓存的子查询项说明table输出行所引用的表extra中出现以下2项意味着MYSQL根本不能使用索引,效率会受到重 大影响。应尽可能对此进行优化。extra项说明Using filesort表示MySQL会对结果使用一个外部索引排序,而 不是从表里按索引次序读到相关内容。可能在内存或者磁盘上进行排序。MySQL 中无法利用索引完成的排序操作称为“文件排序” Using temporary表示 MySQL在对查询结果排序时使用临时表。常见于排序order by和分组查询 group by©下面来举一个例子来说明下explain的用法。先来一张表:>CREATE TABLE

5、 IF NOT EXISTS 'article' (、id' int (10) unsignedNOT NULL AUTO_INCREMENT/author_id' int (10) unsigned NOT NULL ,' category_id' ed NOT NULL, commentsnary(255) NOT NULL, content'int(10) unsigned NOT NULL, 'views' int(10) int(lO) unsigned NOT NULL, text NOT NULL, PRIM

6、ARYunsign varbititleKEY ('id')再插儿条数据:>INSERT INTO 'article'(、author_id','category_id',title','content') VALUES(1,1,2,'2'), (1,1,3,3,merits ,2, 2,它);views , comV),(2,需求:查询 category_id 为 1 且 comments 大于 1 article_ido的悄况下 views最多的先查查试试看:>EXPLAINSELE

7、CT author_idFROM 'article'WHERE comments >1ORDER BY views DESCLIMIT 1Gcategory_id =1 AND看看部分输出结果:1 row * select_type: SIMPLEtabtype: ALLpossible_keys: NULL key_len:rows:3filesortl row in set (0.00kIm kImkImkImkImkIm/ vVv vVv rVv rVvrVv rVv vVv rVv rVvrVv rVv vVv rVv rVvrVv rVv vVvid: 1SIM

8、PLEle:articleef:NULLre:Usingkey: NULLNULLrExtra: Using whe很显然,type是ALL,即最坏的情况。Extra里还出现了 Using filesort,也是最坏的况。优化是必须的。嗯,那么最简单的解决方案就是加索引了。好,我们来试一试。查询的条 件里即where之后共使用了 category_id, comments, views三个字段。那么来 一个联合索引是最简单的了。>ALTER TABLE ' article' ADD INDEX x ('category_id' ,'comments

9、','views' );结果有了一定好转,但仍然很糟糕:LI r>kIm kIm kImj/rI F fl UL*vVv rVv vVvid: 1 select_type: SIMPLEtype: rangepossible_keys:key_len: 8Extra: Usingle:articlekey:ngfilesortlrows:1row in set (0.00 secXref: where;NULUsiUsingtype变成了 range,这是可以忍受的。但是extra里使用 filesort仍是无法接受的。但是我们已经建立了索引,为啥没用呢?这是因为

10、按 照BTree索引的工作原理,先排序category_id,如果遇到相同的category_id 则再排序comments,如果遇到相同的comments则再排序viewso当comments 字段在联合索引里处于中间位置时,因comments > 1条件是一个范H值(所谓 range),MySQL无法利用索引再对后面的views部分进行检索,即range类型 查询字段后面的索引无效。那么我们需要抛弃comments,删除旧索引:> DROP INDEX X ON article:然后建立新索引:>ALTER TABLE 'article' ADD INDE

11、X ycategory_idviews接着再运行査询:)>*1. rowid: 1 select_type: SIMPLE type: refpossible_keys: key_len: 4rows:le: article key: yin set (0.00seckIm kIm kImkIm kIm kImkIm kIm kImvVv rVv rVv rVv vVv rVvrVv rVv rVv rVv vVv rVv rVv rVv rVv rVv vVv rVv rVv rVvtabExtra: Usingy ref: where1constrow显然第一个ALL是需要我们进行优

12、化的。可以看到,type 变为了 ref, Extra 中的 Using filesort 果非常理想。也消失了,结再来看一个多表查询的例子。首先定义3个表class和room。class' (、id' int (10) int (10) unsigned NOT book'>CREATE TABLE IF NOT EXISTS OT NULL AUTO.INCREMENT, ' card'KEY ('id'):CREATE TABLE IF NOT EXISTS(10) unsigned NOT NULL AUTO.INCREME

13、NT, 'card'unsigned N NULL, PRIMARY ('bookid' int int (10) unsignedNOT NULL. PRIMARY KEY ('bookid'):CREATE TABLE IF NOT EXISTS ' phone' ('phoneid' int(10) unsigned NOT NULL AUTO.INCREMENT, ' d' int(10) unsigned NOT NULL, PRIMARY KEY ('phoneid')

14、=innodb:carengine然后再分别插入大量数据。插入数据的php脚本:mysqlconnect("localhost", "root", "870516"):mysql_selec $j= rand(l,” insert into class(card) values($j)"$j= ran<?php$link t_db("test", $link):for($i=0:$i<10000:$i+) 20);$sqlmysql_query($sql):for($i=0:$i<100

15、00:$i+) d(l,20);$sql =”mysql_query($sql):for($i=0:$i<10000:$i+) $sqlinsert into book(card) values($j)"$j 二 rand(1,20);$sql =" insert into phone(card) values($j)"mysql_query($sql) ;inysql_query("COMMIT") :?>然后来看一个左连接查询:explain select * from class left join book on class

16、, card book. cardG分析结果是:)>*1. row1 select_type: SIMPLE type: ALLpossible_keys: NULL key_len: NULL rows:20000Extra:row *SIMPLEtable: bookk ref: NULL Extra: 2 rows in set (id:le: classkey: NULL:NULLkIm kImkIm kImkIm kIm JrVv vVv rVv rVv rVv vVv rVv rVv rVv/id:kIm kImkIm kIm kIm kImkImkIm kIm kIm kI

17、m kImkIm kIm kIm kImkImrVv rVv rVv vVv rVv rVvrVv rVv rVv rVv rVv rVv rVv rVv rVv rVv rVv rVvrVv rVv rVvtabrefkImkImvVv vVv rVv rVv rVv vVv1 select_type: type: ALLpossible_keys: NULL key_len: NULL rows:20000建立个索引试试看:>ALTER TABLE 'book' ADD INDEX y >*1. row1 select_type: SIMPLE type: AL

18、Lpossible_keys: NULL key_len: NULLrows:20000Extra:row *table: book key: test, class, card2 rows in setid:le: class key: NULL:NULLkImkIm kIm kIm kImkImkIm kIm kIm kImkImkIm JrVv rVv vVv rVv rVv rVv rVv rVv rVv rVv rVv rVv rVv rVv rVv/( card );kImrVvrVv vVv rVvrVvrVv vVv rVvrVvrVv vVv rVvrVvtabrefkIm

19、kIm kIm rVv rVv rVv rVv rVvid: 1 select_type: SIMPLEtype: refpossible_keys: y key_len: 4ref:rows: 1000Extra:(0.00 sec可以看到第二行的type变为了 ref, rows也变成了 1741*1 &优化比较 明显。这是山左连接特性决定的。LEFT JOIN条件用于确定如何从右表搜索行, 左边一定都有,所以右边是我们的关键点,一定需要建立索引。删除旧索引:>DROP INDEX y ON book:建立新索引。>ALTER TABLE 'class'

20、 ADD INDEX x ( 'card'):结果>*水*水*1. row1select_type: SIMPLEtype: ALLpossible_keys: NULL key_len: NULL rows: 20000Extra:row *id:kIm kImkIm kImkIm kImrVv rVv rVvrVv rVv rVvrVv rVv rVvrVvtable: classkey: NULL:NULLkImkIm frVv rVv vVv rVv rVv rVv rVv vVv rVv rVv rVv rVv vVv /id:refkIm kIm kIm kI

21、m rVv rVv rVv rVv rVvey: NULL1select_type: SIMPLEtable: booktype: ALLpossible_keys: NULLkkey_l en: NULLref: NULLrows: 20000Extra: 2 rows in set (0.00 sec基本无变化,0。然后来看一个右连接査询:>explain select * from class right join book on class, card =book, card:分析结果是:>*1. row1 select_type: SIMPLE type: ALLposs

22、ible_keys: NULL key_len: NULLrows:20000Extra:row *table: class key: test. book, card2 rows in setid:le: bookkey: NULLNULLkImkIm kIm kImkIm kIm kIm JvVv rVv rVv rVv vVv rVv rVv rVv rVv rVv vVv rVv rVv rVv/kImrVvrVv vVv rVvrVvrVv vVv rVvrVvrVv vVv rVvrVvtabref:kIm kIm rVv rVv rVv rVvid: 1 select_type:

23、 SIMPLEtype: refpossible_keys: x key_len: 4ref:rows: 1000Extra:(0.00 sec优化较明显。这是因为RIGHT JOIN条件用于确定如何从左表搜索行,右 边一定都有,所以左边是我们的关键点,一定需要建立索引。删除旧索引:>DR0P INDEX X ON class:建立新索引。>ALTER TABLE 'book' ADD INDEX y ( 'card');结果>*1. row1select_type: SIMPLEtype: ALLpossible_keys: NULL key

24、_len: NULL rows: 20000Extra:row *id:kImrVvrVv vVv rVvrVvrVv vVv rVvrVvrVv vVv rVvrVvtable: classkey: NULL:NULLkIm kIm kIm kIm kIm kIm kIm kIm kIm kIm kIm kIm f rVv rVv vVv rVv rVv rVv rVv rVv rVv rVv rVv rVv rVv rVv rVv /id:refkIm kIm kIm rVv rVv rVv rVv rVv1select_type: SIMPLEtable: booktype: ALLpo

25、ssible_keys: NULLkkey_l en: NULLref: NULLrows: 20000Extra: 2 rows in set (基本无变化。最后来看看inner join的1W况:>explain select * from class inner join book on class, card =book, card:结果:)>*1. row1 select_type: SIMPLEtype: ALLpossible_keys: NULLkey_len: NULLrows:20000le: bookkey: NULLNULLid:kIm kImkIm kIm

26、 kIm kImkImkIm kIm kIm kIm kImkIm kIm kIm kImkImrVv rVv rVv vVv rVv rVvrVv rVv rVv rVv rVv rVv rVv rVv rVv rVv rVv rVvrVv rVv rVvtabExtra:ref:kImkIm kImrVv rVv rVv vVvkIm kImkIm kImkIm kIm JrVv vVv rVv rVv rVv vVv rVv rVv rVv/id: 1 select_type: SIMPLEtype: refpossible_keys: xkey_len: 4ref:rows: 1000

27、Extra:row *table: class key: test. book, card2 rows in set(0. 00sec删除旧索引:>DR0PINDEX y ON book:结果)>*1. row1 select_type: SIMPLE type: ALLpossible_keys: NULL key_len: NULL rows:20000id:le: classkey: NULL:NULLkImkImkImrVv rVv rVvrVvrVv rVvrVvrVv rVvrVv rVvrVvtabExtra:refkIm kIm kIm kIm rVv rVv rV

28、v rVv rVvkImkIm kIm kIm kImkImkIm kIm kIm kImkImkIm JrVv rVv vVv rVv rVv rVv rVv rVv rVv rVv rVv rVv rVv rVv rVv/id: 1 select_type: SIMPLEtype: ALLpossible_keys: NULL key_len: NULLrows:20000ey: NULLrow *table: book k ref: NULL rows in set (Extra: 20.00 sec建立新索引。>ALTER TABLE 'class' ADD IN

29、DEX x( card );结果)>*1. rowid:kImkImkImkImrVv vVv rVv vVv vVv rVv rVv rVv vVv vVv rVv rVv rVv vVv vVv rVv rVv rVvselect_type: SIMPLEtable: class key: NULL:NULLkIm kImkIm kImkIm JrVv rVv rVvrVv rVv rVvrVv rVv /type: ALLpossible_keys: NULLkey_len: NULLrefrows: 20000Extra: *row 水水*SIMPLEtable: bookkid

30、: 1 select_type:type: ALLpossible_keys: NULL key_len: NULL rows:20000ey: NULLref: NULLExtra: 2 rows in set (0.00 sec综上所述 inner join和left join差不多,都需要优化右表。而 right join需要优化左表©我们再来看看三表査询的例子 添加一个新索引:('card');ALTER TABLE 'book>ALTER TABLE 'phone' ADD INDEX z' ADD INDEX y ( 'card'):row1 select_type: SIMPLE type: ALLpossible_keys: NULL key_len:

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论