mysql索引结构原理、性能分析与优化(七)

2015-01-21 11:32:26 · 作者: · 浏览: 35
-----+-------+---------------+------------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref
| rows | Extra |
+----+-------------+-------+-------+---------------+------------+---------+------+------+-------+
| 1 | SIMPLE | one | index | NULL | last_login | 4 | NULL
| 10 | |
+----+-------------+-------+-------+---------------+------------+---------+------+------+-------+
1 row in set (0.00 sec)
开始没limit查询是遍历表的,加了limit后,索引可以使用,看key_len 和key

where + orerby 类型,where满足最左前缀原则,且orderby的列和where子句用到的索引的列的子集。即是(a,b,c)索引, where满足最左前缀原则且order by中列a、b、c的任意组合

mysql> explain select * from one where username='abgvwfnt' and password ='123456
' and last_login='1338251001' order by password desc,last_login desc;
+----+-------------+-------+------+---------------+----------+---------+-------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+----------+---------+-------------------+------+-------------+
| 1 | SIMPLE | one | ref | username | username | 83 | const,const,const | 1 | Using where |
+----+-------------+-------+------+---------------+----------+---------+-------------------+------+-------------+
1 row in set (0.00 sec)

mysql> explain select * from one where username='abgvwfnt' and password ='123456
' and last_login='1338251001' order by password desc,level desc;
+----+-------------+-------+------+---------------+----------+---------+-------------------+------+----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref| rows | Extra |
+----+-------------+-------+------+---------------+----------+---------+-------------------+------+-----------------------------+
| 1 | SIMPLE | one | ref | username | username | 83 | const,const,const | 1 | Using where; Using filesort |
+----+-------------+-------+------+---------------+----------+---------+-------------------+------+-----------------------------+

1 row in set (0.00 sec)
上面两条语句明显的区别是多了一个非索引列level的排序,在extra这列对了Using filesort。 笔者测试结果:where满足最左前缀且order by中的列是该多列索引的子集时(也就是说orerby中没最左前缀原则限制),不管是否 有asc ,desc混合出现,都能用索引来满足order by。因为篇幅比较大,这里就不一一列出。

Ps:很优化博文都说order by中的列要where中出现的列(是索引)的顺序一致,笔者认为不够严谨。

where + orerby+limit

这个其实也差不多,只要where最左前缀,orderby也正确,limit在此影响不大

如何考虑order by来建索引

这个回归到创建索引的问题来,在比较常用的oder by的列和where中常用的列建立多列索引,这样优化起来的广度和扩张性都比较好, 当然如果要考虑UNION、JOIN、COUNT、IN等进来就复杂很多了

隔离列

隔离列是只查询语句中把索引列隔离出来,也就是说不能在语句中把列包含进表达式中,如id+1=2、inet_aton('210.38.196.138')--- ip转换成整数、convert(123,char(3))---数字转换成字符串、date函数等mysql内置的大多函数。

非隔离列影响性能很大甚至是致命的,这也就是赶集网石展的《三十六军规》中的一条,虽然他没说明是隔离列。 以下就测试一下:

首先建立一个索引(last_login ),这里就不给出建立的代码了,且把last_login改成整型(这里只是为了方便测试,并不是影响条件)

mysql> explain select * from one where last_login = 8388605;  
+----+-------------+-------+------+---------------+------------+---------+-------+-------+-------------+  
| id | select_type | table | type | possible_keys | key        | key_len | ref | rows  | Extra       |  
+----+-------------+-------+------+---------------+------------+---------+-------+-------+-------------+  
|  1 | SIMPLE      | one   | ref  | last_login    | last_login | 3       | const   | 1 | Using where |  
+----+-------------+-------+------+---------------+------------+---