深入浅出数据库索引原理

article/2025/9/11 13:58:04

    使用索引很简单,只要能写创建表的语句,就肯定能写创建索引的语句,要知道这个世界上是不存在不会创建表的服务器端程序员的。然而, 会使用索引是一回事, 而深入理解索引原理又能恰到好处使用索引又是另一回事,这完全是两个天差地别的境界(我自己也还没有达到这层境界)。很大一部份程序员对索引的了解仅限于到“加索引能使查询变快”这个概念为止。

  • 为什么要给表加上主键?

  • 为什么加索引后会使查询变快?

  • 为什么加索引后会使写入、修改、删除变慢?

  • 什么情况下要同时在两个字段上建索引?

    这些问题他们可能不一定能说出答案。知道这些问题的答案有什么好处呢?如果开发的应用使用的数据库表中只有1万条数据,那么了解与不了解真的没有差别, 然而, 如果开发的应用有几百上千万甚至亿级别的数据,那么不深入了解索引的原理, 写出来程序就根本跑不动,就好比如果给货车装个轿车的引擎,这货车还能拉的动货吗?

    接下来就讲解一下上面提出的几个问题,希望对阅读者有帮助。

    网上很多讲解索引的文章对索引的描述是这样的「索引就像书的目录, 通过书的目录就准确的定位到了书籍具体的内容」,这句话描述的非常正确, 但就像脱了裤子放屁,说了跟没说一样,通过目录查找书的内容自然是要比一页一页的翻书找来的快,同样使用的索引的人难到会不知道,通过索引定位到数据比直接一条一条的查询来的快,不然他们为什么要建索引。

    想要理解索引原理必须清楚一种数据结构「平衡树」(非二叉),也就是b tree或者 b+ tree,重要的事情说三遍:“平衡树,平衡树,平衡树”。当然, 有的数据库也使用哈希桶作用索引的数据结构 , 然而, 主流的RDBMS都是把平衡树当做数据表默认的索引数据结构的。

    我们平时建表的时候都会为表加上主键, 在某些关系数据库中, 如果建表时不指定主键,数据库会拒绝建表的语句执行。 事实上, 一个加了主键的表,并不能被称之为「表」。一个没加主键的表,它的数据无序的放置在磁盘存储器上,一行一行的排列的很整齐, 跟我认知中的「表」很接近。如果给表上了主键,那么表在磁盘上的存储结构就由整齐排列的结构转变成了树状结构,也就是上面说的「平衡树」结构,换句话说,就是整个表就变成了一个索引。没错, 再说一遍, 整个表变成了一个索引,也就是所谓的「聚集索引」。 这就是为什么一个表只能有一个主键, 一个表只能有一个「聚集索引」,因为主键的作用就是把「表」的数据格式转换成「索引(平衡树)」的格式放置。

    上图就是带有主键的表(聚集索引)的结构图。图画的不是很好, 将就着看。其中树的所有结点(底部除外)的数据都是由主键字段中的数据构成,也就是通常我们指定主键的id字段。最下面部分是真正表中的数据。 假如我们执行一个SQL语句:

    select * from table where id = 1256;

    首先根据索引定位到1256这个值所在的叶结点,然后再通过叶结点取到id等于1256的数据行。 这里不讲解平衡树的运行细节, 但是从上图能看出,树一共有三层, 从根节点至叶节点只需要经过三次查找就能得到结果。如下图

    假如一张表有一亿条数据 ,需要查找其中某一条数据,按照常规逻辑, 一条一条的去匹配的话, 最坏的情况下需要匹配一亿次才能得到结果,用大O标记法就是O(n)最坏时间复杂度,这是无法接受的,而且这一亿条数据显然不能一次性读入内存供程序使用, 因此, 这一亿次匹配在不经缓存优化的情况下就是一亿次IO开销,以现在磁盘的IO能力和CPU的运算能力, 有可能需要几个月才能得出结果 。如果把这张表转换成平衡树结构(一棵非常茂盛和节点非常多的树),假设这棵树有10层,那么只需要10次IO开销就能查找到所需要的数据, 速度以指数级别提升,用大O标记法就是O(log n),n是记录总树,底数是树的分叉数,结果就是树的层次数。换言之,查找次数是以树的分叉数为底,记录总数的对数,用公式来表示就是

    用程序来表示就是Math.Log(100000000,10),100000000是记录数,10是树的分叉数(真实环境下分叉数远不止10), 结果就是查找次数,这里的结果从亿降到了个位数。因此,利用索引会使数据库查询有惊人的性能提升。

    然而, 事物都是有两面的, 索引能让数据库查询数据的速度上升, 而使写入数据的速度下降,原因很简单的, 因为平衡树这个结构必须一直维持在一个正确的状态, 增删改数据都会改变平衡树各节点中的索引数据内容,破坏树结构, 因此,在每次数据改变时, DBMS必须去重新梳理树(索引)的结构以确保它的正确,这会带来不小的性能开销,也就是为什么索引会给查询以外的操作带来副作用的原因。

    讲完聚集索引 , 接下来聊一下非聚集索引, 也就是我们平时经常提起和使用的常规索引。

    非聚集索引和聚集索引一样, 同样是采用平衡树作为索引的数据结构。索引树结构中各节点的值来自于表中的索引字段, 假如给user表的name字段加上索引 , 那么索引就是由name字段中的值构成,在数据改变时, DBMS需要一直维护索引结构的正确性。如果给表中多个字段加上索引 , 那么就会出现多个独立的索引结构,每个索引(非聚集索引)互相之间不存在关联。 如下图

    每次给字段建一个新索引, 字段中的数据就会被复制一份出来, 用于生成索引。 因此, 给表添加索引,会增加表的体积, 占用磁盘存储空间。

    非聚集索引和聚集索引的区别在于, 通过聚集索引可以查到需要查找的数据, 而通过非聚集索引可以查到记录对应的主键值 , 再使用主键的值通过聚集索引查找到需要的数据,如下图

    不管以任何方式查询表, 最终都会利用主键通过聚集索引来定位到数据, 聚集索引(主键)是通往真实数据所在的唯一路径。

    然而, 有一种例外可以不使用聚集索引就能查询出所需要的数据, 这种非主流的方法 称之为「覆盖索引」查询, 也就是平时所说的复合索引或者多字段索引查询。 文章上面的内容已经指出, 当为字段建立索引以后, 字段中的内容会被同步到索引之中, 如果为一个索引指定两个字段, 那么这个两个字段的内容都会被同步至索引之中。

先看下面这个SQL语句

//建立索引

create index index_birthday on user_info(birthday);

//查询生日在1991年11月1日出生用户的用户名

select user_name from user_info where birthday = '1991-11-1'

这句SQL语句的执行过程如下

首先,通过非聚集索引index_birthday查找birthday等于1991-11-1的所有记录的主键ID值

然后,通过得到的主键ID值执行聚集索引查找,找到主键ID值对就的真实数据(数据行)存储的位置

最后, 从得到的真实数据中取得user_name字段的值返回, 也就是取得最终的结果

我们把birthday字段上的索引改成双字段的覆盖索引

create index index_birthday_and_user_name on user_info(birthday, user_name);

这句SQL语句的执行过程就会变为

通过非聚集索引index_birthday_and_user_name查找birthday等于1991-11-1的叶节点的内容,然而, 叶节点中除了有user_name表主键ID的值以外, user_name字段的值也在里面, 因此不需要通过主键ID值的查找数据行的真实所在, 直接取得叶节点中user_name的值返回即可。 通过这种覆盖索引直接查找的方式, 可以省略不使用覆盖索引查找的后面两个步骤, 大大的提高了查询性能,如下图

    数据库索引的大致工作原理就是像文中所述, 然而细节方面可能会略有偏差,这但并不会对概念阐述的结果产生影响 


http://chatgpt.dhexx.cn/article/EseSwbVM.shtml

相关文章

MySQL索引原理和实现

说到索引,很多人都知道“索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址,在数据十分庞大的时候,索引可以大大加快查询的速度,这是因为使用索引后可以不用扫描全表来定位某行的数…

倒排索引原理,即为什么叫倒排索引

倒排索引的英文原名是Inverted index,大概因为Invert有颠倒的意思,所以就被翻译成了倒排,然后我们就会在字面上出现误解:理解为从A-Z颠倒成Z-A。其实它并不是字面上的意思。 倒排索引源于实际应用中需要根据属性的值来查找记录&a…

【数据库】数据库索引原理

正确的创建合适的索引 是提升数据库查询性能的基础 文章目录 1.索引是什么?2.为什么?3.索引原理B tree 4.B tree 在两大引擎中的体现5.索引的原则 1.索引是什么? 索引是为了加速对表中数据行的检索而创建的一种分散存储的数据结构。 2.为…

Mysql数据库的索引原理

写在前面:索引对查询的速度有着至关重要的影响,理解索引也是进行数据库性能调优的起点。考虑如下情况,假设数据库中一个表有10^6条记录,DBMS的页面大小为4K,并存储100条记录。如果没有索引,查询将对整个表进…

MySql索引原理与使用大全

林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka 一、索引介绍 索引是对数据库表中一列或多列的值进行排序的一种结构。在关系数据库中,索引是一种与表有关的数据库结构,它可以使对应于表的SQL语句执行得更快。索引的作用相…

MySQL:索引原理

文章目录 1、索引概念1.1、使用场景1.2、索引代价 2、索引分类2.1、数据结构2.2、物理存储回表查询 & 覆盖索引 2.3、字段(列)属性2.3.1、主键索引主键的选择 2.3.2、唯一索引2.3.2、普通索引2.3.3、前缀索引 2.4、字段(列)个…

索引的原理和实现的方式

建立索引 需要有索引的类型和索引的方法。 索引的类型包括了Normal Unique Full text 而索引的方法包括了BTREE 和HASH 转载文章:https://www.cnblogs.com/aspwebchh/p/6652855.html 博主写的真好~ 一、什么是Btree B tree (非二叉) 了…

索引的实现原理

这篇文章是介绍MySQL数据库中的索引是如何根据需求一步步演变最终成为B树结构的以及针对B树索引的查询,插入,删除,更新等操作的处理方法。Oracle和DB2数据库索引的实现基本上也是大同小异的。文章写得很通俗易懂,就转在这了。关于…

MySQL索引的理解学习,面试不问索引原理就是事务原理

目录 MySQL执行SQL的整体流程 引言, MySQL索引底层学习原因 磁盘介绍(理解磁盘IO) 索引底层数据结构B树 B树(聚集索引) B树(辅助索引) 思考一下为何使用B树结构, 不是B树, 不是平衡树二叉树,红黑树? 索引总结 MySQL执行SQL的整体流程 显示需要跟MYSQL Serv…

Git | 面试官问你 Git 原理,你能回答得出来吗?

文章目录 原创声明前言一、Git 简单介绍二、解开 Git 在日常上班操作中的神秘面纱2.1 初始化仓库git init 2.2 第n次提交git add xxxgit statusgit commit -m "xxx" 2.3 分支2.3.1 创建分支 git branch xxx2.3.2 切换分支 git checkout 2.3.3 分支中提交 总结参考资料…

Git概念及工作原理总结

Git是分布式版本控制系统。Github和华为等均使用Git作为代码管理工具。之前在工作中比较常用到的是克隆、代码提交拉取、解决回合冲突、代码回滚等。在实际的工作中,可能回合时冲突及版本回退的情况较多,下文将着重介绍这两点。本文不涉及Git的安装等&am…

Git 天天用 但是 Git 原理你了解吗?

前言 做技术一定要知其然知其所以然,意思就是:知道它是这样的,更知道它为什么是这样的。我主要通过4块内容来简单介绍 Git 原理是什么样的。这4块内容如下: Git 存储目录结构介绍Git 是如何存储的Git 的对象Git引用 当然 Git 原…

(一篇就够)git原理深入理解

深入理解git原理 1:git工作模式 基本步骤: 1.workspace 本地工作空间add命令 提交到本地缓存 2、localcache本地缓存commit命令提交到本地仓库 3、localRepository本地仓库push命令提交到远程仓库 拉取步骤: clone 克隆到本地仓库 checkout…

git原理笔记(一)

git原理笔记(一) 这个笔记是对于git内部原理的一个理解。网上很多关于git的用法的教程。这里推荐廖雪峰的git教程。 这里主要记录如下的内部原理的理解 1. git如何存储 2. git如何管理版本 一. git如何存储 常常在使用git的过程中&#…

git工作原理

一. git工作原理 二. git分支标准流程 三. git工具:sourcetree 待续知识分享

git原理和常用命令

git git介绍git工作流程git的几个核心概念 git常用命令参考资料 git介绍 git-分布式版本控制系统,可以有效、高速的处理从很小到非常大的项目版本管理。 git特点 优点: 适合分布式开发,强调个体; 公共服务器压力和数据量都不会太…

Git分支原理

Git分支原理 前言 最近工作由SVN换成Git了,不由地想探寻一下这两种版本控制工具的差别到底在哪里,于是有了这篇笔记。 Git保存方式 Git和SVN的差别主要就在于对待数据的方式。 SVN将存储的信息看作是一组基本文件和每个文件随时间逐步累积的差异&…

git fetch工作原理

背景 相信大家都知道git pull命令相当于git fetch加git merge。那么直接使用git pull和分开使用有什么区别呢&#xff1f;要解答这个问题首先要想了解git fetch的工作原理是什么样的。 git fetch的工作原理 先讲一下什么是远程跟踪分支。远程跟踪分支以 <remote>/<…

Git原理入门解析

前言: 自己第一次听到Git应该是一年前了,当时很懵,不知道它是干啥的,在网上搜索了很多文章,一直不是太明白;今天我来记录一下自己对Git的学习,如果对其他童鞋有所帮助,我荣幸之至! 一、Git 简析 Git是什么? Git是目前世界上最先进的分布式版本控制系统(没有之一)。…

Git原理详解与实用指南

文章目录 上手 1&#xff1a;新公司用 Git 管理代码&#xff0c;怎么快速上手&#xff1f;上手2&#xff1a;团队工作的基本工作模型进阶1&#xff1a;HEAD、master与branch进阶2&#xff1a;push的本质进阶3&#xff1a;merge&#xff1a;合并commits进阶4&#xff1a;Feature…