数据库索引,到底是什么做的?-- 转自沈剑公众号
问题1. 数据库为什么要设计索引?
图书馆存了1000W本图书,要从中找到《架构师之路》,一本本查,要查到什么时候去?
于是,图书管理员设计了一套规则:
(1)一楼放历史类,二楼放文学类,三楼放IT类…
(2)IT类,又分软件类,硬件类…
(3)软件类,又按照书名音序排序…
以便快速找到一本书。
与之类比,数据库存储了1000W条数据,要从中找到name=”shenjian”的记录,一条条查,要查到什么时候去?
于是,要有索引,用于提升数据库的查找速度。
问题2. 哈希(hash)比树(tree)更快,索引结构为什么要设计成树型?
加速查找速度的数据结构,常见的有两类:
(1)哈希,例如HashMap,查询/插入/修改/删除的平均时间复杂度都是O(1);
(2)树,例如平衡二叉搜索树,查询/插入/修改/删除的平均时间复杂度都是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)当数据量大的时候,树的高度会比较高,数据量大的时候,查询会比较慢;
(2)每个节点只存储一个记录,可能导致一次查询有很多次磁盘IO;
画外音:这个树经常出现在大学课本里,所以最为大家所熟知。
第二种:B树
B树,如上图,它的特点是:
(1)不再是二叉搜索,而是m叉搜索;
(2)叶子节点,非叶子节点,都存储数据;
(3)中序遍历,可以获得所有节点;
画外音,实在不想介绍这个特性:非根节点包含的关键字个数j满足,(┌m/2┐)-1 <= j <= m-1,节点分裂时要满足这个条件。
B树被作为实现索引的数据结构被创造出来,是因为它能够完美的利用“局部性原理”。
什么是局部性原理?
局部性原理的逻辑是这样的:
(1)内存读写块,磁盘读写慢,而且慢很多;
(2)磁盘预读:磁盘读写并不是按需读取,而是按页预读,一次会读一页的数据,每次加载更多的数据,如果未来要读取的数据就在这一页中,可以避免未来的磁盘IO,提高效率;
画外音:通常,一页数据是4K。
(3)局部性原理:软件设计要尽量遵循“数据读取集中”与“使用到一个数据,大概率会使用其附近的数据”,这样磁盘预读能充分提高磁盘IO;
B树为何适合做索引?
(1)由于是m分叉的,高度能够大大降低;
(2)每个节点可以存储j个记录,如果将节点大小设置为页大小,例如4K,能够充分的利用预读的特性,极大减少磁盘IO;
第三种:B+树
B+树,如上图,仍是m叉搜索树,在B树的基础上,做了一些改进:
(1)非叶子节点不再存储数据,数据只存储在同一层的叶子节点上;
画外音:B+树中根到每一个节点的路径长度一样,而B树不是这样。
(2)叶子之间,增加了链表,获取所有节点,不再需要中序遍历;
这些改进让B+树比B树有更优的特性:
(1)范围查找,定位min与max之后,中间叶子节点,就是结果集,不用中序回溯;
画外音:范围查询在SQL中用得很多,这是B+树比B树最大的优势。
(2)叶子节点存储实际记录行,记录行相对比较紧密的存储,适合大数据量磁盘存储;非叶子节点存储记录的PK,用于查询加速,适合内存存储;
(3)非叶子节点,不存储实际记录,而只存储记录的KEY的话,那么在相同内存的情况下,B+树能够存储更多索引;
最后,量化说下,为什么m叉的B+树比二叉搜索树的高度大大大大降低?
大概计算一下:
(1)局部性原理,将一个节点的大小设为一页,一页4K,假设一个KEY有8字节,一个节点可以存储500个KEY,即j=500
(2)m叉树,大概m/2<= j <=m,即可以差不多是1000叉树
(3)那么:
一层树: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)。
总结
数据库索引用于加速查询
虽然哈希索引是O(1),树索引是O(log(n)),但SQL有很多“有序”需求,故数据库使用树型索引
InnoDB不支持哈希索引
数据预读的思路是:磁盘读写并不是按需读取,而是按页预读,一次会读一页的数据,每次加载更多的数据,以便未来减少磁盘IO
局部性原理:软件设计要尽量遵循“数据读取集中”与“使用到一个数据,大概率会使用其附近的数据”,这样磁盘预读能充分提高磁盘IO
数据库的索引最常用B+树:
(1)很适合磁盘存储,能够充分利用局部性原理,磁盘预读;
(2)很低的树高度,能够存储大量数据;
(3)索引本身占用的内存很小;
(4)能够很好的支持单点查询,范围查询,有序性查询;
数据库索引,到底是什么做的?-- 转自沈剑公众号相关推荐
- 用新华字典来彻底解释清:数据库索引到底是什么
点击上方蓝字设为星标 下面开始今天的学习- 作者:兜里有辣条 来源:segmentfault.com/a/1190000018153249 说在前面 数据库超级重要,这个大家应该清楚,学过数据库的 ...
- 数据库怎么用Java做封面_一个毫无用处的公众号封面生成器
一个毫无用处的公众号封面生成器 对于一个没有任何艺术细胞的人,写公众号最头疼的无异于文章封面了. 要么选不好图,选好图了呢,公众号这个2.35:1的诡异比例还会涉及到裁剪的问题... 所以或许你已经发 ...
- 如何做一个能赚钱的技术公众号?
晓衡上周去了趟苏州,有幸参考技术圈公众号主的聚会.回来后,有朋友问我有些什么收获,这此收获最大在于了解到了关于技术公众号是如何赚钱的逻辑.而且我也发现社区有越来越多的发者,开始尝试在公众号上发自己的技 ...
- PHP怎么做微信助力,微信助力活动怎么做?教你如何在公众号制作微信助力活动...
微信助力活动是什么?简单的来说是一个依靠分享粉丝给自己助力,也叫微助力或分享助力,助力活动以后有个排行榜,商家可以根据排名,给予一定的物质奖励,可以吸引来大量的新人关注公众号,下面具体介绍微信公众号助 ...
- 分享公众号预约怎么做_教你实现微信公众号预约制作步骤的方法
在日常生活中,我们身边有着各种各样的微信公众号预约系统,例如门诊挂号预约或者各种报名预约,通过在线的报名预约系统,用户不用在跑去现场进行预约,这样极大的方便了用户,同时也方便商家统一管理用户的预约订单 ...
- 怎样做一个网课查题公众号
成品效果图如下 方便又简单的教程 步骤一:进入微信公平台官网(https://mp.weixin.qq.com)按照指引注册. 详细教程 第一步点击右上角立即注册 如已注册微信公众号扫码即可登录 步骤 ...
- 数据库索引如何工作?原理
原文地址:https://blog.csdn.net/weiliangliang111/article/details/51333169 数据库索引到底是什么,是怎样工作的? 我们通过一个简单的例子来 ...
- 白杨SEO:做个世界杯公众号怎么样?以2022年卡塔尔世界杯来做微信搜一搜的SEO流量实战举例
做个世界杯公众号怎么样? 如上图,图片在公众号白杨SEO上去看.同样是世界杯,同样是站长,有人只关注到世界杯本身,有人开始关注思考到搞世界杯流量,尤其微信上公众号流量,不再局限于网站流量. 但是,即使 ...
- 白杨SEO:公众号、小程序微信服务搜索怎么做?搜一搜服务搜索排名规则解析
新知达人, 白杨SEO:公众号.小程序怎么做微信服务搜索? 大纲如下: 1.搜一搜功能有哪些?品牌官方区怎么申请和条件? 2.微信搜一搜的服务搜索是什么? 3.微信公众号怎么做服务搜索? 4.微信小程 ...
最新文章
- SpringBoot 2.x 使用 JWT(JSON Web Token)
- 遇见BUG(1):都是非时钟专用引脚惹的祸?
- 【深度学习笔记】Precision、Recall
- WINCE开机显示logo之前先显示白屏的问题
- Spring Boot 整合 Redis 实现缓存操作
- mybatis collection_MyBatis之关联查询
- Mapreduce的分区—Partitioner
- Java修饰符public,private,protected及默认的区别
- 2020定额水平测算——“15定额工程”一键转换“20定额工程”
- 大学计算机试题深圳大学,深圳大学期末考试试卷参考答案.doc
- SPOJ COT 10628 Count on a tree
- SAR影像辐射定标工程化实现之COSMO-Skymod
- LVDS 显示屏的两种接口标准:VESA 和 JEIDA;单/双路 LVDS 信号
- 都没滤网质量重要 细数净化器鸡肋功能
- 计算机网络实验(华为eNSP模拟器)——第十一章 帧中继网络
- Unity 之 音频类型和编码格式介绍
- 线性探测法和平方探测法 - 哈希表 - 完整代码
- Android 读取系统联系人
- 下载与安装nexus3
- 计算机视觉方向就业怎么样?可以做什么?
热门文章
- 阿里安全潘多拉实验室首先完美越狱苹果iOS 11.2
- android 获取图片的真实地址
- 自签发SSL证书签发生成过程
- 全国增值税发票查验平台 | 免验证码
- SQL如何合并两个表
- 基于爬虫+人脸识别库实现指定人物自动采集
- JPA设置in参数时报错(Encountered array-valued parameter binding, but was expecting [java.lang.String (n/a)])
- 可视化Docker管理工具-DockerUI
- java实现模拟鼠标键盘操作
- swagger 源代码_我们如何使用swagger代码生成器从Angular 4更新到Angular 5