搜索
首页数据库mysql教程mysql explain解析_MySQL

explain显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。

先解析一条sql语句,看出现什么内容

EXPLAIN SELECTs.uid,s.username,s.name,f.email,f.mobile,f.phone,f.postalcode,f.address FROM uchome_space AS s,uchome_spacefield AS f<br> WHERE 1<br> AND s.groupid=0<br> AND s.uid=f.uid<br> <code class="sql"><img src="/static/imghwm/default1.png" data-src="http://img.bitscn.com/upimg/allimg/c150410/142V3FN3Z60-153V.jpg" class="lazy" alt="\">

<code class="sql"><strong>1. id</strong>

<code class="sql">SELECT识别符。这是SELECT查询序列号。这个不重要,查询序号即为sql语句执行的顺序,看下面这条sql

<code class="sql"><code class="sql">EXPLAIN SELECT * FROM(SELECT* FROMuchome_space LIMIT10)AS s

<code class="sql"><code class="sql">它的执行结果为

<code class="sql"><code class="sql"><img src="/static/imghwm/default1.png" data-src="http://img.bitscn.com/upimg/allimg/c150410/142V3FN593P-2CT.jpg" class="lazy" alt="\">

<code class="sql"><code class="sql">可以看到这时的id变化了

<code class="sql"><code class="sql"><strong>2.select_type</strong>

<code class="sql"><code class="sql">select类型,它有以下几种值

<code class="sql"><code class="sql">2.1 simple: 它表示简单的select,没有union和子查询

<code class="sql"><code class="sql">2.2 primary :最外面的select,在有子查询的语句中,最外面的select查询就是primary,上图中就是这样

<code class="sql"><code class="sql">2.3 union :举例,

<code class="sql"><code class="sql">explain select * from uchome_space limit 10 union select * from uchome_space limit 10,10

<code class="sql"><code class="sql">会有如下结果,第二条语句使用了union

<code class="sql"><code class="sql"><img src="/static/imghwm/default1.png" data-src="http://img.bitscn.com/upimg/allimg/c150410/142V3FNK0-33b1.jpg" class="lazy" alt="\">

 

<code class="sql"><code class="sql">2.4 dependent union UNION中的第二个或后面的SELECT语句,取决于外面的查询

<code class="sql"><code class="sql">2.5 union result UNION的结果,如上面所示

<code class="sql"><code class="sql">2.6 derived: 派生表 select(from子句中的子查询)

<code class="sql"><code class="sql">还有几个参数,这里就不说了,不重要

<code class="sql"><code class="sql"><strong>3 table</strong>

<code class="sql"><code class="sql">输出的行所用的表,这个参数显而易见,容易理解

<code class="sql"><code class="sql"><strong>4 type</strong>

<code class="sql"><code class="sql">连接类型。有多个参数,先从最佳类型到最差类型介绍 <strong>重要且困难</strong>

<code class="sql"><code class="sql">4.1 system

<code class="sql"><code class="sql">表仅有一行,这是const类型的特列,平时不会出现,这个也可以忽略不计

<code class="sql"><code class="sql">4.2 const

<code class="sql"><code class="sql">表最多有一个匹配行,const用于比较primary key 或者unique索引。因为只匹配一行数据,所以很快

<code class="sql"><code class="sql">记住一定是用到primary key 或者unique,并且只检索出两条数据的 情况下才会是const,看下面这条语句

<code class="sql"><code class="sql">explain SELECT * FROM `asj_admin_log` limit 1,结果是

<code class="sql"><code class="sql"><img src="/static/imghwm/default1.png" data-src="http://img.bitscn.com/upimg/allimg/c150410/142V3FNZ620-42263.jpg" class="lazy" alt="\">

<code class="sql"><code class="sql">虽然只搜索一条数据,但是因为没有用到指定的索引,所以不会使用const.继续看下面这个

<code class="sql"><code class="sql">explain SELECT * FROM `asj_admin_log` where log_id = 111

<code class="sql"><code class="sql"><img src="/static/imghwm/default1.png" data-src="http://img.bitscn.com/upimg/allimg/c150410/142V3FO04E0-53117.jpg" class="lazy" alt="\">

<code class="sql"><code class="sql">log_id是主键,所以使用了const。所以说可以理解为const是最优化的

<code class="sql"><code class="sql">4.3 eq_ref

<code class="sql"><code class="sql">对于eq_ref的解释,mysql手册是这样说的:"对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。它用在一个索引的所有部分被联接使用并且索引是UNIQUE或PRIMARY KEY"。eq_ref可以用于使用=比较带索引的列。看下面的语句

<code class="sql"><code class="sql">explain select * from uchome_spacefield,uchome_space where uchome_spacefield.uid = uchome_space.uid

<code class="sql"><code class="sql">得到的结果是下图所示。很明显,mysql使用eq_ref联接来处理uchome_space表。

<code class="sql"><code class="sql"><img src="/static/imghwm/default1.png" data-src="http://img.bitscn.com/upimg/allimg/c150410/142V3FO21X0-64295.jpg" class="lazy" alt="\">

<code class="sql"><code class="sql">目前的疑问:

<code class="sql"><code class="sql">4.3.1 为什么是只有uchome_space一个表用到了eq_ref,并且sql语句如果变成

<code class="sql"><code class="sql">explain select * from uchome_space,uchome_spacefield where uchome_space.uid = uchome_spacefield.uid

<code class="sql"><code class="sql">结果还是一样,需要说明的是uid在这两个表中都是primary

<code class="sql"><code class="sql">4.4 ref 对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。如果联接只使用键的最左边的前缀,或如果键不是UNIQUE或PRIMARY KEY(换句话说,如果联接不能基于关键字选择单个行的话),则使用ref。如果使用的键仅仅匹配少量行,该联接类型是不错的。

<code class="sql"><code class="sql">看下面这条语句 explain select * from uchome_space where uchome_space.friendnum = 0,得到结果如下,这条语句能搜出1w条数据

<code class="sql"><code class="sql"><img src="/static/imghwm/default1.png" data-src="http://img.bitscn.com/upimg/allimg/c150410/142V3FO3K0-H955.jpg" class="lazy" alt="\">

<code class="sql"><code class="sql">4.5 ref_or_null 该联接类型如同ref,但是添加了MySQL可以专门搜索包含NULL值的行。在解决子查询中经常使用该联接类型的优化。

<code class="sql"><code class="sql">上面这五种情况都是很理想的索引使用情况

<code class="sql"><code class="sql">4.6 index_merge 该联接类型表示使用了索引合并优化方法。在这种情况下,key列包含了使用的索引的清单,key_len包含了使用的索引的最长的关键元素。

<code class="sql"><code class="sql">4.7 unique_subquery

<code class="sql"><code class="sql">4.8 index_subquery

<code class="sql"><code class="sql">4.9 range 给定范围内的检索,使用一个索引来检查行。看下面两条语句

<code class="sql"><code class="sql">explain select * from uchome_space where uid in (1,2)

<code class="sql"><code class="sql">explain select * from uchome_space where groupid in (1,2)

<code class="sql"><code class="sql">uid有索引,groupid没有索引,结果是第一条语句的联接类型是range,第二个是ALL.以为是一定范围所以说像 between也可以这种联接,很明显

<code class="sql"><code class="sql">explain select * from uchome_space where friendnum = 17

<code class="sql"><code class="sql">这样的语句是不会使用range的,它会使用更好的联接类型就是上面介绍的ref

<code class="sql"><code class="sql">4.10 index 该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。(也就是说虽然all和Index都是读全表,但index是从索引中读取的,而all是从硬盘中读的)

<code class="sql"><code class="sql">当查询只使用作为单索引一部分的列时,MySQL可以使用该联接类型。

<code class="sql"><code class="sql">4.11 ALL 对于每个来自于先前的表的行组合,进行完整的表扫描。如果表是第一个没标记const的表,这通常不好,并且通常在它情况下<em>很</em>差。通常可以增加更多的索引而不要使用ALL,使得行能基于前面的表中的常数值或列值被检索出。

<code class="sql"><code class="sql"><strong>5 possible_keys</strong> 提示使用哪个索引会在该表中找到行,不太重要

<code class="sql"><code class="sql"><strong>6 keys</strong> MYSQL使用的索引,简单且重要

<code class="sql"><code class="sql"><strong>7 key_len</strong> MYSQL使用的索引长度

<code class="sql"><code class="sql"><strong>8 ref </strong>ref列显示使用哪个列或常数与key一起从表中选择行。

<code class="sql"><code class="sql"><strong>9 rows</strong> 显示MYSQL执行查询的行数,简单且重要,数值越大越不好,说明没有用好索引

<code class="sql"><code class="sql"><strong>10 Extra</strong> 该列包含MySQL解决查询的详细信息。

<code class="sql"><code class="sql">10.1 Distinct MySQL发现第1个匹配行后,停止为当前的行组合搜索更多的行。一直没见过这个值

<code class="sql"><code class="sql">10.2 Not exists

<code class="sql"><code class="sql">10.3 range checked for each record

<code class="sql"><code class="sql">没有找到合适的索引

<code class="sql"><code class="sql">10.4 using filesort

<code class="sql"><code class="sql">MYSQL手册是这么解释的“MySQL需要额外的一次传递,以找出如何按排序顺序检索行。通过根据联接类型浏览所有行并为所有匹配WHERE子句的行保存排序关键字和行的指针来完成排序。然后关键字被排序,并按排序顺序检索行。”目前不太明白

<code class="sql"><code class="sql">10.5 using index 只使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的信息。这个比较容易理解,就是说明是否使用了索引

<code class="sql"><code class="sql">explain select * from ucspace_uchome where uid = 1的extra为using index(uid建有索引)

<code class="sql"><code class="sql">explain select count(*) from uchome_space where groupid=1 的extra为using where(groupid未建立索引)

<code class="sql"><code class="sql">10.6 using temporary

<code class="sql"><code class="sql">为了解决查询,MySQL需要创建一个临时表来容纳结果。典型情况如查询包含可以按不同情况列出列的GROUP BY和ORDER BY子句时。

<code class="sql"><code class="sql">出现using temporary就说明语句需要优化了,举个例子来说

<code class="sql"><code class="sql">EXPLAIN SELECT ads.id FROM <strong>ads</strong>, city WHERE city.city_id = 8005 AND ads.status = 'online' AND city.ads_id=ads.id<strong> ORDER BY ads.id desc</strong>

<code class="sql"><code class="sql"><strong>id select_type table type possible_keys key key_len ref rows filtered Extra<br> ------ ----------- ------ ------ -------------- ------- ------- -------------------- ------ -------- -------------------------------<br> 1 SIMPLE <strong>city </strong> ref ads_id,city_id city_id 4 const 2838 100.00 <strong>Using temporary</strong>; Using filesort<br> 1 SIMPLE ads eq_ref PRIMARY PRIMARY 4 city.ads_id 1 100.00 Using where </strong>
 

<code class="sql"><code class="sql"><strong>这条语句会使用using temporary,而下面这条语句则不会</strong>

 

<code class="sql"><code class="sql">EXPLAIN SELECT ads.id FROM <strong>ads</strong>, city WHERE city.city_id = 8005 AND ads.status = 'online' AND city.ads_id=ads.id<strong> ORDER BY city.ads_id desc</strong>

<code class="sql"><code class="sql"><strong>id select_type table type possible_keys key key_len ref rows filtered Extra<br> ------ ----------- ------ ------ -------------- ------- ------- -------------------- ------ -------- ---------------------------<br> 1 SIMPLE <strong>city </strong> ref ads_id,city_id city_id 4 const 2838 100.00 <strong>Using where; Using filesort</strong><br> 1 SIMPLE ads eq_ref PRIMARY PRIMARY 4 city.ads_id 1 100.00 Using where </strong>
 

<code class="sql"><code class="sql">这是为什么呢?他俩之间只是一个order by不同,MySQL 表关联的算法是 Nest Loop Join,是通过驱动表的结果集作为循环基础数据,然后一条一条地通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果。EXPLAIN 结果中,第一行出现的表就是驱动表(Important!)以上两个查询语句,驱动表都是 city,如上面的执行计划所示!

<code class="sql"><code class="sql">对驱动表可以直接排序,对非驱动表(的字段排序)需要对循环查询的合并结果(临时表)进行排序(Important!) 因此,order by ads.id desc 时,就要先 using temporary 了! 驱动表的定义 wwh999 在 2006年总结说,当进行多表连接查询时, [驱动表] 的定义为:<br> 1)指定了联接条件时,满足查询条件的记录行数少的表为[驱动表];<br> 2)未指定联接条件时,行数少的表为[驱动表](Important!)。 <strong><strong>永远用小结果集驱动大结果集</strong></strong>

 

<code class="sql"><code class="sql"><strong>今天学到了一个很重要的一点:当不确定是用哪种类型的join时,让mysql优化器自动去判断,我们只需写select * from t1,t2 where t1.field = t2.field</strong>

<code class="sql"><code class="sql">10.7 using where

<code class="sql"><code class="sql">WHERE子句用于限制哪一个行匹配下一个表或发送到客户。除非你专门从表中索取或检查所有行,如果Extra值不为Using where并且表联接类型为ALL或index,查询可能会有一些错误。(这个说明不是很理解,因为很多很多语句都会有where条件,而type为all或index只能说明检索的数据多,并不能说明错误,useing where不是很重要,但是很常见)

<code class="sql"><code class="sql">如果想要使查询尽可能快,应找出Using filesort 和Using temporary的Extra值。

<code class="sql"><code class="sql">10.8 Using sort_union(...), Using union(...),Using intersect(...)

<code class="sql"><code class="sql">这些函数说明如何为index_merge联接类型合并索引扫描

<code class="sql"><code class="sql">10.9 Using index for group-by

<code class="sql"><code class="sql">类似于访问表的Using index方式,Using index for group-by表示MySQL发现了一个索引,可以用来查询GROUP BY或DISTINCT查询的所有列,而不要额外搜索硬盘访问实际的表。并且,按最有效的方式使用索引,以便对于每个组,只读取少量索引条目。

<code class="sql"><code class="sql">实例讲解

 

<code class="sql"><code class="sql">通过相乘EXPLAIN输出的rows列的所有值,你能得到一个关于一个联接如何的提示。这应该粗略地告诉你<strong>MySQL</strong>必须检查多少行以执行查询。当你使用max_join_size变量限制查询时,也用这个乘积来确定执行哪个多表SELECT语句。

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
您什么时候应该使用复合索引与多个单列索引?您什么时候应该使用复合索引与多个单列索引?Apr 11, 2025 am 12:06 AM

在数据库优化中,应根据查询需求选择索引策略:1.当查询涉及多个列且条件顺序固定时,使用复合索引;2.当查询涉及多个列但条件顺序不固定时,使用多个单列索引。复合索引适用于优化多列查询,单列索引则适合单列查询。

如何识别和优化MySQL中的慢速查询? (慢查询日志,performance_schema)如何识别和优化MySQL中的慢速查询? (慢查询日志,performance_schema)Apr 10, 2025 am 09:36 AM

要优化MySQL慢查询,需使用slowquerylog和performance_schema:1.启用slowquerylog并设置阈值,记录慢查询;2.利用performance_schema分析查询执行细节,找出性能瓶颈并优化。

MySQL和SQL:开发人员的基本技能MySQL和SQL:开发人员的基本技能Apr 10, 2025 am 09:30 AM

MySQL和SQL是开发者必备技能。1.MySQL是开源的关系型数据库管理系统,SQL是用于管理和操作数据库的标准语言。2.MySQL通过高效的数据存储和检索功能支持多种存储引擎,SQL通过简单语句完成复杂数据操作。3.使用示例包括基本查询和高级查询,如按条件过滤和排序。4.常见错误包括语法错误和性能问题,可通过检查SQL语句和使用EXPLAIN命令优化。5.性能优化技巧包括使用索引、避免全表扫描、优化JOIN操作和提升代码可读性。

描述MySQL异步主奴隶复制过程。描述MySQL异步主奴隶复制过程。Apr 10, 2025 am 09:30 AM

MySQL异步主从复制通过binlog实现数据同步,提升读性能和高可用性。1)主服务器记录变更到binlog;2)从服务器通过I/O线程读取binlog;3)从服务器的SQL线程应用binlog同步数据。

mysql:简单的概念,用于轻松学习mysql:简单的概念,用于轻松学习Apr 10, 2025 am 09:29 AM

MySQL是一个开源的关系型数据库管理系统。1)创建数据库和表:使用CREATEDATABASE和CREATETABLE命令。2)基本操作:INSERT、UPDATE、DELETE和SELECT。3)高级操作:JOIN、子查询和事务处理。4)调试技巧:检查语法、数据类型和权限。5)优化建议:使用索引、避免SELECT*和使用事务。

MySQL:数据库的用户友好介绍MySQL:数据库的用户友好介绍Apr 10, 2025 am 09:27 AM

MySQL的安装和基本操作包括:1.下载并安装MySQL,设置根用户密码;2.使用SQL命令创建数据库和表,如CREATEDATABASE和CREATETABLE;3.执行CRUD操作,使用INSERT,SELECT,UPDATE,DELETE命令;4.创建索引和存储过程以优化性能和实现复杂逻辑。通过这些步骤,你可以从零开始构建和管理MySQL数据库。

InnoDB缓冲池如何工作,为什么对性能至关重要?InnoDB缓冲池如何工作,为什么对性能至关重要?Apr 09, 2025 am 12:12 AM

InnoDBBufferPool通过将数据和索引页加载到内存中来提升MySQL数据库的性能。1)数据页加载到BufferPool中,减少磁盘I/O。2)脏页被标记并定期刷新到磁盘。3)LRU算法管理数据页淘汰。4)预读机制提前加载可能需要的数据页。

MySQL:初学者的数据管理易用性MySQL:初学者的数据管理易用性Apr 09, 2025 am 12:07 AM

MySQL适合初学者使用,因为它安装简单、功能强大且易于管理数据。1.安装和配置简单,适用于多种操作系统。2.支持基本操作如创建数据库和表、插入、查询、更新和删除数据。3.提供高级功能如JOIN操作和子查询。4.可以通过索引、查询优化和分表分区来提升性能。5.支持备份、恢复和安全措施,确保数据的安全和一致性。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器