MySQL 索引

avatar
作者
筋斗云
阅读量:0

索引是什么? 索引是帮助MySQL高效获取数据排好序的数据结构。 索引为什么使用? 不走索引,会发生全表扫描产生无用的IO。 索引分类 索引的逻辑结构分类 normal普通索引、unique唯一索引、fulltext全文索引、spatial空间索引 1.普通索引:索引允许重复值和空值 2.唯一索引:索引列不允许重复值,但允许空值 3.主键索引:是一种特殊的唯一索引,不允许有空值 4.全文索引:用于查找文本中的关键字,全文索引列必须创建索引 5.空间索引:索引MySQL中存储的地理空间数据 6.位图索引:索引MySQL中存储的位序列数据 7.单列索引:对表中的某列创建索引 8.组合索引:对表中的多个列创建索引 空间索引只能在存储引擎为MyISAM的表中创建。 索引的物理结构分类 聚簇索引、非聚簇索引 1.聚簇索引:索引和数据存放在一起。(MyISAM) 2.非聚簇索引:索引和数据分开存放。(InnoDB) 索引的数据结构 Hash索引、B+树索引 1.Hash索引:键储存列,值储存行。在等值查询效率很高(O1)。但是在范围查询要全表扫描 2.B+树索引:叶子节点储存键值,非叶子节点储存键值范围。在范围查询效率很高(OlogN),叶子节点储存索引字段和数据,索引递增排序,通过双向指针连接(提高区间的访问能力) 索引的使用场景 1.在经常条件查询、排序、分组、联合查询的字段上建立索引 2.在多字段组合查询优先使用复合索引 3.在不重复的字段优先使用唯一索引 4.添加id主键 索引的失效场景 1.在索引列上使用运算符或者函数操作 2.在索引列上使用类型转换 3.在索引列上使用like以%开头 4.在索引列上使用is null或者is not null或者!=,全表扫描比走索引快 9.在复合索引上未使用最左前缀原则 索引的性能分析 使用explain分析sql使用的索引和优化了多少行数据 

SQL查询一次可以使用几个索引?
一次支持使用一个索引,可以通过创建复合索引包含多个列。
主键索引和唯一索引的区别?
主键索引只能有一个,包括唯一索引并且不能为NULL。

为什么联合索引有最左前缀法则?

因为构建的B+索引树导致的,从联合索引的第一列开始,第一列一致的排在一起,然后依次

为什么MySQL索引不使用二叉树?

打个比方如果列是ID递增列,二叉树会一直在增加右边节点,变成了链表。

为什么MySQL索引不使用红黑树?

如果数据量特别多的话,树构造的高度不可控也会导致查找数据很满。

为什么MySQL索引使用B+树?

B+树对比其他索引结构更好的支持范围查询。

因为B+树数据结构非叶子节点不储存数据,在叶子节点储存数据,并且是递增,通过双向链表连接,提高的区间的访问效率。

为什么B+树默认使用三层,不用四层? 

B+树查找数据快的原因,是非叶子上的索引大部分加载到内存了,如果是四层的话,上层索引加载到加内存需要的空间特别大。

MyISAM 和 InnoDB 实现 B+ 树索引方式的区别是什么?

InnoDB:B+树索引叶子节点保存数据本身,数据本身就保存索引文件

MyISAM :B+树索引叶节点的 data 域存放的是数据记录的地址,索引文件和数据文件是分离的。

为什么InnoDB尽量使用主键?

因为InnoDB是聚簇索引,储存就一个ibd文件,默认需要一个主键索引构造B+树。

如果没有主键索引组织B+树,会隐藏生成一个主键rowid组织B+树。

为什么InnoDB尽量使用自增主键?    

以为叶子节点是递增排序好的,自增主键永远会在右边添加新的节点。

如果不是自增主键,之前的的叶子节点会分裂造成性能消耗。

索引的失效场景

在索引列上使用运算符或者函数操作。

 在索引列上使用like以%开头 

在索引列上使用类型转换

比如:int类型的height字段添加了引号条件、varchar类型的字段查询sql时候没加引号、

用户表的id字段是数字类型,用户账户表关联用户字段的类型是字符串类型。

SELECT * FROM `user` WHERE height= 175; height为varchar类型导致索引失效,尤其多张表时注意

在索引列上使用is null或者is not null或者!=,全表扫描比走索引快

is null 、is not null、!=这些到底会不会使用二级索引还是得具体情况具体分析,主要取决于查询优化器对于使用二级索引+回表 和 全表扫描 两种方式的成本计算和比较,哪个成本低就会用哪个

 

复合索引未使用最左前缀导致索引失效。

索引的优化场景

深分页问题

当表的数据量特别大的时候,分页查询后面的数据,需要跳过大量的数据才能到目标数据。

解决

使用where条件利用索引找到开始位置。

 

B+树索引的原理 

B+树能储存多少索引?

 一个节点储存:(16384b/1024=16kb)数据量

非叶节点储存:16384/(8+6)=1170索引数

叶子节点储存:16索引

如果树的高度是三次:1170*1170*16=两千多万索引

16384/(索引类型bigint的大小8b)+(记录磁盘地址的节点大小6b)=1170 索引数

16kb/1kb(默认储存数据大小)=16索引

(第一层索引数1170)*(第二层索引数1170)*(第三层索引数16)=两千多万索引

B+树索引为什么这么快?

默认非子节点都加载加载到内存了,查询数据只需要比对。

 联合索引的原理

 InnoDB索引的原理

 MyISAm索引的原理

MyISAM文件储存

 

-- 创建表 CREATE TABLE my_table (     id INT AUTO_INCREMENT PRIMARY KEY,     column1 VARCHAR(255),     column2 VARCHAR(255) );  -- 创建索引 CREATE INDEX idx_column1_column2 ON my_table (column1, column2); CREATE INDEX idx_column1 ON my_table(column1); CREATE INDEX idx_column2 ON my_table(column2); DROP INDEX idx_column2 ON my_table; DROP INDEX idx_column1_column2 ON my_table;  -- 插入数据 INSERT INTO my_table (column1, column2) VALUES ('apple', 'red'), ('banana', 'yellow'), ('grape', 'purple'), ('apple', 'green'), ('banana', 'green'), ('grape', 'red'), ('apple', 'yellow'), ('banana', 'purple'), ('grape', 'green'), ('apple', 'purple');     DESC  SELECT * FROM my_table WHERE column1 = 'apple' OR column2 = 'green'  Using union(idx_column1,idx_column2); Using where   DESC  SELECT * FROM my_table WHERE column1 = 'apple' UNION  SELECT * FROM my_table WHERE column2 = 'green';  DESC  SELECT * FROM my_table WHERE column1 = 'apple' OR column2 = 'green' ORDER BY column1,column2;  Using union(idx_column1,idx_column2); Using where; Using filesort     

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!