MySQL索引及数据结构

Hash索引

(1) 它会使用到hash函数,算出一个确切的值 , 如果key发生变化. hash值也会跟着发生变化. 而且还存在着hash冲突的情况.

(2)  联合索引的情况 hash(id+name) = hash值 , 不能支持 部分索引查询和范围查找.

红黑树

(1) 树太高,读取磁盘的次数过多, 1,2,4,8,16......

  比如第一层只会存一个数据,读一次磁盘,就取1个数据 ,如果是n叉树,读一次磁盘可以拿到n个数据....

(2) 每次读取磁盘浪费太多

所以, 不适合做数据库索引, 毕竟它只是个二叉树,太浪费磁盘IO了.

红黑树用于HashMap的原因?

因为HashMap是内存数据结构,所以不存在上面提到的两个问题

B树

B-tree,  B+tree,   B*tree

B-tree是n叉排序树.

M阶的Btree的几个重要特性:

1. 结节最多含有m颗子树(指针), m-1个关键字(存储数据的空间) (m>2)

2. 除根节点和叶子节点外,其它每个节点至少有ceil(m/2)个子节点, ciel向上取整 . 比如, 5/2 =2.5 (取整) = 3 . 分裂的时候从中间分开,分成两颗子树.

3. 若根节点不是叶子节点,则至少有两根子树

示例

  创建一颗5阶Btree,插入的数据有3 14 7 1 8 5 11 17 13 6 23 12 20 26 4 16 18 24 25 19(数据库的userId),根据Btree的特点, 5阶Btree即一个磁盘空间最多有5个指针(存的查找路径), 4个关键字(mysql中存的数据)

现在插入8,发现空间不够,就会出现一次分裂,移动中间元素到根节点即可

现在插入13, 7的右子树空间又不够了,将会再次发生分裂, 不过这次需要注意的是,13会插入到7的后面

后面过程略,最终结构如下图所示

再比较一下B+tree的结构

MySQL是如何建联合索引的?

假设我们使用user_id+name+age建联合索引, MySQL的底层还是使用user_id字段来创建的索引,只不过使用user_id创建的这颗索引树的叶子节点不再是存储的MySQL数据,它存储的是 user_id+name+age+ 数据地址(这个地址指向了数据库的真实数据).

所以,在使用联合索引查询数据的时候,首先是通过user_id查找这颗树的叶子,然后在叶子节点中找到 user_id+name+age 对应的这条数据地址,然后再使用这个地址去磁盘读取数据.

联合索引也体现了最左原则,所以在使用联合索引查询的时候,如果没有user_id,MySQL根本就找不到索引树.所以,索引就会失败.

MySQL索引树一个节点存储关键字的多少 = 页大小(16K)/索引大小

每个节点上关键字越多,树就应该越矮, 查找速度也就更快, 所以,建索引的字段应该越小越好.

再来一个小示例

mysql> select * from tb_emp;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | 乔峰 | 123 |
+----+--------+------+
1 row in set (0.00 sec)

mysql> show index from tb_emp;
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tb_emp | 0 | PRIMARY | 1 | id | A | 2 | NULL | NULL | | BTREE | | |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

# 创建一个name+age 的联合索引

mysql> alter table tb_emp add index `name_age_index`(name,age);
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> show index from tb_emp;
+--------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tb_emp | 0 | PRIMARY | 1 | id | A | 2 | NULL | NULL | | BTREE | | |
| tb_emp | 1 | name_age_index | 1 | name | A | 1 | NULL | NULL | YES | BTREE | | |
| tb_emp | 1 | name_age_index | 2 | age | A | 1 | NULL | NULL | YES | BTREE | | |
+--------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)

索引创建成功!

(1) name_age_index索引存在

mysql> explain select * from tb_emp where age =123;
+----+-------------+--------+------------+-------+---------------+----------------+---------+------+------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+-------+---------------+----------------+---------+------+------+----------+--------------------------+
| 1 | SIMPLE | tb_emp | NULL | index | NULL | name_age_index | 88 | NULL | 2 | 50.00 | Using where; Using index |
+----+-------------+--------+------------+-------+---------------+----------------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)

(2) drop name_age_index索引

mysql> drop index name_age_index on tb_emp;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> explain select * from tb_emp where age =123;
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | tb_emp | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 50.00 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

在原先的认知, name+age创建的组合索引name_age_index后,如果查询条件中没有使用name,仅使用age是不会走索引的.

然而,通过上面的测试可知,Extra给出的解释是Using where; Using index ,说明它即使用了索引, 也回了表.

删除name_age_index后,Extra给出的解释只有Using where, 说明只是回表查询.

why? 不知道!

原文地址:https://www.cnblogs.com/z-qinfeng/p/12122223.html

时间: 2024-09-29 02:34:39

MySQL索引及数据结构的相关文章

深入理解Mysql索引底层数据结构与算法

深入理解Mysql索引底层数据结构与算法 ----->之前很多人还问我一些关于mysql索引的底层和使用,我就特意写一篇文章跟大家一起分享一下我对mysql索引的理解,大家有更深入的理解可以下面留言. 1.索引的定义 MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构 大家使用索引有没有想过这个问题?为什么索引能够帮助mysql高效获取数据?我一一给大家道来!在给大家讲之前,先更大家分享一些计算机基础知识,有助于理解 我们都知道mysql数据是已文件的形式存储

【一步一步学习mysql】Mysql索引底层数据结构与算法

索引是什么 索引是帮助MySQL高效获取数据的排好序的数据结构. 索引存储在文件里 补充知识: 磁盘存取原理: * 寻道时间(速度慢,费时) * 旋转时间(速度较快) 磁盘IO读取效率: * 单次IO读取是N个页的大小,读取数据量大于N个页就需要分页读取. 索引的数据结构,推荐学习网站:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html 二叉树 有可能出现worst-case,如果输入序列已经排序,则时间复杂度为O(N)

深入浅出分析MySQL索引设计背后的数据结构

在我们公司的DB规范中,明确规定: 1.建表语句必须明确指定主键 2.无特殊情况,主键必须单调递增 对于这项规定,很多研发小伙伴不理解.本文就来深入简出地分析MySQL索引设计背后的数据结构和算法,从而可以帮你释疑如下问题: 1.为什么innodb表需要主键? 2.为什么建议innodb表主键是单调递增? 3.为什么不建议innodb表主键设置过长? B-tree(多路搜索树,并不是二叉的)是一种常见的数据结构.使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度.B通常

MySQL索引背后的数据结构及算法原理

摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎 对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等.为了避免混乱,本文将只关注于BTree索 引,因为这是平常使用MySQL时主要打交道的索引,至于哈希索引和全文索引本文暂不讨论. 数据结构及算法基础 索引的本质 MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构.提取句子主干

浅谈MySQL索引背后的数据结构及算法

摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持 也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等.为了避免混乱,本文将只关注于BTree索引,因为这是 平常使用MySQL时主要打交道的索引,至于哈希索引和全文索引本文暂不讨论. 文章主要内容分为四个部分. 第一部分主要从数据结构及算法理论层面讨论MySQL数据库索引的数理基础. 第二部分结合MySQL数据库中

MySQL索引背后的数据结构及最左原则

MySQL索引原理 ##索引目的索引的目的在于提高查询效率,可以类比字典,如果要查“mysql”这个单词,我们肯定需要定位到m字母,然后从下往下找到y字母,再找到剩下的sql.如果没有索引,那么你可能需要把所有单词看一遍才能找到你想要的,如果我想找到m开头的单词呢?或者ze开头的单词呢?是不是觉得如果没有索引,这个事情根本无法完成? ##索引原理除了词典,生活中随处可见索引的例子,如火车站的车次表.图书的目录等.它们的原理都是一样的,通过不断的缩小想要获得数据的范围来筛选出最终想要的结果,同时把

[纯干货] MySQL索引背后的数据结构及算法原理

摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等.为了避免混乱,本文将只关注于BTree索引,因为这是平常使用MySQL时主要打交道的索引,至于哈希索引和全文索引本文暂不讨论. 文章主要内容分为三个部分. 第一部分主要从数据结构及算法理论层面讨论MySQL数据库索引的数理基础. 第二部分结合MySQL数据库中My

浅谈MySQL索引背后的数据结构及算法(转载)

转自:http://blogread.cn/it/article/4088?f=wb1 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等.为了避免混乱,本文将只关注于BTree索引,因为这是平常使用MySQL时主要打交道的索引,至于哈希索引和全文索引本文暂不讨论. 文章主要内容分为三个部分. 第一部分主要从数据结

MySQL索引背后的数据结构及算法原理(转)

原文:http://blog.codinglabs.org/articles/theory-of-mysql-index.html 目录 摘要 数据结构及算法基础 索引的本质 B-Tree和B+Tree 为什么实用B-Tree(B+Tree) MySQL索引实现 MyISAM索引实现 InnoDB索引实现 索引使用策略及优化 示例数据库 最左前缀原理与相关优化 索引选择性与前缀索引 InnoDB的主键选择与插入优化 后记 参考文献 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一