데이터 베이스 MySQL 튜토리얼 mysql explain解析_MySQL

mysql explain解析_MySQL

Jun 01, 2016 pm 01:01 PM

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/imghw/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/imghw/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/imghw/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/imghw/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/imghw/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/imghw/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/imghw/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으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌
Will R.E.P.O. 크로스 플레이가 있습니까?
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

InnoDB 전체 텍스트 검색 기능을 설명하십시오. InnoDB 전체 텍스트 검색 기능을 설명하십시오. Apr 02, 2025 pm 06:09 PM

InnoDB의 전체 텍스트 검색 기능은 매우 강력하여 데이터베이스 쿼리 효율성과 대량의 텍스트 데이터를 처리 할 수있는 능력을 크게 향상시킬 수 있습니다. 1) InnoDB는 기본 및 고급 검색 쿼리를 지원하는 역 색인화를 통해 전체 텍스트 검색을 구현합니다. 2) 매치 및 키워드를 사용하여 검색, 부울 모드 및 문구 검색을 지원합니다. 3) 최적화 방법에는 워드 세분화 기술 사용, 인덱스의 주기적 재건 및 캐시 크기 조정, 성능과 정확도를 향상시키는 것이 포함됩니다.

Alter Table 문을 사용하여 MySQL에서 테이블을 어떻게 변경합니까? Alter Table 문을 사용하여 MySQL에서 테이블을 어떻게 변경합니까? Mar 19, 2025 pm 03:51 PM

이 기사는 MySQL의 Alter Table 문을 사용하여 열 추가/드롭 테이블/열 변경 및 열 데이터 유형 변경을 포함하여 테이블을 수정하는 것에 대해 설명합니다.

Windows 7에 MySQL을 설치할 수 있습니까? Windows 7에 MySQL을 설치할 수 있습니까? Apr 08, 2025 pm 03:21 PM

예, MySQL은 Windows 7에 설치 될 수 있으며 Microsoft는 Windows 7 지원을 중단했지만 MySQL은 여전히 ​​호환됩니다. 그러나 설치 프로세스 중에 다음 지점이 표시되어야합니다. Windows 용 MySQL 설치 프로그램을 다운로드하십시오. MySQL의 적절한 버전 (커뮤니티 또는 기업)을 선택하십시오. 설치 프로세스 중에 적절한 설치 디렉토리 및 문자를 선택하십시오. 루트 사용자 비밀번호를 설정하고 올바르게 유지하십시오. 테스트를 위해 데이터베이스에 연결하십시오. Windows 7의 호환성 및 보안 문제에 주목하고 지원되는 운영 체제로 업그레이드하는 것이 좋습니다.

MySQL에서 인덱스를 사용하는 것보다 전체 테이블 스캔이 더 빠를 수 있습니까? MySQL에서 인덱스를 사용하는 것보다 전체 테이블 스캔이 더 빠를 수 있습니까? Apr 09, 2025 am 12:05 AM

전체 테이블 스캔은 MySQL에서 인덱스를 사용하는 것보다 빠를 수 있습니다. 특정 사례는 다음과 같습니다. 1) 데이터 볼륨은 작습니다. 2) 쿼리가 많은 양의 데이터를 반환 할 때; 3) 인덱스 열이 매우 선택적이지 않은 경우; 4) 복잡한 쿼리시. 쿼리 계획을 분석하고 인덱스 최적화, 과도한 인덱스를 피하고 정기적으로 테이블을 유지 관리하면 실제 응용 프로그램에서 최상의 선택을 할 수 있습니다.

MySQL 연결에 대한 SSL/TLS 암호화를 어떻게 구성합니까? MySQL 연결에 대한 SSL/TLS 암호화를 어떻게 구성합니까? Mar 18, 2025 pm 12:01 PM

기사는 인증서 생성 및 확인을 포함하여 MySQL에 대한 SSL/TLS 암호화 구성에 대해 설명합니다. 주요 문제는 자체 서명 인증서의 보안 영향을 사용하는 것입니다. [문자 수 : 159]

인기있는 MySQL GUI 도구는 무엇입니까 (예 : MySQL Workbench, Phpmyadmin)? 인기있는 MySQL GUI 도구는 무엇입니까 (예 : MySQL Workbench, Phpmyadmin)? Mar 21, 2025 pm 06:28 PM

기사는 MySQL Workbench 및 Phpmyadmin과 같은 인기있는 MySQL GUI 도구에 대해 논의하여 초보자 및 고급 사용자를위한 기능과 적합성을 비교합니다. [159 자].

InnoDB에서 클러스터 된 인덱스와 비 클러스터 된 인덱스 (2 차 지수)의 차이. InnoDB에서 클러스터 된 인덱스와 비 클러스터 된 인덱스 (2 차 지수)의 차이. Apr 02, 2025 pm 06:25 PM

클러스터 인덱스와 비 클러스터 인덱스의 차이점은 1. 클러스터 된 인덱스는 인덱스 구조에 데이터 행을 저장하며, 이는 기본 키 및 범위별로 쿼리에 적합합니다. 2. 클러스터되지 않은 인덱스는 인덱스 키 값과 포인터를 데이터 행으로 저장하며 비 예산 키 열 쿼리에 적합합니다.

MySQL에서 큰 데이터 세트를 어떻게 처리합니까? MySQL에서 큰 데이터 세트를 어떻게 처리합니까? Mar 21, 2025 pm 12:15 PM

기사는 MySQL에서 파티셔닝, 샤딩, 인덱싱 및 쿼리 최적화를 포함하여 대규모 데이터 세트를 처리하기위한 전략에 대해 설명합니다.

See all articles