在MySQL中单键索引是很好理解的,就是通过B-tree快速匹配到要查询的记录。但是一个MySQL语句中只能使用一个索引,当想优化整个查询的时候就会出现复合索引。也就是用一个索引给多个列添加索引。

单列索引:

ALTER TABLE people ADD INDEX lname (lname);
mysql>SELECT `uid` FROM people WHERE lname`='Liu'
AND `fname`='Zhiqun' AND `age`=26

将lname列建索引,这样就把范围限制在lname='Liu'的结果集1上,之后扫描结果集1,产生满足fname='Zhiqun'的结果集2,再扫描结果集2,找到

age=26的结果集3,即最终结果。由于建立了lname列的索引,与执行表的完全扫描相比,效率提高了很多,但我们要求扫描的记录数量仍旧远远超过了实际所需要的。虽然我们可以删除lname列上的索引,再创建fname或者age

列的索引,但是,不论在哪个列上创建索引搜索效率仍旧相似。

复合索引:

ALTER TABLE people ADD INDEX lname_fname_age

(lame,fname,age);

为了提高搜索效率,我们需要考虑运用多列索引,由于索引文件以B-Tree格式保存,所以我们不用扫描任何记录,即可得到最终结果。

注:

1)在mysql中执行查询时,只能使用一个索引,如果我们在lname,fname,age上分别建索引,执行查询时,只能使用一个索引,mysql会选择一个最严格(获得结果集记录数最少)的索引。

2)最左前缀:顾名思义,就是最左优先,上例中我们创建了lname_fname_age多列索引,相当于创建了(lname)单列索引,(lname,fname)组合索引以及(lname,fname,age)组合索引,注意,此时并不是创建了(fname)这就是最左前缀的意义。

3)组合索引的第一个字段必须出现在查询组句中,这个索引才会用到,否则此索引不会发挥任何的作用,例如:

alter table A add index R(id,name);
select * from A where name = 'lisi';

因为此时只用到了name,但是name却是索引R的第二个字段所以此处不会发挥任何的作用。

4)即使在语句中出现了复合索引的所有字段,但是顺序却和索引中的顺序不一致,此时索引当然也会用到,但是不如一致时的效率高,例如:

执行下面的sql语句:

select product_id
from orders
where order_id in (123, 312, 223, 132, 224);
这条语句要mysql去根据order_id进行搜索,然后返回匹配记录中的product_id。
所以组合索引应该按照以下的顺序创建:
create index orderid_productid on orders(order_id,
product_id)
mysql> explain select product_id from orders where order_id
in (123, 312, 223, 132, 224) \G
*************************** 1. row
***************************
id: 1
select_type: SIMPLE
table: orders
type: range
possible_keys: orderid_productid
key: orderid_productid
key_len: 5
ref: NULL
rows: 5
Extra: Using where; Using index
1 row in set (0.00 sec)

可以看到,这个组合索引被用到了,扫描的范围也很小,只有5行。

如果把组合索引的顺序换成product_id, order_id的话,

mysql就会去索引中搜索 *123 *312 *223 *132 *224,必然会有些慢了。

mysql> create index orderid_productid on orders(product_id,
order_id);
Query OK, 31 rows affected (0.01 sec)
Records: 31  Duplicates: 0
Warnings: 0
mysql> explain select product_id from orders where order_id
in (123, 312, 223, 132, 224) \G
*************************** 1. row
***************************
id: 1
select_type: SIMPLE
table: orders
type: index
possible_keys: NULL
key: orderid_productid
key_len: 10
ref: NULL
rows: 31
Extra: Using where; Using index
1 row in set (0.00 sec)

这次索引搜索的性能显然不能和上次相比了。