索引的常见模型

  • 哈希表
    基于散列函数,不是有序的,而且散列冲突带来的链表结构等,会导致哈希索引做区间查询的速度很慢。因此这种结构适用于只有等值查询的场景,比如 Memcached 及其他一些 NoSQL 引擎。
  • 有序数组
    有序数组在等值查询和范围查询场景中的性能就都非常优秀,但是在需要数据的时候就麻烦了,往中间插入一个记录就必须得挪动后面所有的记录,成本太高。只适用于静态存储引擎
  • 搜索树
    等值查询和范围查询性能都很好,且数据也很方便,被广泛应用在数据库引擎中。

基于主键索引和普通索引的查询有什么区别?

  • 如果语句是 select * from T where ID=500,即主键查询方式,则只需要搜索 ID 这棵 B+ 树;
  • 如果语句是 select * from T where k=5,即普通索引查询方式,则需要先搜索 k 索引树,得到 ID 的值为 500,再到 ID 索引树搜索一次。这个过程称为回表。

也就是说,基于非主键索引的查询需要多扫描一棵索引树。因此,我们在应用中应该尽量使用主键查询。

联合索引

假设,我们对(a,b)字段建立索引,那么入下图所示
他们是按照a来进行排序,在a相等的情况下,才按b来排序。

因此,我们可以看到a是有序的1,1,2,2,3,3。而b是一种全局无序,局部相对有序状态! 什么意思呢?

从全局来看,b的值为1,2,1,4,1,2,是无序的。

从局部来看,当a的值确定的时候,b是有序的。例如a = 1时,b值为1,2是有序的状态。当a=2时候,b的值为1,4也是有序状态。
联合索引

最左前缀

根据联合索引分析,我们可以知道,联合索引跟顺序有关。因此,当执行a = 1 and b = 2是a,b字段能用到索引的。而执行a > 1 and b = 2时,a字段能用到索引,b字段用不到索引。因为a的值此时是一个范围,不是固定的,在这个范围内b值不是有序的,因此b字段用不上索引。这就是最左匹配原则,在遇到范围查询的时候,就会停止匹配。

以下是一些例子:
例1:建立索引(a,b,c)、(b,a,c)、(c,a,b)都可以,因为无范围查询,优化器会自动判断选择索引

SELECT * FROM table WHERE a = 1 and b = 2 and c = 3;

例2:建立索引(b,a)

SELECT * FROM table WHERE a > 1 and b = 2;

例3:(b,a)或者(b,c)都可以,要结合具体情况具体分析

SELECT * FROM `table` WHERE a > 1 and b = 2 and c > 3;

例4:对(a,b)建索引,当a = 1的时候,b相对有序,可以避免再次排序

SELECT * FROM `table` WHERE a = 1 ORDER BY b;

例5:(a,b,c)或(b,a,c)都可以

SELECT * FROM `table` WHERE a = 1 AND b = 2 AND c > 3 ORDER BY c;

例6:对(a,b)建立索引,因为IN在这里可以视为等值引用,不会中止索引匹配,所以还是(a,b)

SELECT * FROM `table` WHERE a IN (1,2,3) and b > 1;

覆盖索引

概念:如果索引包含所有满足查询需要的数据的索引成为覆盖索引(Covering Index),也就是平时所说的不需要回表操作。explain extra列值为 using index


诗富
2 声望0 粉丝