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语句。

데이터베이스 최적화에서 쿼리 요구 사항에 따라 인덱싱 전략을 선택해야합니다. 1. 쿼리에 여러 열이 포함되고 조건 순서가 수정되면 복합 인덱스를 사용하십시오. 2. 쿼리에 여러 열이 포함되어 있지만 조건 순서가 고정되지 않은 경우 여러 단일 열 인덱스를 사용하십시오. 복합 인덱스는 다중 열 쿼리를 최적화하는 데 적합한 반면 단일 열 인덱스는 단일 열 쿼리에 적합합니다.

MySQL 느린 쿼리를 최적화하려면 SlowQueryLog 및 Performance_Schema를 사용해야합니다. 1. SlowQueryLog 및 Set Stresholds를 사용하여 느린 쿼리를 기록합니다. 2. Performance_schema를 사용하여 쿼리 실행 세부 정보를 분석하고 성능 병목 현상을 찾고 최적화하십시오.

MySQL 및 SQL은 개발자에게 필수적인 기술입니다. 1.MySQL은 오픈 소스 관계형 데이터베이스 관리 시스템이며 SQL은 데이터베이스를 관리하고 작동하는 데 사용되는 표준 언어입니다. 2.MYSQL은 효율적인 데이터 저장 및 검색 기능을 통해 여러 스토리지 엔진을 지원하며 SQL은 간단한 문을 통해 복잡한 데이터 작업을 완료합니다. 3. 사용의 예에는 기본 쿼리 및 조건 별 필터링 및 정렬과 같은 고급 쿼리가 포함됩니다. 4. 일반적인 오류에는 구문 오류 및 성능 문제가 포함되며 SQL 문을 확인하고 설명 명령을 사용하여 최적화 할 수 있습니다. 5. 성능 최적화 기술에는 인덱스 사용, 전체 테이블 스캔 피하기, 조인 작업 최적화 및 코드 가독성 향상이 포함됩니다.

MySQL 비동기 마스터 슬레이브 복제는 Binlog를 통한 데이터 동기화를 가능하게하여 읽기 성능 및 고 가용성을 향상시킵니다. 1) 마스터 서버 레코드는 Binlog로 변경됩니다. 2) 슬레이브 서버는 I/O 스레드를 통해 Binlog를 읽습니다. 3) 서버 SQL 스레드는 데이터를 동기화하기 위해 Binlog를 적용합니다.

MySQL은 오픈 소스 관계형 데이터베이스 관리 시스템입니다. 1) 데이터베이스 및 테이블 작성 : CreateAbase 및 CreateTable 명령을 사용하십시오. 2) 기본 작업 : 삽입, 업데이트, 삭제 및 선택. 3) 고급 운영 : 가입, 하위 쿼리 및 거래 처리. 4) 디버깅 기술 : 확인, 데이터 유형 및 권한을 확인하십시오. 5) 최적화 제안 : 인덱스 사용, 선택을 피하고 거래를 사용하십시오.

MySQL의 설치 및 기본 작업에는 다음이 포함됩니다. 1. MySQL 다운로드 및 설치, 루트 사용자 비밀번호를 설정하십시오. 2. SQL 명령을 사용하여 CreateAbase 및 CreateTable과 같은 데이터베이스 및 테이블을 만듭니다. 3. CRUD 작업을 실행하고 삽입, 선택, 업데이트, 명령을 삭제합니다. 4. 성능을 최적화하고 복잡한 논리를 구현하기 위해 인덱스 및 저장 절차를 생성합니다. 이 단계를 사용하면 MySQL 데이터베이스를 처음부터 구축하고 관리 할 수 있습니다.

innodbbufferpool은 데이터와 색인 페이지를 메모리에로드하여 MySQL 데이터베이스의 성능을 향상시킵니다. 1) 데이터 페이지가 버퍼 풀에로드되어 디스크 I/O를 줄입니다. 2) 더러운 페이지는 정기적으로 디스크로 표시되고 새로 고침됩니다. 3) LRU 알고리즘 관리 데이터 페이지 제거. 4) 읽기 메커니즘은 가능한 데이터 페이지를 미리로드합니다.

MySQL은 설치가 간단하고 강력하며 데이터를 쉽게 관리하기 쉽기 때문에 초보자에게 적합합니다. 1. 다양한 운영 체제에 적합한 간단한 설치 및 구성. 2. 데이터베이스 및 테이블 작성, 삽입, 쿼리, 업데이트 및 삭제와 같은 기본 작업을 지원합니다. 3. 조인 작업 및 하위 쿼리와 같은 고급 기능을 제공합니다. 4. 인덱싱, 쿼리 최적화 및 테이블 파티셔닝을 통해 성능을 향상시킬 수 있습니다. 5. 데이터 보안 및 일관성을 보장하기위한 지원 백업, 복구 및 보안 조치.


핫 AI 도구

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

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

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

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

인기 기사

뜨거운 도구

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

드림위버 CS6
시각적 웹 개발 도구

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경

에디트플러스 중국어 크랙 버전
작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음
