MySQL 索引

发布于:2024-07-17 ⋅ 阅读:(62) ⋅ 点赞:(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