MySQL中的普通索引和唯一索引实际开发中的选择

news2024/12/24 8:41:47

文章目录

  • 前言
  • 一、普通索引和唯一索引介绍
  • 二、查询语句的比较
  • 三、更新语句的比较
  • 四、索引的选择和实践


前言

本文我们将会从针对普通索引与唯一索引的增删改查的具体执行流程,来看看效率的对比。以便让我们在实际业务开发中可以进行更好的选择。


一、普通索引和唯一索引介绍

普通索引:
普通索引就是建立在普通字段上的索引,即不要求字段为主键,也不要求字段为UNIQUE。
在创建表时,创建普通索引的方式如下:

create table table_name (
	...
	index(index_column_1,index_column_2,...)
	);

建表后,如果要创建普通索引,可以使用如下这条命令:

create index index_name on table_name(index_column_1,index_column_2,...);

唯一索引:
唯一索引建立在UNIQUE字段上的索引,一张表可以有多个唯一索引,索引列的值必须唯一,但是允许有空值。
在创建表时,创建唯一索引的方式如下:

create table table_name(
	...
	unique key(index_column_1,index_column_2,...)
	);

建表后,如果要创建唯一索引,可以使用下面这条命令:

create unique index index_name on table_name(index_column_1,index_column_2,...);

明白了基本概念,接着我们对执行具体SQL语句的时候,看看用这两个索引的具体执行流程是啥,性能咋样。

二、查询语句的比较

我们也是通过具体的例子来进行分析。
如果我们执行如下查询 语句:

select id from t_table where k=5;

id为主键,k为普通索引或者唯一索引。

这个查询语句在索引树上查找的过程,先是通过B+树从树根开始,按层搜索到叶子节点的指向的数据页,然后数据页内部通过二分法来定位记录。接下来我们,看下当确定 到第一条记录后,对于 普通索引和唯一索引会有什么不同:

  • 普通索引:查找到满足条件的第一个记录后,需要查找下一个记录,直到碰到第一个不满足k=5条件的记录;
  • 唯一索引:由于索引定义了唯一性,查找到第一个满足条件的记录后,就会停止继续检索

那这个不同会带来多大的性能差异呢?其实是微乎其微的。

因为InnoDB的数据是按数据页为单位来读写的。当需要读一条记录的时候,并不是将这个记录本身从磁盘读出来,而是以页为单位,将其整体读入内存。(数据页的大小默认是16KB)

所以,当找到k=5的记录的时候,它所在的数据页就都在内存里了。那么,对于普通索引来说,要多做的那一次“查找和判断下一条记录”的操作,就只需要一次指针寻找和一次计算。虽然有可能,k=5这个记录刚好是这个数据页的最后一个记录,那么读取下一个记录,就要读取下一个数据页,设计到对磁盘io的操作,性能可能会降低,但是出现这种情况的概率很低,所以通过计算平均性能差异可以忽略不计。

由此可见,说到底用这两个不同查询语句的区别就是,普通索引找到记录后,还会往后接着遍历,直到记录不满足为止。而唯一索引查询到第一个满足条件的记录后,就直接停止检索了。

三、更新语句的比较

在介绍之前,我们先介绍下基本的更新过程。再介绍这些之前,我们先连接两个概念:

  • buffer pool:MySQL 的 Buffer Pool
  • change buffer:它是内存中的一块区域,保存在InnoDB的buffer pool中,在磁盘上也有对应的持久化空间(change buffer在内存中有拷贝,也会被写入到磁盘上),在系统表空间ibdata中。它在MySQL中的change buffer信息如下,默认值是25,代表它的大小最大只能占用到InnoDB buffer pool的25%大小,如下所示:
show variables like "%change%";

在这里插入图片描述

明白之后,我们再来看下,更新流程的基本操作:
当更新数据页的时候,如果数据页在内存中就直接更新,而如果这个数据页还没有在内存中
的话,在不影响数据一致性的前提下,InooDB会将这些更新操作缓存在change buffer中,这样就不需要从磁盘中读入这个数据页了。在下次查询需要访问这个数据页的时候,将数据页读入内存,然后执行change buffer中与这个页有关的操作。通过这种方式就能保证这个数据逻辑的正
确性。这样做主要有两个好处:

  • 第一个:将原本2次的磁盘访问,整合成1次磁盘访问,并且能够保证数据的一致性;
  • 第二个:数据页读入内存是需要占用内存空间的。如果仅仅是为了更新而把数据页读入到内存,这未免会造成浪费。因此,上述方法能够避免内存的使用,提高内存的利用率。

将change buffer中的操作应用到原数据页,得到最新结果过程称为merge。触发merge的有以下几种情况:

  • 访问这个数据页的时候
  • 后台线程会定期merge
  • 数据库正常关闭的过程中

明白了使用使用change buffer效率的高效。接下来我们看看是不是普通索引和唯一索引都可以使用呢?
先告诉结论吧,唯一索引不能使用change buffer,普通索引会使用。 接下来分析下原因:
对于唯一索引来说,所有的更新操作都要先判断这个操作是否违反唯一性约束。 比如,要插入
(4,400)这个记录,就要先判断现在表中是否已经存在k=4的记录,而这必须要将数据页读入内存
才能判断。如果都已经读入到内存了
,那直接更新内存会更快,就没必要使用change buffer
了。

明白了普通索引和唯一索引的更新流程,接下来我们以一个具体的例子,再来看看它们之间的性能差异:
如果要在上述所说的表中插入一个如新记录(4,400)的话。我们分别使用的是普通索引和唯一索引:
如果记录要更新的目标页在内存中,处理流程如下:

  • 唯一索引:找到3和5之间的位置,判断有没有冲突,插入这个值,语句执行结束;
  • 普通索引:找到3和5之间的位置,插入这个值,语句执行结束

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

如果这个记录更新的目标不在内存中,处理流程如下:

  • 唯一索引:将数据页读入内存,判断到没有冲突,插入这个值,语句执行结束;
  • 普通索引:将更新记录在change buffer,语句执行结束

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

通过上述,我们了解了change buffer的具体功效,明白了change buffer只限用在普通索引的场景下,而不适用于唯一索引。接下来我们对change buffer的使用场景进行深度分析,看看对于普通索引的所有场景,使用change buffer都可以起到加速作用吗?
在一些写多读少的业务中,change buffer能够发挥很好的作用。它可以将多次对磁盘的操作,合并成一次merge操作,从而提高MySQL的性能,一次性merge的操作越多,收益就越大。

但是需要注意,如果你的数据写入之后。立马会读取(也就意味着需要从磁盘读取到内存),那么建议不要使用change buffer,因为在这种情况下,使用change buffer不会减低IO次数,反而多了change buffer的维护开销。

了解了这些之后,我们还要落实到实处,看看在实际中是怎么进行选择的。

四、索引的选择和实践

这两类索引在查询能力上是没差别的,主要考虑的是对更新性能的影响。所以,尽量选择普通索引。

如果所有的更新后面,都马上伴随着对这个记录的查询,那么你应该关闭change buffer。而在其他情况下,change buffer都能提升更新性能。

普通索引和change buffer的配合使用,对于数据量大的表的更新优化还是很明显的。特别是机械硬盘,访问磁盘较耗时。

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

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

相关文章

动态规划系列 —— 背包问题

什么是背包问题 背包问题是有N件物品,容量为V的背包 每个物品有两个属性:体积,价值,分别用数组v,w表示 第i件物品的体积为v[i],价值为w[i] 计算在背包装得下的情况下,能装的最大价值是多少&…

MATLAB 图像处理大作业

1、基础知识利用 MATLAB 提供的 Image file/IO 函数完成以下处理:(a)以测试图像中心为圆心,图像长宽中较小值一半为半径画一个红颜色的圆;(b)将测试图像涂成国际象棋状的‘黑白格’样子&#xf…

华芯片特微 M33内核 KEIL5环境配置不上问题

1 JFLASH连接不上问题 官方手册有说解决这个问题 2 JFLASH能连接上KEIL提示no found sw-dp 在替换keil下载算法后还是提示no found sw-dp 1 怀疑是keil 527版本太高了, 就换了518 还是不行 2 怀疑是keil检测到盗版了就不让下, 替换Jlink为以前老版本还是不行 解决方案: 下…

聊天气泡图片的动态拉伸、适配与镜像

聊天气泡图片的动态拉伸、适配与镜像前情提要创建.9.png格式的图片从资源文件夹加载.9.png图片从本地文件加载“.9.png”图片项目痛点进阶探索iOS中的方式Android中的探索构造chunk数据构造padding数据镜像翻转功能屏幕的适配简单封装演示示例一条线段控制的拉伸两条线段控制的…

Pandas 安装与教程

前言Pandas 是 Python 语言的一个扩展程序库,用于数据分析。Pandas 是一个开放源码、BSD 许可的库,提供高性能、易于使用的数据结构和数据分析工具。Pandas 名字衍生自术语 "panel data"(面板数据)和 "Python data…

[apidoc]Apidoc-文档生成工具

Apidoc主要是用于生成API文档的工具,可以用于多种语言,包括java、javascript、php等 这里主要是为了写前端的APIDOC,方便交互是双方的使用; 工具的安装 工具包的安装 npm i apidoc [-g|-D]可以-g全局安装,或者-D局部安装,因为…

网盘系统|基于SpringBoot的网盘系统的设计与实现

作者主页:编程指南针 作者简介:Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容:Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 收藏点赞不迷路 关注作者有好处 文末获取源…

【无功优化】考虑泄流效应的光伏并网点电压系统侧无功优化(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

软考中级,【软件评测师】经验分享

,以下是我的考试成绩,一次通过很是幸运,希望把我的好运传递给大家,大家都能一次通过谈经验之前,先和大家说说考试的题型以及考试的内容,根据往年的考试题目我们可以很容易得知,软件评测师考试分…

Cisco(62)——PBR策略路由案例

场景1-单下一跳: 拓扑: 需求: R1和R2均连接100.100.100.100,R4看做一台PC,当PC访问100.100.100.100的时候优先走左边,当左边down掉之后切换到右边链路,使用PBR操作。 实现: 1.IP地址等基本配置 R4: R4(config)#no ip routingR4(config)#int e0/0 R4(config-if)#ip add…

Typora自动上传文章图片太难折腾?十三行JavaScript代码足矣

前言 Typora是我用过最爽的markdown文本编辑器了。但是有一点很让人难受,就是在写文章的时候,粘贴上的图片是本地路径。这就导致在复制文章到各大博客平台时发表,图片无法显示。然后需要各种办法去处理文章中的图片,不仅要手动上传…

【学习笔记】【Pytorch】十、线性层

【学习笔记】【Pytorch】九、线性层学习地址主要内容一、前言二、Pytorch的线性层三、Linear类的使用1.使用说明2.代码实现学习地址 PyTorch深度学习快速入门教程【小土堆】. 主要内容 一、前言 在神经网络中,我们通常用线性层来完成两层神经元间的线性变换。 …

【C++】面向对象---继承(万字详解)

目录前言一、继承的定义及概念二、继承方式三、基类和派生类之间的转换四、切片五、继承中的作用域六、派生类中的默认成员函数七、继承中的友元与静态成员继承与友元继承中的静态成员八、棱形继承和虚继承棱形继承虚继承总结前言 继承是面向对象的一个重点,而继承…

活动星投票医疗保障案例推介网络评选微信的投票方式线上免费投票

“医疗保障案例推介”网络评选投票_线上免费投票系统_功能齐全的微信投票_在线免费投票用户在使用微信投票的时候,需要功能齐全,又快捷方便的投票小程序。而“活动星投票”这款软件使用非常的方便,用户可以随时使用手机微信小程序获得线上投票…

图形编辑器:标尺功能的实现

大家好,我是前端西瓜哥。今天我们来实现图形编辑器的标尺功能。 项目地址: https://github.com/F-star/suika 线上体验: https://blog.fstars.wang/app/suika/ 标尺指的是画布上边和左边的两个有刻度的尺子,作用让用户知道他正在编…

java 探花交友day2 项目简介,环境搭建 登录验证码

技术方案: 项目结构: 项目概述 通过接口文档(API文档)定义规范 开发工具安装与配置 Linux虚拟机 YAPI 账号 tanhuaitcast.cn 密码123456 安装个安卓模拟器,然后安装APK 开发环境说明 初始工程搭建 阿里云短…

Leetcode:235. 二叉搜索树的最近公共祖先(C++)

目录 问题描述: 实现代码与解析: 递归: 原理思路: 精简版: 迭代: 原理思路: 问题描述: 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先…

1589_AURIX_TC275_PMU_Flash的基本特性以及操作

全部学习汇总: GreyZhang/g_TC275: happy hacking for TC275! (github.com) 关于这部分,感觉能够看到的比较有实践指导价值的信息不多。这里关于是否支持cache的信息,之前在内核手册等地方其实也看过了。 DFlash不支持buffer命中的功能&#…

21.Isaac教程--GEMS 导航堆栈简介

Isaac GEMS 导航堆栈简介 ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 导航堆栈必须执行以下高级功能: Mapping 映射用于自动创建操作环境的地图。 该地图既用于定位,又用于路径规划。 它可以由具有附加功能的人进行注…

deap遗传算法 tirads代码解读

deap遗传算法 tirads代码解读写在最前面Overview 程序概览参考deap框架介绍creator模块创建适应度类Types定义适应度策略创建个体类Toolbox类创建种群(个体、策略以及粒子)Initialization1. 创建 attr_int 运算符2. 创建 individual_guess() 运算3.创建新…