以前只知道索引可以加快查询速度,而具体为什么会加速快速,对于多列索引也不清楚,也没有用过多列索引,今天了解了一下。
多列索引是指定多个列组合为一个索引,MySQL将会将多个列的值组合计算后构建索引表。使用多列索引要比使用多个单列索引要快得多。
为什么这么说呢?因为当一个SQL语句中出现多个索引字段时候,它并不能每个索引都能得上,实际上它也只能使用其中一个单列索引去查找(MySQL会选择最精确的那个索引),为什么?我们可以把索引类比成一本书的目录,都是用来快速查找我们想要的内容的。我们小学学过使用新华字典,我们知道有两种查找的方法,一种是拼音法,一种是偏旁部首法,我们每次只能使用其中的一个,不能同时使用两种方法。多个单列索引也一样,每次只能使用其中一个,不能同时使用。
而多列索引呢,当我们在一个SQL语句中合理使用了多列索引中的几个字段时候,它能够利用多列索引的几列或全部列,这就比多个单列索引只能使用一个索引要高效的多。
并且如果建立的了太多的单列索引,增删改效率会下降,而使用多列索引,则不需要担心这个问题。
多列索引使用原则是指SQL语句中使用了多列索引中的一个或多个字段时会采用哪些索引项的规则。多列索引的最左前缀原则:
具体使用一定要看看下节的案例。
假设某个表有一个联合索引为(c1, c2, c3, c4),分析下列语句索引使用情况。
A: where c1=x and c2=x and c4>x and c3=x
B: where c1=x and c2=x and c4=x order by c3
C: where c1=x and c4=x group by c3,c2
D: where c1=x and c5=x order by c2,c3
E: where c1=x and c2=x and c5=x order by c2,c3
分析:首先根据最左原则,会有如下索引:(c1),(c1, c2),(c1, c2, c3),(c1, c2, c3, c4)。然后一个一个选项的进行分析,建立下面的表,然我们可以使用explain
语句查看MySQL的解释。
create table test (
c1 tinyint(1) not null default 0,
c2 tinyint(1) not null default 0,
c3 tinyint(1) not null default 0,
c4 tinyint(1) not null default 0,
c5 tinyint(1) not null default 0,
index c1234(c1,c2,c3,c4)
);
-- 插入两条数据
insert into test values (1,3,5,6,7),(2,3,9,8,3),(4,3,2,7,5);
insert into test values (2,4,5,8,7),(1,3,5,8,4),(3,4,2,9,6);
执行下面语句:
explain select *
from test
where c1=1 and c2=2 and c4>3 and c3=3 \G
执行结果:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: test
type: range
possible_keys: c1234
key: c1234
key_len: 4
ref: NULL
rows: 1
Extra: Using where
1 row in set (0.00 sec)
可以将c4>3
与c3=3
调换,再执行explain:
explain select *
from test
where c1=1 and c2=2 and c3=3 and c4>3 \G
执行结果:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: test
type: range
possible_keys: c1234
key: c1234
key_len: 4
ref: NULL
rows: 1
Extra: Using where
1 row in set (0.00 sec)
可以发现两次的执行结果一样,这说你MySQL可以自动进行一些简单的语句优化,这里根据出现顺序,所以 c1,c2,c3,c4 都能用上。
执行下面语句:
explain select *
from test
where c1=1 and c2=2 and c4=3
order by c3 \G
执行结果:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: test
type: ref
possible_keys: c1234
key: c1234
key_len: 2
ref: const,const
rows: 1
Extra: Using where
1 row in set (0.00 sec)
只使用了c1,c2两个,使用c1,c2后,c3已经是有序的,不需要排序。
执行下面语句:
explain select *
from test
where c1=1 and c4=2
group by c3,c2 \G
执行结果:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: test
type: ref
possible_keys: c1234
key: c1234
key_len: 1
ref: const
rows: 2
Extra: Using where; Using temporary; Using filesort
1 row in set (0.00 sec)
只使用了c1一个,c2,c3不能使用,因为顺序是c3,c2。
执行下面语句:
explain select *
from test
where c1=1 and c5=2
group by c2,c3 \G
执行结果:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: test
type: ref
possible_keys: c1234
key: c1234
key_len: 1
ref: const
rows: 2
Extra: Using where
1 row in set (0.00 sec)
只使用了c1一个,c2和c3没使用,因为使用了c1后,c2,c3已经是有序的。
执行下面语句:
explain select *
from test
where c1=1 and c2=3 and c5=2
order by c2,c3 \G
执行结果:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: test
type: ref
possible_keys: c1234
key: c1234
key_len: 2
ref: const,const
rows: 2
Extra: Using where
1 row in set (0.00 sec)
只使用了c1,c2两个,c3没使用,因为使用了c1,c2后,c2,c3已经是有序的。
本文标签: MySQL
暂无评论,赶紧发表一下你的看法吧。