MySQL深入索引

什么是索引:索引的出现简单来说是为了提交数据查询的效率,就像书的目录一样;

索引模型

三种简单模型,哈希表,有序列表,二叉搜索树;

哈希表:哈希表是一种以键 - 值(key-value)存储数据的结构,我们只要输入待查找的键即 key,就可以找到其对应的值即 Value。哈希的思路很简单,把值放在数组里,用一个哈希函数把 key 换算成一个确定的位置,然后把 value 放在数组的这个位置。

假设,你现在维护着一个身份证信息和姓名的表,需要根据身份证号查找对应的名字,这时对应的哈希索引的示意图如下所示

User2 和 User4 根据身份证号算出来的值都是 N,那么会拉出一个链表,增加数据会很快,只需要往后增加;因为不是有序,区间查询很慢;适合等值查询,memcached等,

有序数组:有序数组只适合静态存储,比如不需要更改的数据,更新数据时,需要挪动后面的位置成本比较高;

二叉搜索树:父节点左子树所有结点的值小于父节点的值,右子树所有结点的值大于父节点的值。这样如果你要查 ID_card_n2 的话,按照图中的搜索顺序就是按照 UserA -> UserC -> UserF -> User2 这个路径得到;

Innodb索引模型

在表的是根据主键顺序以索引形式存放的,存储方式叫索引组织表。innodb采用了B+树索引模型,所以数据存储在B+树中。每个索引在innodb里面都对应一棵树;
举例:

create table T(id int primary key, k int not null, name varchar(16),index (k))engine=InnoDB;

表中 R1~R5 的 (ID,k) 值分别为 (100,1)、(200,2)、(300,3)、(500,5) 和 (600,6),两棵树的示例示意图如下。

索引:索引类型分为主键索引和非主键索引。主键索引存的叶子节点是整行数组,主键索引也叫聚簇索引,非主键索引叶子节点内容是主键的值,非主键索引也叫二级索引;

关于主键索引和普通索引查询的区别?
如果语句是 select * from T where ID=500,即主键查询方式,则主键查询方式,则只需要搜索ID这颗B+树,如果语句是 select * from T where k=5,即普通索引查询方式,则需要先搜索 k 索引树,得到 ID 的值为 500,再到 ID 索引树搜索一次。这个过程称为回表。也就是说,基于非主键索引的查询需要多扫描一棵索引树。因此,我们在应用中应该尽量使用主键查询。

索引维护

.一个数据页满了,按照B+Tree算法,新增加一个数据页,叫做页分裂,会导致性能下降。空间利用率降低大概50%。当相邻的两个数据页利用率很低的时候会做数据页合并,合并的过程是分裂过程的逆过程。从性能和存储空间方面考量,自增主键往往是更合理的选择。

关于索引删除

如果删除,新建主键索引,会同时去修改普通索引对应的主键索引,性能消耗比较大。
删除重建普通索引貌似影响不大,不过要注意在业务低谷期操作,避免影响业务。

索引实战
create table T (ID int primary key,k int NOT NULL DEFAULT 0, s varchar(16) NOT NULL DEFAULT '',index k(k))engine=InnoDB;insert into T values(100,1, 'aa'),(200,2,'bb'),(300,3,'cc'),(500,5,'ee'),(600,6,'ff'),(700,7,'gg');

SQL 查询语句的执行流程:
1.在 k 索引树上找到 k=3 的记录,取得 ID = 300;
2.再到 ID 索引树查到 ID=300 对应的 R3;
3.在 k 索引树取下一个值 k=5,取得 ID=500;
4.再回到 ID 索引树查到 ID=500 对应的 R4;
5.在 k 索引树取下一个值 k=6,不满足条件,循环结束。
回到主键索引树搜索的过程,我们称为回表,上面读了3次索引树,2次回表;

覆盖索引

覆盖索引:如果查询条件使用的是普通索引(或是联合索引的最左原则字段),查询结果是联合索引的字段或是主键,不用回表操作,直接返回结果,减少IO磁盘读写读取正行数据

最左前缀:联合索引的最左 N 个字段,也可以是字符串索引的最左 M 个字符

联合索引:根据创建联合索引的顺序,以最左原则进行where检索,比如(age,name)以age=1 或 age= 1 and name=‘张三’可以使用索引,单以name=‘张三’ 不会使用索引,考虑到存储空间的问题,还请根据业务需求,将查找频繁的数据进行靠左创建索引。

索引下推:like 'hello%’and age >10 检索,MySQL5.6版本之前,会对匹配的数据进行回表查询。5.6版本后,会先过滤掉age<10的数据,再进行回表查询,减少回表率,提升检索速度

posted @ 2021-02-22 14:43  惊风破浪的博客  阅读(63)  评论(0编辑  收藏  举报