MySQL多列索引和经典案例

MySQL 阅读: 459

以前只知道索引可以加快查询速度,而具体为什么会加速快速,对于多列索引也不清楚,也没有用过多列索引,今天了解了一下。

多列索引

多列索引是指定多个列组合为一个索引,MySQL将会将多个列的值组合计算后构建索引表。使用多列索引要比使用多个单列索引要快得多。

为什么这么说呢?因为当一个SQL语句中出现多个索引字段时候,它并不能每个索引都能得上,实际上它也只能使用其中一个单列索引去查找(MySQL会选择最精确的那个索引),为什么?我们可以把索引类比成一本书的目录,都是用来快速查找我们想要的内容的。我们小学学过使用新华字典,我们知道有两种查找的方法,一种是拼音法,一种是偏旁部首法,我们每次只能使用其中的一个,不能同时使用两种方法。多个单列索引也一样,每次只能使用其中一个,不能同时使用。

而多列索引呢,当我们在一个SQL语句中合理使用了多列索引中的几个字段时候,它能够利用多列索引的几列或全部列,这就比多个单列索引只能使用一个索引要高效的多。

并且如果建立的了太多的单列索引,增删改效率会下降,而使用多列索引,则不需要担心这个问题。

多列索引使用原则:最左前缀原则

多列索引使用原则是指SQL语句中使用了多列索引中的一个或多个字段时会采用哪些索引项的规则。多列索引的最左前缀原则:

  1. 如果有一个2列的索引(col1, col2),则已经对(col1)、(col1, col2)上建立了索引;
  2. 如果有一个3列索引(col1, col2, col3),则已经对(col1)、(col1, col2)、(col1, col2, col3)上建立了索引;

具体使用一定要看看下节的案例。

多列索引经典案例

问题描述

假设某个表有一个联合索引为(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);

A选项

执行下面语句:

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>3c3=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 都能用上。

B选项

执行下面语句:

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已经是有序的,不需要排序。

C选项

执行下面语句:

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。

D选项

执行下面语句:

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已经是有序的。

E选项

执行下面语句:

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已经是有序的。

参考文章

  1. 索引的最左前缀原则 - 节奏型男-全栈 - 博客园
  2. Mysql多列索引经典案例 - Yxh_blogs - 博客园

版权声明:本文为博主原创文章,转载需注明来自: 洛洛の空间