Mysql索引分析

这里主要利用explain来观察语句是否走索引。html

explain语法自行百度,详见Mysql官方文档。mysql

1、explain输出格式说明sql

具体说明:数据库

1) id缓存

该字段标识select语句id,若SQL中只有1个select语句(即便是多表关联查询),则该值为1,不然依次递增;若SQL是union的结果,则该值为NULL。优化

2) select_type网站

该字段说明select语句的类型,其可能的取值以下图(来自官网文档):spa

其中,simple是最多见的类型,代表SQL只包含1个select语句;derived代表该行表明的数据表(derived table)实际上是from子句中包含的子查询的输出结果;其他类型较易理解,阅读官方文档便可,这里不赘述。翻译

3) tablehtm

该字段代表explain输出的每行所表明的数据集来自哪张表,其值一般是具体的表名,当数据集是union的结果时,其值可能

是<unionM,N>,当数据集来自derived table时,其值多是<derivedN>。这里提到的M或N均是id字段的值。

4) type

该字段代表各表是如何被join的,其取值比较复杂,详细可参考官网文档。这里只列出最多见的几种取值。

a. system/const

const代表上述"table"字段表明的数据集中,最多只有1行记录命中本步执行计划的查询条件,例如这步执行计划的sql的where

子句以某张表的primary key或unique index与常数作比较时,该执行计划对应的type字段取值就是const。

system只是const值的一个特例,它表示本步执行计划要操做的数据集中只有1行记录。

它们只可能出如今单表查询SQL的type字段取值中。

b. eq_ref

该值代表本步执行计划操做的数据集中关联字段是索引字段且只有1条记录符合上步执行计划操做的数据集的关联条件。

是对多表作关联查询时,可能获得的最优的join类型(由于它一般代表关联的字段是本步执行计划要操做的表的primary key或unique index)。

c. ref

该值代表本步执行计划操做的数据集中关联字段是索引字段但不仅有1条记录符合上步执行计划操做的数据集的关联条件。

符合关联条件的记录不仅1条代表关联字段非primary key或unique index,当符合关联条件的记录数比较少时,这种join_type='ref'的场景仍是比较合理的,但它显然不如join_type='eq_ref'高效。

d. ref_or_null

该join type类型与ref的场景相似,但它代表MySQL会对包含NULL值的字段作额外搜索。例以下面SQL的join type就是ref_or_null:

SELECT * FROM ref_table WHERE key_column=expr OR key_column IS NULL;

e. index_merge

该值代表MySQL会对本步执行计划进行index merge优化,触发index merge的SQL一般包含'or'操做,常见实例以下:

SELECT * FROM tbl_name WHERE key1 = 10 OR key2 = 20;

SELECT * FROM tbl_name WHERE (key1 = 10 OR key2 = 20) AND non_key=30;

SELECT * FROM t1, t2 WHERE (t1.key1 IN (1,2) OR t1.key2 LIKE 'value%') AND t2.key1=t1.some_col;

SELECT * FROM t1, t2 WHERE t1.key1=1 AND (t2.key1=t1.some_col OR t2.key2=t1.some_col2);

f. range

该值代表本步执行计划只操做单表且符合查询条件的记录不仅1,可能出如今有in或between操做的SQL中。

只限于单表操做场景也是其与前面提到的join_type取值为'ref'场景的区别,由于ref可能出如今单表/多表join操做场景下。

g. ALL

该值代表本步执行计划会对数据集作全表扫描,这是必须作优化的场景。一般能够经过对某些字段合理建索引来避免全表扫描。

h. index

该值代表MySQL执行本步计划时扫描的是index tree,而ALL则是扫全表。它可能在两种场景下出现:

case1. 本步计划查询数据集时select语句须要返回的字段是该数据集索引字段的最左前缀匹配集。如table A中已创建含2个字段的联合索引(f1, f2),则select f1 from A where f2 = 'yyy'可能会触发MySQL扫描index tree,这种状况下,执行计划的Extra字段会包含"Using index"来代表它扫描的是index tree,由于f1是(f1, f2)最终前缀匹配集中的1个元素;而select f2 from A where f2 = 'yyy'则会扫描全表。

case2. 本步计划按照索引顺序进行全表扫描来查找符合条件的数据。这种状况下,执行计划的Extra字段不会包含"Using index",这种全表扫描也是必须优化的场景。

5) possible_keys

该字段的值是可能被MySQL用做索引的字段,若值为NULL,则没有字段会被用做索引,所以查询效率不会高,这种状况下,须要优化数据表的索引结构。

6) key

该字段的值是MySQL真正用到的索引。

值得注意的是:该字段的值有可能不是possible_keys列出的候选索引字段,例如,当前查询SQL要返回的字段是数据表某索引字段的最左前缀匹配字段,但SQL的where条件中没有使用数据表的索引字段,则此时possible_keys可能为NULL,而key字段的值多是那个能cover住待查询字段的数据表索引字段,此时,MySQL会扫描索引树,虽然低效,但比起扫描全表仍是要快。这种场景也正是本文前面解释join_type='index'时提到的case1。

此外,在select语句中借助"force index或"use index"能够强制MySQL使用possible_keys中列出的候选索引字段。

7) key_len

该字段的值代表上述key字段的length,当MySQL将某联合索引字段做为SQL执行时用到的索引时,key_len字段能够暗示MySQL真正在什么程度上(多长的最左前缀匹配字段)使用了该联合索引。若key字段的值为NULL,则key_len字段值也为NULL。

8) ref

该字段的值代表数据表中的哪列或哪一个constants会被用于与key字段指定的索引作比较。

9) rows

该字段的值代表MySQL执行该步计划对应的query时必须扫描的行数。这个值对于SQL优化很是具备参考意义,一般状况下,该值越小查询效率越高。

10) Extra

该字段的值包含了MySQL执行query时的其它额外信息。该字段可能的取值状况较多,详细状况可参考官网文档的说明。

该说明官网均有,既然有现成本身也就懒得翻译了。

PS:

字段说明参考网址:http://www.2cto.com/database/201502/377682.html

Mysql官方网址:http://dev.mysql.com/doc/refman/5.5/en/explain-output.html

2、其余问题

show index返回的字段意思:

1)     Table 表的名称。

2)     Non_unique 若是索引不能包括重复词,则为0,若是能够则为1。

3)     Key_name 索引的名称

4)     Seq_in_index 索引中的列序列号,从1开始。

5)     Column_name 列名称。

6)     Collation 列以什么方式存储在索引中。在MySQL中,有值‘A’(升序)或NULL(无分类)。

7)     Cardinality 索引中惟一值的数目的估计值。经过运行ANALYZE TABLE或myisamchk -a能够更新。基数根据被存储为整数的统计数据来计数,因此即便对于小型表,该值也没有必要是精确的。基数越大,当进行联合时,MySQL使用该索引的机会就越大。

8)     Sub_part 若是列只是被部分地编入索引,则为被编入索引的字符的数目。若是整列被编入索引,则为NULL。

9)     Packed 指示关键字如何被压缩。若是没有被压缩,则为NULL。

10)   Null 若是列含有NULL,则含有YES。若是没有,则该列含有NO。

11)   Index_type 用过的索引方法(BTREE, FULLTEXT, HASH, RTREE)。

12)   Comment 多种评注,您可使用db_name.tbl_name做为tbl_name FROM db_name语法的另外一种形式。这两个语句是等价的:

mysql>SHOW INDEX FROM mytable FROM mydb;

mysql>SHOW INDEX FROM mydb.mytable;

 

http://www.th7.cn/db/mysql/201508/114301.shtml

SELECT /*!40001 SQL_NO_CACHE */ * FROM ... :

1 /*! */ 这是mysql 特里的语法,并不是注释,由于里面达到条件也会执行。

2 !后面是版本号, 若是本数据库等于或大于此版本号,那么注释内的代码也会执行。

3 那么这句话的意思是 若是版本号大于或等于4,会执行 sql_no_cache, 就是不用缓存数据。 而并不是说本次查询不做为下次查询的缓存。

4 在备份操做时Mysql 会自动调用此语法。

 

3、实践操做

本身项目就不展现了,安利一个网站。

推荐网址:http://tech.meituan.com/mysql-index.html(美团团队Mysql慢查询分析与解析,里面还详细讲了数据库使用的B+树)

相关文章
相关标签/搜索