一、数据库索引介绍

数据库索引

索引是加速表的查询效率而创建的数据结构

日常场景:新华字典的目录类似一个索引。

构造一个索引过程例子

user_id/索引列

磁盘地址

磁盘地址

order_id/主键

user_id

shop_id

create_time

status

amount

delivery_amount

1000

0x01

0x01

1

1000

7567

2/19/2020 13:56

1

100

2

4000

0x04

0x02

2

6700

7670

2/19/2020 13:56

1

101

3

5643

0x03

0x03

3

5643

3450

2/19/2020 13:56

1

102

4

6700

0x02

0x04

4

4000

5660

2/19/2020 13:56

1

103

5

6700

0x05

0x05

5

6700

4356

2/19/2020 13:56

1

104

6

8880

0x06

0x06

6

8880

4356

2/19/2020 13:56

1

105

7

● 索引是一个有序结构

       ○ 有序的结构可以提高查找的效率【不仅仅可以采用二分查找,可以构造多叉有序结构提高查找效率】

       ○ 无序的结构的查找需要遍历

● 索引可以减少存储引擎(MYSQL)的查询数据量

        ○ 索引是有序结构、避免了全表扫描

        ○ 索引列少,占用的存储量少

● 将随机IO变成有序IO

        ○ 业务写入是无序的、从有序的结构中检索

        ○ 一般而言,无序的东西是没有价值的。【将随机变成有序是一种架构】

        ○ 写性能和读性能的平衡(架构)、并发处理的解决方案

 ● 提高分组、排序效率,避免使用临时表

        ○ 对有序结构遍历就可以完成分组、排序

        ○ 全表扫描、内存不够就需要使用临时表

二、Hash索引的原理和应用

通过元素的Hash函数直接计算出元素的地址的索引。

    - Hash(4000)=0x04

    - 实际上这种算法是不存在的

    真实的Hash索引是基于Hash表的数据结构

mysql内连接索引 mysql索引结构如何实现_数据库

Hash表的基础结构

     ● 数组 例子中有13个元素、

             ○ 对元素进行分治分桶处理。

             ○ 数组可以快速的通过下标定位元素。

     ● 链表 例子中是向上的结构

             ○ 处理元素Hash碰撞导致的数组地址重复问题

     ● Hash算法

             ○ 计算元素在数组中的位置坐标。

             ○ 常见的Hash算法

                     ● 第一步 元素(字符串)Hash运算取整

                     ● Hash整数对数组取余

Hash索引的应用场景

     ● 数据结构中使用HashMap

     ● 小数据量的内存索引中

     ● 内存数据库中会使用Hash索引

     ● INNODB也是使用Hash索引

三、B树、B+树结构和应用场景

B树、B+树 多路树、多二叉树的扩展。

B树、B+树 数据结构的差异

● B+树最末端叶子节点包含所有的元素、B树是整棵树包含所有的元素

● B+树的最末端叶子节点是链表

user_id/索引列

磁盘地址

磁盘地址

order_id/主键

user_id

shop_id

create_time

status

amount

delivery_amount

1000

0x01

0x01

1

1000

7567

2/19/2020 13:56

1

100

2

4000

0x04

0x02

2

6700

7670

2/19/2020 13:56

1

101

3

5643

0x03

0x03

3

5643

3450

2/19/2020 13:56

1

102

4

6700

0x02

0x04

4

4000

5660

2/19/2020 13:56

1

103

5

6700

0x05

0x05

5

6700

4356

2/19/2020 13:56

1

104

6

8880

0x06

0x06

6

8880

4356

2/19/2020 13:56

1

105

7

mysql内连接索引 mysql索引结构如何实现_数据库_02

mysql内连接索引 mysql索引结构如何实现_mysql内连接索引_03

 B+树索引的优良特性

● B系列树的多路特性(节点可以容纳更多的关键字、元素)、整棵树的层级会非常浅、可以充分利用操作系统的分页读取特性(Linux操作系统每次读取4KB页数据、MYSQL每页是16KB)、可以将索引单节点完全加载到内存。

● B+树非最末端叶子节点只需要存储下级节点的地址(指针)、B+树的非末端叶子节点每页可以容纳更多的关键字(元素)、B树还要存储数据、B+树的非末端叶子节点可以容纳多少元素是可以被计算出来的。

● B+树的最末端叶子节点是链表、如果你需要遍历,只需要顺序读取就可以了。

B+树的应用场景

● 数据库的索引

● 大数量的场景都可以作为快速查找的目录结构

四、二叉树结构和索引的关系

常见的有序二叉树

● 二叉查找树 极端情况会退化成链表、丧失平衡性、无法体现二分查找的优越性【LogN】

● AVL树 完美平衡的树、但是自平衡效率非常低

● 红黑树 非完美平衡的树、黑色完美平衡的树、自平衡效率优良

二叉树结构不适合数据库索引原因

● 节点稀疏 一个节点只有一个元素(关键字)、很难利用操作系统页读取和存储的特性

● 节点深100万的二叉树结构,层级至少为20以上【20次的IO对于数据库而言是灾难性的】

● 二叉树结构难以连续的读取

二叉树结构的应用场景

    ● 非数据密集型的小数据集场景

           ○ 红黑树HashMap数据结构中

           ○ Linux NIO Epoll网络编程模型 使用了红黑树结构

二叉树结构对数据库索引的启发关系

    ● 减少层级

    ● 增加页内元素的数量

    ● 叶子结点使用双向链表的结构

五、InnoDB聚簇索引原理

MySQL聚簇索引

聚簇索引定义:行数据存放在B+树索引的叶子节点上。一般而言聚簇索引和主键索引是相同的。

聚簇索引是表记录的存储方式。使用聚簇索引的表叫索引组织表

MySQL InnoDB 存储引擎使用的就是索引组织表。

通俗的将聚簇索引理解为数据和索引聚集在一起的索引。

构造MySQL聚簇索引

    ● 第一步 使用主键列构造B+树结构

    ● 第二步 将表的行记录添加到B+树的叶子节点上

六、InnoDB聚簇索引性能优化

聚簇索引的构造原理

● MySQL聚簇索引默认使用主键索引

● MySQL聚簇索引会使用非空唯一键索引

● 没有主键索引、非空唯一键索引。INNODB会在表的列中增加ROWID列作为隐形主键

聚簇索引性能优化

使用INNODB的自增ID作为主键。

● MySQL INNODB 的每张表都要有一个自增的主键【被推荐】【顺序递增的主键索引一般而言是追加操作】

● UUID主键、随机数主键【不推荐】【乱序的主键、索引要分裂节点、移动最末端叶子节点内的元素】

● 不推荐使用多列的组合主键【ABCDEFG7列,使用ABC三列主键,组合主键会增加索引的稀疏度,增加磁盘的存储】

七、InnoDB可以存储多少行数据

B+树、聚簇索引、索引组织表。

高性能的索引组织表 要求B+树深度不大于3(每次索引读取只需要3次IO)。

计算3层B+树可以存多少行表数据

第一层 16K=131072bit 关键字为64bit的整型,关键字下层的页指针64bit,第一层可以存储131072 / 128=1024页

第二层 可以存储1024*1024=1048576页

第三层 大约可以存储1048576*16=16777216行记录。假设一行表记录大小是1KB,每页可以存储16行记录。

MYSQL Innodb理论的行数是一千多万。实际工作中,MySQL Innodb每张表不要超过500万。

八、InnoDB辅助索引原理

除聚簇索引之外创建的索引

单列索引 只有一个列的辅助索引

联合索引 有多个列的辅助索引

唯一键索引 多了一个唯一性约束、可以是单列索引、联合索引

InnoDB 辅助索引的特点

● 辅助索引的索引值是主键,不是表记录的地址(指针)

● 使用innoDB辅助索引检索的时候需要进行两次索引的查询。

● 两次索引的查询过程:先读取辅助索引,再读取聚簇索引(主键索引)。

九、MyISAM非聚簇索引

MyISAM存储引擎、Oracle关系型数据库。

表行数据和索引是分开存储的。使用非聚簇索引存储结构的表叫堆表。【分为索引文件和数据文件】

优点:

    ● 表的写入速度会非常快【采用无序追加的方式写数据】

    ● 表的记录数可以容纳更多,三层非聚簇索引B+树可以容纳1073741824行数据。【公式1024的三次方】

构造一个非聚簇索引

    ● 表行记录数据还是分页存储,每页16K

    ● B+树索引的每个节点分页存储,每页16K