普通索引和唯一索引详解

news2024/9/20 11:50:46

前言

面试的时候有时会问面试者,普通索引和唯一索引有什么区别。很多人,甚至工作很多年的工程师回答的千篇一律 “普通索引可以有重复的值,唯一索引不能有重复的值”。于是我又问,这两个索引这两个索引效率哪个高,很少有人回答的很好。下面我会从查询和更新多个维度去剖析这两个索引的区别。

现在我们系统有这样一个需求,根据用户的身份证查询用户的信息,用户表的数据很多。

select name from user where id_card='xxxx003'

为了查询的高效,我们肯定是要为id_card 建立索引,应该建立什么索引呢,有人说是主键索引,主键索引当然不合适,有下面几个原因:

  1. id_card 不能保证顺序递增,可能会导致页的分裂,

  2. 还有所占字节太大,主键索引每个叶存的数据太少,其他索引所占的空间也会增多,影响这个数据库的性能。

主键索引不合适,那么就剩下普通索引和唯一索引,对于这个需求,我们将逐步展开讨论。下面我将画出innodb 索引组织结构

接下来,我们就从这两种索引对查询语句和更新语句的性能影响来进行分析。

查询的区别

这个语句在B+tree 中查询过程是这样的,我们从id_card 索引树根开始查找,按层搜索到叶子节点,也就是找到了图中又下脚的那个数据叶。然后可以为数据页 内部通过二分法来定位记录。

  1. 那么对于普通索引来说,查找到 (xxxx003,3) 还需要往下找,直到找到下一个 id_card !='xxxx003' 停止

  2. 对于唯一索引来说,查找到 (xxxx003,3) 就停止,因为索引是唯一性的,查找到第一个满足条件的记录后,就会停止继续检索。

为此很多人感觉唯一索引在查询性能上高于普通索引,这个对性能的消耗微乎其微的。为什么呢?

在这里给大家解释下:

大家都知道,在innodb 查询数据的时候,都是按数据页为单位读取的,也就是说,当我们查询一条数据,并不是这个记录本身从磁盘读出来,而是把这条数据所在页从磁盘中读出来,叶的默认大小是16kB,接下来的查询一般来说会在内存中遍历。为什么说一般来说呢,如果这条记录是页的最后一条,会经过磁盘对数据,稍微复杂点,这种概率很低,可以忽略。

更新的区别

Innodb 有个WAL机制,所谓的WAL机制就是先写日志,在刷盘。这样可以提高数据库的性能,否则只有每次读盘,特别是机械磁盘,一次读盘需要经过寻道,旋转,传输,性能会受到很大的影响。

对于日志来说不得不提到redo log 以及 change buffer,简单对比这两个机制在更新性能上的收益来说,redo log 主要节省的是随机写磁盘的 IO 消耗(转成顺序写),而 change buffer 主要节省的则是随机读磁盘的 IO 消耗。

change buffer 的WAL机制是怎么实现的?

当需要更新一个数据页的时候,如果数据页在内存中直接更新,没有在内存中,在不影响数据一致性的前提下,innodb 会将这个更新操作缓存到change buffer中,这样就不用从磁盘读取这个数据页了。下次查询这个数据页,在将数据页读到内存中,执行change buffer 与这个数据页有关的操作。这种方式就能保证这个数据逻辑的正确性。说明的是change buffer 不仅在内存中有,也会被写到磁盘中。

上面我们说到执行change buffer 与这个数据页有关的操作,就是我们所说的merge。以下情况也会出发merge,数据库正常关闭,后台线程会定时merge。

是不是很神奇,那么是不是只要对数据库的更新都能用到change buffer,其实不一定的。

现在举一个例子,我们要插入(5,xxxx005) 这条记录,我们要分情况讨论。

第一种情况,这个记录要更新的目标页在内存中。两种索引处理流程是这样的

  1. 唯一索引,会看 xxxx004 和 下一条记录之间是否存在一条 xxxx005的记录,没有才插入,语句执行结束。

  2. 普通索引,会在 xxxx004 和 下一条记录之间直接插入一条xxxx005的记录,语句执行结束。

这样看来,普通索引和唯一索引对更新语句性能影响的差别,只是一个判断,只会耗费微小的 CPU 时间。

第二种情况,这个记录要更新的目标页不在内存中

  1. 唯一索引,需要将数据页读入内存中,判断到没有冲突,插入这个值,语句执行结束

  2. 普通索引,只需要该记录在change buffer ,语句就执行结束了

将数据从磁盘读入内存涉及随机 IO 的访问,是数据库里面成本最高的操作之一。change buffer 因为减少了随机磁盘访问,所以对更新性能的提升是会很明显的。

唯一索引哪种情况下都无法使用change buffer,而普通索引可以通过使用change buffer通过减少磁盘的随机读而提高性能。在想想,如果数据在更新后,立马就读取。是不是每次都要触发change buffer 的merge ,不仅要随机读还要维护chage buffer。

那么普通索引和唯一索引该怎么选择了?

我们在业务开发时第一原则是保证业务的准确性,确实需要唯一索引保证数据的唯一性,我们用唯一索引。除此之外,普通索引的优点还是很多的,特别是有些业务写多,读少比如历史数据,特别是数据量很大的情况收益还是非常显著的。

change buffer 用的是 buffer pool 里的内存,因此不能无限增大。change buffer 的大小,可以通过参数 innodb_change_buffer_max_size 来动态设置。这个参数设置为 50 的时候,表示 change buffer 的大小最多只能占用 buffer pool 的 50%。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot231基于SpringBoot+Vue的乡政府管理系统

乡政府管理系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装乡政府管理系统软件来发挥其高效…

植物神经紊乱和焦虑症是一样吗?教你认清这两种疾病

植物神经紊乱和焦虑症并非同一种疾病,尽管它们在一些方面可能有相似的症状,但在病理生理过程、诊断标准和治疗方法上存在明显的区别。患者和家属需要更深入地了解这两种疾病,以便进行正确的诊断和治疗。 植物神经紊乱是一种自主神经功能紊乱的…

python模型训练

目录 1、新建模型 train_model.py 2、运行模型 (1)首先会下载data文件库 (2)完成之后会开始训练模型(10次) 3、 训练好之后,进入命令集 4、输入命令:python -m tensorboard.ma…

MWC 2024:华为手机展现科技创新实力,持续强化高端科技品牌形象

虽然天气有些清冷,但今年的巴塞罗那街头却人潮涌动,从2月26号开始,这个位于伊比利亚半岛东北部,濒临地中海的世界著名历史文化名城将迎来一年一度的全球移动盛会。 作为全球通信领域最具规模和影响的展会,MWC&#xf…

2024最新精华版Java面试题之spring篇

目录 一、Java面试题之spring篇 1、什么是spring? 2、你们项目中为什么使用Spring框架? 3、 Autowired和Resource关键字的区别? 4、依赖注入的方式有几种,各是什么? 5、讲一下什么是Spring容器? 6、说说你对Spring MVC的理…

智慧治水丨计讯物联水利RTU助推小型水库出险加固工程建设与管理

日前,水利部印发《关于健全小型水库除险加固和运行管护机制的意见》(以下简称《意见》),健全小型水库除险加固和运行管护常态化机制,提高小型水库安全管理水平。《意见》提出了“十四五”的两大管理机制,通…

TSINGSEE青犀AI智能分析网关V4工业园区/厂区/工厂智慧安监方案

一、背景与需求分析 随着科技的不断发展,传统的安全监管方式已经难以满足现代工业园区的安全需求。为了提高工业园区的安全监管水平,智慧安监方案成为了新的选择。针对工业园区化工企业多且安全及环保等方面存在风险高、隐患多、精细化管控复杂的情况&a…

Linux - 权限概念

Linux下有两种用户:超级用户(root)、普通用户。 超级用户:可以再linux系统下做任何事情,不受限制普通用户:在linux下做有限的事情超级用户的命令提示符是“#”,普通用户的命令提示符是“$” 命…

shell 免交互ecxept样例

语法 expect [选项] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ] 选项 -c:从命令行执行expect脚本,默认expect是交互地执行的 示例:expect -c expect "\n" {send "pressed enter\n"} -d:输出调试信息 …

2024全国水科技大会暨新能源及电子行业废水论坛(十一)

一、会议背景 为深入学习贯彻《中共中央、国务院关于全面推进美丽中国建设的意见》,全面贯彻实施《固体废物污染环境防治法》、《“十四五”全国城市基础设施建设规划》,推进我国污泥处理工程建设,提高处理产物资源化利用水平,促进…

YOLOv9详细解读,改进提升全面分析(附YOLOv9结构图)

🥑 Welcome to Aedream同学 s blog! 🥑 文章目录 1. 概要1.1 模型结构上的改动:1.2 训练脚本上的改动: 2. 介绍2.1 背景2.2 主要贡献 3. 总体框架3.1 可编程梯度信息(PGI)3.1.1 辅助可逆分支3.1.2 多级辅助信息 3.2 Ge…

【UE 材质】制作加载图案(2)

在上一篇(【UE 材质】制作加载图案)基础上继续实现如下效果的加载图案 效果 步骤 1. 复制一份上一篇制作的材质并打开 2. 添加“Floor”节点向下取整 除相同的平铺数 此时的效果如下 删除如下节点 通过“Ceil”向上取整,参数“Tiling”默认…

苹果iOS群控系统开发常见功能及其代码解析!

随着移动互联网的快速发展,iOS设备因其良好的用户体验和丰富的应用生态,受到了广大用户的喜爱,苹果iOS群控系统,即可以同时对多台iOS设备进行集中控制和管理的系统,逐渐成为了开发者、测试人员以及企业管理的有力工具。…

基于PHP的在线英语学习平台

有需要请加文章底部Q哦 可远程调试 基于PHP的在线英语学习平台 一 介绍 此在线英语学习平台基于原生PHP开发,数据库mysql。系统角色分为学生,教师和管理员。(附带参考设计文档) 技术栈:phpmysqlphpstudyvscode 二 功能 学生 1 注册/登录/…

Spring Exception 常见错误

今天,来学习 Spring 的异常处理机制。Spring 提供了一套健全的异常处理框架,以便我们在开发应用的时候对异常进行处理。但是,我们也会在使用的时候遇到一些麻烦,接下来我将通过两个典型的错误案例,带着你结合源码进行深…

Centos7.9环境源码编译安装ffmpeg6.x

1.官网ffmpeg下载源码 https://ffmpeg.org/download.html#build-windows 2.未安装x264库则先安装配置 可以先查询x264库: whereis libx264 安装编译工具和依赖库: sudo yum install gcc make cmake mercurial git yasm pkgconfig autoconf automake libtool sudo…

Android ANR 日志分析定位

ANR 是 Android 应用程序中的 "Application Not Responding" 的缩写,中文意思是 "应用程序无响应"。这是当应用程序在 Android 系统上运行时,由于某种原因不能及时响应用户输入事件或执行一个操作,导致界面无法更新&…

NodeJs 版本升级时Vue工程报错

最近把nodejs 的版本更新了,原来用的 16.15.1 现在用的 18.16.1,结果所有的vue工程都启不动了,一直报错。 1.报错截图 2.原因分析 error:03000086:digital envelope routines::initialization error ,这个是nodejs版本的问题&am…

Linux基础指令(任务调度、磁盘分区挂载、网络配置、进程管理)

Linux基础指令 1、任务调度简介基本语法crontab【选项】at定时任务 2、磁盘分区、挂载3、网络配置配置网络环境设置主机名和host映射主机名解析过程分析 4、进程管理ps指令终止进程查看进程树服务管理打开或关闭指定端口动态监控进程(top)监控网络状态 1…

Vue3 使用动态组件 component

component 标签&#xff1a;用于动态渲染标签或组件。 语法格式&#xff1a; <component is"标签或组件名">标签内容</component> 动态渲染标签&#xff1a; <template><h3>我是父组件</h3><component is"h1">动态…