数据库索引,到底是什么做的(代码片段)

rinack rinack     2022-12-29     799

关键词:

问题1. 数据库为什么要设计索引?

图书馆存了1000W本图书,要从中找到《架构师之路》,一本本查,要查到什么时候去?

于是,图书管理员设计了一套规则:

  • 一楼放历史类,二楼放文学类,三楼放IT类…
  • IT类,又分软件类,硬件类…
  • 软件类,又按照书名音序排序…

以便快速找到一本书。

与之类比,数据库存储了1000W条数据,要从中找到name=”shenjian”的记录,一条条查,要查到什么时候去?

于是,要有索引,用于提升数据库的查找速度。

问题2. 哈希(hash)比树(tree)更快,索引结构为什么要设计成树型?

加速查找速度的数据结构,常见的有两类:

  • 哈希,例如HashMap,查询/插入/修改/删除的平均时间复杂度都是O(1);
  • 树,例如平衡二叉搜索树,查询/插入/修改/删除的平均时间复杂度都是O(lg(n));

可以看到,不管是读请求,还是写请求,哈希类型的索引,都要比树型的索引更快一些,那为什么,索引结构要设计成树型呢?

画外音:80%的同学,面试都答不出来。

索引设计成树形,和SQL的需求相关。

对于这样一个单行查询的SQL需求:

select * from t where name=”shenjian” 

确实是哈希索引更快,因为每次都只查询一条记录。

画外音:所以,如果业务需求都是单行访问,例如passport,确实可以使用哈希索引。

但是对于排序查询的SQL需求:

  • 分组:group by
  • 排序:order by
  • 比较:<、>

哈希型的索引,时间复杂度会退化为O(n),而树型的“有序”特性,依然能够保持O(log(n)) 的高效率。

任何脱离需求的设计都是耍流氓。

多说一句,InnoDB并不支持哈希索引。

问题3. 数据库索引为什么使用B+树?

为了保持知识体系的完整性,简单介绍下几种树。

1. 第一种:二叉搜索树

技术分享图片

二叉搜索树,如上图,是最为大家所熟知的一种数据结构,就不展开介绍了,它为什么不适合用作数据库索引?

  • 当数据量大的时候,树的高度会比较高,数据量大的时候,查询会比较慢;
  • 每个节点只存储一个记录,可能导致一次查询有很多次磁盘IO;

画外音:这个树经常出现在大学课本里,所以最为大家所熟知。

2. 第二种:B树

技术分享图片

B树,如上图,它的特点是:

  • 不再是二叉搜索,而是m叉搜索;
  • 叶子节点,非叶子节点,都存储数据;
  • 中序遍历,可以获得所有节点;

画外音,实在不想介绍这个特性:非根节点包含的关键字个数j满足,(┌m/2┐)-1 <= j <= m-1,节点分裂时要满足这个条件。

B树被作为实现索引的数据结构被创造出来,是因为它能够完美的利用“局部性原理”。

(1) 什么是局部性原理?

局部性原理的逻辑是这样的:

  • 内存读写块,磁盘读写慢,而且慢很多;
  • 磁盘预读:磁盘读写并不是按需读取,而是按页预读,一次会读一页的数据,每次加载更多的数据,如果未来要读取的数据就在这一页中,可以避免未来的磁盘IO,提高效率;(画外音:通常,一页数据是4K。)
  • 局部性原理:软件设计要尽量遵循“数据读取集中”与“使用到一个数据,大概率会使用其附近的数据”,这样磁盘预读能充分提高磁盘IO;

(2) B树为何适合做索引?

  • 由于是m分叉的,高度能够大大降低;
  • 每个节点可以存储j个记录,如果将节点大小设置为页大小,例如4K,能够充分的利用预读的特性,极大减少磁盘IO;

第三种:B+树

技术分享图片

B+树,如上图,仍是m叉搜索树,在B树的基础上,做了一些改进:

  • 非叶子节点不再存储数据,数据只存储在同一层的叶子节点上;(画外音:B+树中根到每一个节点的路径长度一样,而B树不是这样。)
  • 叶子之间,增加了链表,获取所有节点,不再需要中序遍历;

这些改进让B+树比B树有更优的特性:

  • 范围查找,定位min与max之后,中间叶子节点,就是结果集,不用中序回溯;(画外音:范围查询在SQL中用得很多,这是B+树比B树最大的优势。)
  • 叶子节点存储实际记录行,记录行相对比较紧密的存储,适合大数据量磁盘存储;非叶子节点存储记录的PK,用于查询加速,适合内存存储;
  • 非叶子节点,不存储实际记录,而只存储记录的KEY的话,那么在相同内存的情况下,B+树能够存储更多索引;

最后,量化说下,为什么m叉的B+树比二叉搜索树的高度大大大大降低?

大概计算一下:

(1)局部性原理,将一个节点的大小设为一页,一页4K,假设一个KEY有8字节,一个节点可以存储500个KEY,即j=500

(2)m叉树,大概m/2<= j <=m,即可以差不多是1000叉树

那么:

  • 一层树:1个节点,1*500个KEY,大小4K
  • 二层树:1000个节点,1000*500=50W个KEY,大小1000*4K=4M
  • 三层树:1000*1000个节点,1000*1000*500=5亿个KEY,大小1000*1000*4K=4G

画外音:额,帮忙看下有没有算错。

可以看到,存储大量的数据(5亿),并不需要太高树的深度(高度3),索引也不是太占内存(4G)。

总结

(1)数据库索引用于加速查询

(2)虽然哈希索引是O(1),树索引是O(log(n)),但SQL有很多“有序”需求,故数据库使用树型索引

(3)InnoDB不支持哈希索引

(4)数据预读的思路是:磁盘读写并不是按需读取,而是按页预读,一次会读一页的数据,每次加载更多的数据,以便未来减少磁盘IO

(5)局部性原理:软件设计要尽量遵循“数据读取集中”与“使用到一个数据,大概率会使用其附近的数据”,这样磁盘预读能充分提高磁盘IO

(6)数据库的索引最常用B+树:

  • 很适合磁盘存储,能够充分利用局部性原理,磁盘预读;
  • 很低的树高度,能够存储大量数据;
  • 索引本身占用的内存很小;
  • 能够很好的支持单点查询,范围查询,有序性查询;

索引到底能提升多少查询效率?何时该使用索引?一文快速搞懂数据库索引及合理使用它(代码片段)

一、前言无论是面试、还是日常工作中,或多或少都会使用或者听到别人谈论索引这个技术。然而很大一部份程序员对索引的了解仅限于到“加索引能使查询变快”这个概念为止。使用索引也很简单,然而,会使用索... 查看详情

到底什么是es索引?

你会发现,其实在ES里面,索引扮演的角色其实并不是存储,而是“索引”,看起来有点傻,但是其实我之前一直理解索引是存储,其实从命名上可以看出来,索引其实是分片的索引,分片的字典,记录了每个分片的位置,索引... 查看详情

特征工程到底是什么?(代码片段)

...数据将直接用于创建样本。首先,建立一个电影标题索引,以便快速进行字符串匹配[1],然后在推文中找到所有匹配的电影标题。现在规定你的样本是一些匹配,你的机器学习问题是二分类的问题:一个匹配... 查看详情

r语言中的factor到底是什么?(代码片段)

R语言中的Factor到底是什么?  因子(factors)是用于对数据进行分类(categorize)并将其存储为不同水平或者级别(levels)的数据对象。它们既可以存储字符串,也可以存储整数。Factors的唯一值是有限的。像“男”、“女”和“真”... 查看详情

mysqlforupdate到底是rowlock/tablelock(代码片段)

...文末。本文测试的环境为MySQL8.0.21验证MySQLforupdate时使用索引检索数据的情况下,使用的是rowlock,而不使用索引检索数据的话,是tablelock,下面我们先来通过实验验证这个说法。打开两个MySQ 查看详情

数据库面试总结(代码片段)

数据库索引左连接右连接内连接什么是最左前缀原则?什么是最左匹配原则数据库为什么使用B+树而不是B树红黑树红黑树统计性能比AVL树更高索引失效索引分类主键索引和唯一索引的区别哪些情况需要索引哪些情况不要创... 查看详情

关于mysql,你未必知道的!

...讲解MySQL索引底层实现,也是阅读量最高的几篇之一。《数据库索引,到底是什么做的?》这一篇,介绍了哈希索引,树索引,数据预读/局部性原理,B+树的优化思路。《MyISAM与InnoDB的索引差异究竟是啥?》在上一篇基础之上,... 查看详情

sqlserver事务日志的lsn到底是什么?(代码片段)

一:背景1.讲故事大家都知道数据库应用程序它天生需要围绕着数据文件打转,诸如包含数据的.mdf,事务日志的.ldf,很多时候深入了解这两类文件的合成原理,差不多对数据库就能理解一半了,关于.mdf的合成前面的文章已经有... 查看详情

关于mysql索引(代码片段)

文章目录MySQL索引是什么?索引的优势索引的劣势什么时候适合建立索引?什么时候不适合建立索引?一般性建议MySQL索引分类如何避免索引失效?MySQL索引是什么?官方定义:索引(INDEX)是帮助mys... 查看详情

servlet到底是什么?(代码片段)

servlet到底是什么?对于这个问题一直云里雾里的,今天打算刨根问底。一、Servlet简介  Servlet是sun公司提供的一门用于开发动态web资源的技术。  Sun公司在其API中提供了一个servlet接口,用户若想用发... 查看详情

oracle中的incarnation到底是个什么?实验操作篇(代码片段)

...篇》。目录1.官方图示例2.场景模拟3.实验步骤  3.1备份数据库(略)  3.2 查询当前数据库化身版本  3.3按场景模拟操作  3.4恢复出B表并打开数据库  3.5查询当前数据库 查看详情

数据库(代码片段)

前言本篇博客内容为索引,索引是为了提高数据库的查询效率。索引什么是索引?索引就相当于书的目录,是mysql中一种专门的数据结构,称为key,索引的本质原理就是通过不断地缩小查询范围,来降低io次数从而提升查询性能... 查看详情

如何快速检索?(代码片段)

...?Elasticsearch是通过Lucene的倒排索引技术实现比关系型数据库更快的过滤。特别是它对多条件的过滤支持非常好,比如年龄在18和30之间,性别为女性这样的组合查询。倒排索引很多地方都有介绍,但是其比关系型... 查看详情

一文彻底搞懂cookiesessiontoken到底是什么(代码片段)

...注“终端研发部”设为“星标”,和你一起掌握更多数据库知识责编:架构君 | 来源:不学无数的程序员链接:https://my.oschina.net/u/4030990/blog/3136476上一篇好文:MySQL数据库的优化,你知道有哪些?大家... 查看详情

day868.索引(上)-mysql实战(代码片段)

索引(上)Hi,我是阿昌,今天学习记录的是关于索引(上)的内容。某一个SQL查询比较慢,分析完原因之后,可能就会说“给某个字段加个索引吧”之类的解决方案。但到底什么是索引,索引... 查看详情

sqlserver事务日志lsn到底是什么?(代码片段)

一:背景1.讲故事大家都知道数据库应用程序它天生需要围绕着数据文件打转,诸如包含数据的.mdf,事务日志的.ldf,很多时候深入了解这两类文件的合成原理,差不多对数据库就能理解一半了,关于.mdf的... 查看详情

mysql基础篇之索引上--04(代码片段)

...引的常见模型InnoDB的索引模型索引维护小结补充引言提到数据库索引,我想你并不陌生,在日常工作中会经常接触到。比如某一个SQL查询比较慢,分析完原因之后,你可能就会说“给某个字段加个索引吧”之类的... 查看详情

时间序列数据库的秘密——索引(代码片段)

...索?Elasticsearch是通过Lucene的倒排索引技术实现比关系型数据库更快的过滤。特别是它对多条件的过滤支持非常好,比如年龄在18和30之间,性别为女性这样的组合查询。倒排索引很多地方都有介绍,但是其比关系型数据库的b-tree... 查看详情