索引是如何提高查询性能的?

引言

问:如何提高一条查询SQL的性能?

答:最常用的方式就是加「索引」。

问:索引为什么就能提高查询性能?

答:索引就像一本书的目录,用目录查当然很快。

问:为什么通过目录就能提高查询速度呢。

答:……

都知道通过书目可以快速查询,这只是表象,背后的原因到底是什么呢?

下面就来扒一扒。



二叉树

由 n( n > 0)个有限节点组成一个具有层次关系的集合,看起来就像一个倒挂的树,因此称这样的数据结构为树。

一个节点的子节点个数叫做度,通俗的讲就是树叉的个数。树中最大的度叫做树的度,也叫做阶。一个 2 阶树最多有 2 个子节点即最多有 2 叉,因此这样的树称为二叉树。

二叉树是树家族中最简单的树。

二分查找


下面这幅动图就为二分查找的基本过程,也是最简单的一种二分查找。

每次都把查询的范围减半,时间复杂度log2(n)。

单纯的一次查询,先排序,再二分查找,不见得比逐一扫描快。但是,大部分数据一生会被查询无数次,如果只在数据产生的时候排一次序,以后是不是就可以直接用二分查找。

优点:

  • 查找快

缺点:

  • 必须有序,需要提前排序
  • 每次查找都需要不断计算中间位置

二分查找树

假设一组数据不常变更,那么他们的位置也基本不变。可是每次查询都需要重新计算中间位置是一种浪费。

我们能不能把所有中间节点组织起来,每次使用时,直接取中间节点?

如图,找到所有单次二分查找的中间节点,把他们连起来,并用手提起最中间的那个节点,就是一棵二分查找树。

优点:


二分查找树就是通过数据结构的方式实现了二分查找算法,通过存储中间节点的数据,弥补了二分查找每次都要计算中间位置的缺点。

平衡二叉树

如果二分查找树不断进行修改,比如删除某些节点,经过一段时间后,最早那个中间节点的数据(根),很可能就不在中间了。

中间位置就像一个天平的支点,如果他不在中间了,那么整个天平就会失衡,失衡的世界就会坍塌成不伦不类的瘸树,甚至是降维成一个链表或者数组。

二分查找算法的关键在于有序和中间节点,而二分查找树的关键是中间节点的维护,如果维护的节点已经不在中间了,那么它就失去了意义。

所以必须保证「二分查找树」是一个正确的树,一个根节点在中心的树,一个左右子树层级(高度)基本相等(高度相差不超过1)的树,一个平衡的树。

平衡二叉树中最常见的就是红黑树:

红黑树规定了一系列节点颜色规则,以及对应的左旋和右旋操作来保证颜色规则,从而达到树的平衡性。


看到这花里胡哨的颜色以及复杂的规则,让人第一眼就望而却步,但所有的这些,也不过是为了保证二叉树的平衡性,由于维持平衡的操作太过麻烦,无法用一句话简单概括,只好用一堆人鬼难分的规则和步骤来实现,只要按着这些步骤就一定能实现二叉树的平衡。

平衡二叉树  =  二分查找树 + 平衡(左右高度相差不超过 1 )

平衡二叉树并未提高二分查找树的性能,它只是保正树不会被二向箔(多次增删改)打击降维成链表或不对称的残缺树,永远维持平衡。

另外,不仅仅是二叉树,其他种类的树,也是需要有序和平衡,才能发挥最大的威力。

多叉树(B-tree)

两个叉的树就能折半查询,理论可以提高一倍性能,那么多个叉是不是能提高更多倍性能?

如下图的 3 叉树

每个节点维护两个数据,并指向最多 3 个子节点。如图 3 个子节点的数据分别为:小于 17, 17 ~ 35 ,大于 35。


假设,从上图中查找 10 这个数,步骤如下:

  • 找到根节点,对比 10 与 17 和 35 的大小,发现 10 < 17 在左子节点,也就是第 2 层节点;
  • 从根节点的指针,找到左子节点,对比 10 与 8 和 12 的大小,发现 8 < 10 < 12,数据在当前节点的中间子节点,也就是第 3 层节点;
  • 通过上步节点的指针,找到中间子节点(第 3 层节点),对比 10 与 9 和 10 的大小,发现 9 < 10 == 10,因此找到当前节点的第二数即为结果。

加上忽略的 12 个数据,从 26 个数据中查找一个数字 10,仅仅用了 log3(26)≈ 3 次,而如果用平衡二叉树,则需要 log2(26)≈ 5 次,事实证明,多叉树确实可以再次提高查找性能。

多叉树是在二分查找树的基础上,增加单个节点的数据存储数量,同时增加了树的子节点数,一次计算可以把查找范围缩小更多。

多叉树之 B+tree

做为数据库的索引,无论用什么样的数据结构维护,这些数据最终都会存储到磁盘中。

鉴于磁盘  I/O 的性能问题,以及每次 I/O 获取数据量上限所限,提高索引本身 I/O 的方法最好是,减少 I/O 次数和每次获取有用的数据。

B-tree 已经大大改进了树家族的性能,它把多个数据集中存储在一个节点中,本身就可能减少了 I/O 次数或者寻道次数。

但是仍然有一个致命的缺陷,那就是它的索引数据与业务绑定在一块,而业务数据的大小很有可能远远超过了索引数据,这会大大减小一次 I/O 有用数据的获取,间接的增加 I/O 次数去获取有用的索引数据。

因为业务数据才是我们查询最终的目的,但是它又是在「二分」查找中途过程无用的数据,因此,如果只把业务数据存储在最终查询到的那个节点是不是就可以了?

理想很丰满,现实很骨瘦如柴,谁知道哪个节点就是最终要查询的节点呢?

B+tree 横空出世,B+ 树就是为了拆分索引数据与业务数据的平衡多叉树。

B+ 树中,非叶子节点只保存索引数据,叶子节点保存索引数据与业务数据。这样即保证了叶子节点的简约干净,数据量大大减小,又保证了最终能查到对应的业务数。既提高了单次 I/O 数据的有效性,又减少了 I/O 次数,还实现了业务。


但是,在数据中索引与数据是分离的,不像示例那样的?

如图:我们只需要把真实的业务数据,换成数据所在地址就可以了,此时,业务数据所在的地址在 B+ 树中充当业务数据。

树的结构最大的优点就是查询性能高,因此所有需要提高查询性能的都可以考虑树。


而现实中也确实有这样的例子,比如:

  • HashMap 中的数据冲突时,链表转化成红黑树;
  • 数据库索引使用的 B+ 树;
  • 搜索引擎倒排索引使用的字典树;

以上只是描述了数据库使用 B+ 树索引为什么能提高查询性能原因及简单过程。

并没有深入各种数据结构的细节,仅仅是,让大家对索引有一个感性的认识。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/271850.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

restTemplate支持https忽略证书

由于公司的某个服务器由http转为https&#xff0c;导致原先的接口不可用&#xff0c;不过网上一堆忽略ssl都可以用就不多写了&#xff0c;写几个奇葩的问题 首先报错都是 sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.cert…

前端开发之通过vue-office组件实现文件预览

前端开发之通过vue-office组件实现文件预览 前言效果图docx文件xlsx文件pdf文件 vue中简单案例1、安装组件2、vue中代码 前言 在实现文件预览的时候我们可以通过vue-office组件来实现文件的预览效果 效果图 docx文件 xlsx文件 pdf文件 vue中简单案例 1、安装组件 整体安装…

Intel® SGX Instruction References(五)

文章目录 前言一、Intel SGX Instruction Syntax and Operation1.1 ENCLS Register Usage Summary1.2 ENCLU Register Usage Summary1.3 ENCLV Register Usage Summary1.4 Information and Error Codes1.5 Internal CREGs1.6 Concurrent Operation Restrictions 二、Intel SGX …

腾讯云4核8G服务器三年优惠价格表

腾讯云轻量服务器4核8G12M有三年优惠价吗&#xff1f;有&#xff0c;但是不怎么优势&#xff0c;相对于云轻量2核2G4M带宽三年价格是540元、2核4G5M带宽3年优惠价756元&#xff0c;4核8G12M轻量应用服务器三年价格是5292元&#xff0c;怎么样&#xff1f;还想买吗&#xff1f;阿…

个性化定制的知识付费小程序,为用户提供个性化的知识服务,知识付费saas租户平台

明理信息科技知识付费saas租户平台 在当今数字化时代&#xff0c;知识付费已经成为一种趋势&#xff0c;越来越多的人愿意为有价值的知识付费。然而&#xff0c;公共知识付费平台虽然内容丰富&#xff0c;但难以满足个人或企业个性化的需求和品牌打造。同时&#xff0c;开发和…

FCIS 2023网络安全创新大会-核心PPT资料下载

一、峰会简介 本次会议的主题是“AI大模型、人工智能与智能制造安全、攻击面管理与供应链安全”。 1、AI大模型 会议首先探讨了AI大模型在网络安全领域的应用。AI大模型是一种基于深度学习的模型&#xff0c;具有强大的特征提取和分类能力&#xff0c;可以用于检测和防御各种…

一开始我还不信!高德导航红绿灯竟然能读秒?

高德导航红绿灯为啥能读秒&#xff1f; 1 内部员工吐露 每天工作其实就是负责自己片区的红绿灯&#xff0c;一大早就去校对时间&#xff0c;然后发布到后台。是的&#xff0c;统计出来的&#xff0c;而且还是人工统计&#xff0c;有误差请见谅[害羞] 真的是很辛苦了&#xf…

低代码平台:明年IT规划的关键

背景 在这个快速变化的世界中&#xff0c;企业面临前所未有的挑战。明年的经济形势预计将遭遇巨大变化&#xff0c;全球市场也正在经历深刻调整。在这样的环境下&#xff0c;企业的应用系统也面临着重新评估和调整的需求。为了保持竞争力&#xff0c;企业必须确保其IT系统不仅…

WAVE SUMMIT迎来第十届,文心一言将有最新披露!

10句话2分钟&#xff0c;挑战成功说服宿管阿姨开门&#xff0c;这个人群中的“显眼包”是一个接入文心大模型4.0游戏里的NPC&#xff0c;妥妥 “工具人”实锤&#xff5e; 尝试用AI一键自动识别好坏咖啡豆&#xff0c;看一眼便知好坏&#xff0c;真正“颜值即正义”&#xff0c…

手写Promise完整介绍

✨ 专栏介绍 在现代Web开发中&#xff0c;JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性&#xff0c;还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言&#xff0c;JavaScript具有广泛的应用场景&#x…

一文看懂所有字符编码标准

文章目录 ASCII128个符号不够用欧洲国家亚洲国家 GB2312GBKGB18030UnicodeUTF-8 QA最高位b7是什么意思?UTF-8和UTF-16的区别UTF-8和UTF-32的区别 ASCII ASCII&#xff08;American Standard Code for Information Interchange&#xff09;是一种字符编码标准&#xff0c;最初…

基于业务功能级别的流量控制

之前产品线上发生过若干次因为tomcat连接池被耗尽而导致宕机的故障&#xff0c;而具体根源原因则各不尽相同。有因为调用和被调用的服务申请相同的分布式锁而导致死锁的&#xff0c;有因为发送内部或外部的JMS消息发生堵塞的&#xff0c;有因为某个存在性能问题的接口被较多调用…

如何使用队列处理 API 速率限制

对于遇到速率限制的应用程序来说也是一个挑战&#xff0c;因为它需要“放慢速度”或暂停。这是一个典型的场景&#xff1a; 初始请求&#xff1a;当应用程序发起与 API 的通信时&#xff0c;它会请求特定的数据或功能。API 响应&#xff1a; API 处理请求并响应请求的信息或执…

linxu重启网络服务失败——Failed to start LSB: Bring up/down networking.

一、出现问题的场景 在虚拟机中的Linux系统启动后&#xff0c;发现没有网络&#xff0c;执行ifconfig 发现自己配置的ens33网卡没有启动。 接着&#xff0c;执行systemctl restart network 重启网络服务失败 查看网络状态&#xff0c;执行 systemctl status network 发现报错…

有什么好用的C/C++源代码混淆工具?

​ 有什么好用的C/C源代码混淆工具&#xff1f; 开始使用ipaguard 前言 iOS加固保护是直接针对ios ipa二进制文件的保护技术&#xff0c;可以对iOS APP中的可执行文件进行深度混淆、加密。使用任何工具都无法逆向、破解还原源文件。对APP进行完整性保护&#xff0c;防止应用…

圣诞树(动态效果)

一、运行效果 二、制作方法 1.复制代码到Dreamweaver或HBuilder或vscode中 2.点击运行---运行到浏览器---选择你要打开的浏览器 3.打开后会出现这个界面&#xff0c;前四个是固定音乐&#xff0c;最后一个是自主选择的音乐&#xff0c;你可以选择你电脑上的歌曲&#xff0c…

CCF-CSP真题《202309-2 坐标变换(其二)》思路+python,c++满分题解

想查看其他题的真题及题解的同学可以前往查看&#xff1a;CCF-CSP真题附题解大全 试题编号&#xff1a;202309-2试题名称&#xff1a;坐标变换&#xff08;其二&#xff09;时间限制&#xff1a;2.0s内存限制&#xff1a;512.0MB问题描述&#xff1a; 问题描述 对于平面直角坐标…

vue项目中使用axios发送http请求添加header自定义变量出现跨域问题

request代码片段&#xff1a; export const request (api,method,params {},config,responseType {} ) > {let apiToken localStorage.getItem("token");let headers {Authorization: ${apiToken},};if (config?.headers) {headers {...headers,...config…

java:4-7运算符优先级

运算符优先级 运算符有不同的优先级&#xff0c;所谓优先级就是表达式运算中的运算顺序。如右表&#xff0c;上一行运算符总优先于下一行。只有单目运算符&#xff08;第二行&#xff09;、赋值运算符&#xff08;倒数3行&#xff09;是从右向左运算的。一览表, 不要背&#x…

SecuSphere:一款功能强大的一站式高效DevSecOps安全框架

关于SecuSphere SecuSphere是一款功能强大的一站式高效DevSecOps解决方案&#xff0c;DevSecOps作为一个经过针对性设计的集中式平台&#xff0c;可以帮助广大研究人员管理和优化漏洞管理、CI/CD管道集成、安全评估和DevSecOps实践。 SecuSphere是一个功能全面的DevSecOps平台…