# 数据库索引

# 位图索引

部分内容来源:点击这里 (opens new window)

不使用索引时,数据库只能一行行扫描所有记录,然后判断该记录是否满足查询条件

  • 位图索引适合只有几个固定值的列,如性别、婚姻状况、行政区等等,而身份证号这种类型不适合用位图索引。

  • 位图索引适合静态数据,而不适合索引频繁更新的列。

  • 位图索引不存储rowid值(数据实际物理地址),也不存储键值。

  • 在表中放置单独的位图索引是没有意义的,只有多个列建立位图索引,系统才能有效的利用位图索引提高查询速度。

  • 位图索引不适合OLTP(联机事务处理)适合OLAP(联机分析处理)

      create bitmap index emp_job_bitmap_idx on 表(列);	
    

流程:

  1. 性别只有男女两个值,最多再加个未知,数值种类较少,因此用位图索引较为合适。
rowId 1 2 3 4 5 6 ...
1 1 1 1 0 1 ...
0 0 1 0 1 1 ...

位图索引形成两个向量,男向量为111101...,向量的每一位表示该行是否是男,如果是则位1,否为0,同理,女向量位001011...

  1. 婚姻情况也是类似
rowId 1 2 3 4 5 6 ...
已婚 1 1 1 1 0 1 ...
未婚 0 0 1 0 1 1 ...

位图索引形成两个向量,已婚向量为111101...,未婚向量位001011...

此时如果有个查询,查询 性别=男 and 婚姻=未婚 ,就会将男向量与未婚向量想与,得到相与结果为1的就是要查询的结果。

不适合 OLTP 的原因:
位图索引, 由于用位图反映数据, 不同会话更新相同键值的同一位图段, insert、update、delete相互操作都会发锁定,导致阻塞,未完成前无法进行下一步操作。

# Mysql存储引擎

  • MyISAM引擎

MyISAM存储引擎不支持行级锁,只有表级锁;
不支持事务,也不支持外键,主要面向OLAP应用,是MySQL数据库5.5.8之前版本默认的存储引擎。
MyISAM适用于不需要关心事务,读多写少的场景。
每张MyISAM表在磁盘上会创建三个文件:.frm. MYD. MYI,其中.frm文件为表结构,每个存储引擎都会有这个文件,是用来存储表结构的,
. MYD文件用来存储数据,. MYI用来存储索引,也就是说MyISAM的数据和索引是分开存储的,这一点和InnoDB不一样。
在MySQL5.0之前,MyISAM默认支持的表只有4GB,如果要修改默认表大小的话,需要修改参数MAX_ROWS和AVG_ROW_LENGTH的大小,不过这一点在MySQL5.0之后得到了改善,默认大小为256TB,这个大小在绝大部分应用应该都是可以满足要求的。

  • InnoDB引擎

InnoDB存储引擎支持事务,主要是为了面向在线事务处理(OLTP)的应用而生,支持行锁和外键,
其通过使用多版本并发控制(MVCC)来提升高并发性能,实现了SQL标准的4种隔离级别。
从MySQL数据库5.5.8版本开始,为MySQL默认存储引擎。 每张 InnoDB表在磁盘上会创建两个文件:.frm.ibd
其中.frm文件和MyISAM引擎一样,用来存储表结构的, .ibd文件存储的是索引和数据,InnoDB中索引和数据放在同一个文件中。

# Mysql的最左匹配原则

# like和_的最左匹配方式

比如我们在表user中的列name中创建了索引,然后执行查询语句:

select * from user where name like '%张三';
select * from user where name like '_张三';
1
2

这两种因为不是从开头开始匹配的,等于跳过了索引的开头部分,根据索引的最左匹配原则,这种情况就不会使用索引。

# 联合索引的最左匹配方式

比如我们在表user中的列name和age中创建了联合索引index(name, age),然后执行查询语句:

select * from user where name='张三';
select * from user where age=12;
select * from user where name='张三' and age=12;
1
2
3

上面的索引中1和3是可以用到索引的,联合索引可以只使用一列,和第二句,因为跳过了name直接搜索age,违反了最左匹配原则,所以一般不支持索引。

# 其他无法使用索引场景

  • 在索引列上使用函数(replace\substr\concat\sum count avg等),使用表达式或者计算(+、-、*、/)
  • 字符串不加引号,会出现隐式转换,相当于使用函数to_char()
  • 使用!,<>,not like,not in等反向查询

这些规则其实也仅仅只是在一般情况下,然后到底用不用索引,最终还是要优化器决定,MySQL优化器是基于开销来决定是否使用索引而不是基于规则来决定是否使用索引。

Last Update: 1/19/2021, 11:09:58 PM