1. 分析查询语句
通过对查询语句的分析,可以了解查询语句的执行情况,找出查询语句执行的瓶颈,从而优化查询语句。
MySql提供列EXPLAIN语句和DESCRIBE语句,用来分析查询语句。
EXPLAIN语法:
EXPLAIN [EXTENDED] SELECT select_options;
使用EXTENDED可以使EXPLAIN的查询结果包含附加信息。

下面对EXPLAIN查出的字段进行描述:
| id |
select 识别符。是select查询*** |
| select_type |
表示select语句的类型,可以有以下几种值:
- simple表示简单查询,其中不包括连接查询和子查询。
- primary表示主查询或是最外层的查询语句
- union表示连接查询的第2个或后面的查询语句
- dependent union连接查询中的第2个或后面的select语句取决于外面的查询
- union result 连接查询结果
- subquery 子查询中的第一个select语句
- dependent subquery 子查询中的第一个select语句,取决于外面查询
- derived 导出表的select(from子句的子查询)
|
| table |
表示查询的表 |
| type |
表示表的连接类型。下面按照从最佳类型到最差类型的顺序给出各种连接类型:
- system 该表是仅有一行的系统表,是const的一个特例
- const 数据表最多只有一个匹配行他将在查询开始是被读取并在余下的查询优化中作为常量对待。const表查询速度 快因为他们只读一次。const用于使用常数值比较primary key或unique索引的所有部分的场合eg:select * from tb_name where primary_key = 1;
- eq_ref 对于每个来自前面的表的行的组合,从该表中读取一行。当一个索引的所有部分都在查询中使用并且索引是 unique或primary key时,即可使用这种类型。eq_ref可以用于使用“=”操作符比较带索引的列。比较值可以为常量或 一个在该表前面所读取的表的列的表达式。eg:select * from red_table,other_table where ref_table.key_cloumn=other_table.column;
- ref 对于来自前面的表的任意行组合,将从该表中读取所有匹配的行。这种类型用于索引即不是unique也不是primary key的情况,或者查询中使用列索引列的左子集。ref可以用于使用=或<=>操作符的带索引的列eg:select * from ref_table where key_column=exper;
- ref_or_null 该类型如同ref,但是添加了Mys+SQl可以专门搜索包含NULL值的行。在解决子查询中经常使用该连接类型 的优化。eg:select * from ref_table where key_cloumn = expr or key_cloumn is NULL;
- index_merge 该连接类型表示使用列索引合并优化方法。在这种情况下,key列包含了使用索引的清单。key_len包含了使用的索引的最长的关键元素
- unique_subquery 该类型替换了下面形式的in子查询的ref:value in (select primary_key from single_table where some_expr),unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高。
- index_subquery 该连接类型类似于unique_subquery,可以替换in子查询,但只适合下列形式的子查询中的非唯一索 引:value in (select key_cloumn from single_table where some_expr)
- range 只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引。key_len包含所使用索引的最长关键元素。
- index 该连接类型与all相同,除了只扫描索引树。这通常比all快,因为索引文件通常比数据文件小
- all 对于前面的表的任意组合,进行完整的表扫描。如果表是第一个没标记const的表,这样不好,并且在其他情况下很差。通常可以增加更多的索引来避免使用all连接。
|
| possible_keys |
指出mysql能使用哪个索引在该表中找到行。如果该列是NULL,则没有相关索引在这种情况下,可以通过检查where子句看他是否引用某些列或适合索引的列来提高查询性能,如果是这样可以创建适合的索引来提高查询性能 |
| key |
表示查询实际使用到的索引,如果没有选择索引,该列的值为NULL。要想强制MySQL使用或忽视possible_key列中的索引,在查询中使用force index、use index或者ignore index。 |
| key_len |
表示MySQL选择的索引字段按字节计算的长度,如果key为NULL,则长度为NULL。注意通过key_len的值可以确定MySQL将实际使用一个多列索引中的几个字段 |
| ref |
表示使用哪个列或常数与索引一起来查询记录 |
| rows |
显示MySQL在表中进行查询时必须检查的行数 |
| extra |
表示MySQL在处理查询时的详细信息 |
2. 索引对查询的影响
下面通过例子看一下索引对数据库查询的影响

可以看到,没有使用索引时查询age为20的记录需要扫描5行记录,这是表的总数。建立索引后,查询只需要扫描两行,这样就大大提高了sql的执行速度。
3. 使用索引查询
索引可以提高查询速度。但并不是使用带有索引的字段查询时,索引都会起作用。
使用索引有几种特殊的情况,在这些情况下,有可能使用带有索引的字段查询时,索引并没有起作用。
1. 使用like关键字查询语句
在使用like关键字进行查询时,如果匹配的字符串的第一个字符为"%",索引不会起作用。只有"%"不在第一个位置,索引才会 起作用。
2. 使用多列索引的查询语句
MySQL可以为多个字段创建索引。一个索引可以包含16个字段。对于多列索引,只有查询条件使用了这些字段中的第一个字 段时,索引才会被使用。
3. 使用or关键字的查询语句
查询语句的查询条件有or关键字,且or前后的两个条件中的列都是索引时,查询才会使用索引。
4. 优化子查询
MySQL执行子查询时,需要为内层查询语句的查询结果建立一个临时表,然后外层查询语句从临时表中查询记录。查询完毕后再销毁临时表。因此,查询速度会受子查询的数据量影响。
可以使用连接(join)查询来代替子查询。连接查询不需要建立临时表,所以速度要比子查询快,如果查询中使用索引的话性能会更好。