MySQL优化必备知识-索引篇

索引用于快速查找具有特定列值的行。如果没有索引,MySQL必须从第一行开始,然后读取整个表以查找相关行。表越大,成本越高。如果表中有相关列的索引,MySQL可以快速确定在数据文件中间查找的位置,而不必查看所有数据。这比按顺序读取每一行要快得多。

提高SELECT操作性能的最佳方法是在查询中测试的一个或多个列上创建索引。索引项的作用类似于指向表行的指针,允许查询快速确定哪些行与WHERE子句中的条件匹配,并检索这些行的其他列值。可以索引所有MySQL数据类型。

尽管为查询中使用的每一个可能的列创建一个索引很有诱惑力,但不必要的索引会浪费MySQL确定要使用哪些索引的空间和时间。索引还增加了插入、更新和删除的成本,因为每个索引都必须更新。我们必须了解索引、理解和掌握索引,最后找到适当的平衡,才能使用最佳索引集实现快速查询。

MySQL索引划分

MySQL中把索引分为聚集索引(Clustered Index)和二级索引(Secondary Indexes),我们通常说的索引都是二级索引。

聚集索引

每个InnoDB表都有一个称为聚集索引的特殊索引,用于存储行数据。通过聚集索引访问行非常快,因为索引搜索直接指向包含行数据的页面。

通常,聚集索引与主键同义。为了从查询、插入和其他数据库操作中获得最佳性能,了解InnoDB如何使用聚集索引来优化常见的查找和DML操作非常重要。

如果不为表定义主键,InnoDB将使用第一个唯一索引(所有键列定义为not NULL)作为聚集索引。
如果表没有主键或合适的唯一索引,InnoDB将在包含行ID值的合成列上生成一个名为GEN_CLUST_index的隐藏聚集索引。行按InnoDB分配的行ID排序。行ID是一个6字节的字段,随着插入新行而单调增加。因此,按行ID排序的行实际上是按插入顺序排列的。

二级索引

聚集索引以外的索引称为二级索引。在InnoDB中,二级索引中的每个记录都包含该行的主键列以及为二级索引指定的列。InnoDB使用此主键值搜索聚集索引中的行。如果主键长,则二级索引占用更多空间,因此主键短是有利的。

二级索引包括唯一索引(UNIQUE)、普通索引(Normal INDEX)、全文索引(FULLTEXT)和空间数据索引(Spatial)

索引构建

除了空间索引之外,InnoDB索引都是B树数据结构。空间索引使用R树,R树是用于索引多维数据的专用数据结构。索引记录存储在其B树或R树数据结构的叶页中。索引页的默认大小为16KB。页面大小由初始化MySQL实例时的innodb_page_size设置确定。

当新记录插入到InnoDB聚集索引中时,InnoDB会尝试保留页面的1/16空间,以便将来插入和更新索引记录。如果按顺序(升序或降序)插入索引记录,当大约占15/16页则表示索引页满。如果以随机顺序插入记录,当大约占1/2到15/16页则表示索引页满。

InnoDB批量创建或重建B树索引,而不是一次插入一条索引记录,这种索引创建方法也称为排序索引构建。

在引入排序索引构建之前,索引条目是使用插入API一次一条记录地插入到B树中的。这种方法包括打开B树光标以找到插入位置,然后使用乐观插入将条目插入B树页面。如果由于页面已满而导致插入失败,则将执行悲观插入,这包括打开B树光标,并根据需要拆分和合并B树节点以查找条目的空间。这种“自上而下”的索引构建方法的缺点是搜索插入位置的成本以及B树节点的不断拆分和合并。

排序索引构建使用“自下而上”的方法来构建索引。使用这种方法,在B树的所有级别上都会保留对最右侧叶页的引用。在必要的B树深度处的最右边的叶页被分配,并且条目根据它们的排序顺序被插入。一旦一个叶页已满,就会将一个节点指针附加到父页,并为下一次插入分配一个同级叶页。此过程一直持续到插入所有条目,这可能导致插入到根级别。分配同级页时,将释放对先前固定的叶页的引用,新分配的叶页将成为最右侧的叶页和新的默认插入位置。

排序索引构建有三个阶段:
在第一阶段,扫描聚集索引,生成索引条目并将其添加到排序缓冲区。当排序缓冲区已满时,将对条目进行排序并将其写入临时中间文件。这个过程也称为“run”。
在第二阶段,将一个或多个run写入临时中间文件,对文件中的所有条目执行合并排序。
在第三个也是最后一个阶段,已排序的条目被插入到B树中。

为了给未来的索引增长留出空间,可以使用innodb_fill_actor变量来保留一定比例的B树页面空间(设置为100将使聚集索引页中的1/16空间用于将来的索引增长)。例如,在排序索引构建过程中,将innodb_fill_actor设置为80将保留B树页面中20%的空间。此设置同时适用于B树叶子页和非叶子页。它不适用于用于TEXT或BLOB条目的外部页面。保留的空间量可能与配置的不完全一样,因为innodb_fill_actor值被解释为提示而不是硬限制。

如果innodb_fill_factor低于MERGE_THRESHOLD(合并阈值,默认为50%),InnoDB将尝试收缩索引树以释放该页。innodb_fill_factor设置同时应用于B树和R树索引。

全文索引也支持排序索引生成。

索引关联

索引与表压缩

对于表压缩,以前的索引创建方法将条目附加到压缩页和未压缩页。当修改日志(表示压缩页面上的可用空间)变满时,压缩页面将被重新压缩。如果压缩由于空间不足而失败,页面将被拆分。

对于排序索引构建,条目仅附加到未压缩的页面。当未压缩的页面变满时,它将被压缩。自适应填充用于确保在大多数情况下压缩成功,但如果压缩失败,则会拆分页面并再次尝试压缩。此过程一直持续到压缩成功。

排序索引生成和Redo日志

在排序索引生成过程中,将禁用Redo日志记录。相反,有一个检查点来确保索引构建能够承受意外退出或失败。检查点强制将所有脏页写入磁盘。在排序索引构建过程中,会定期向页面清理线程发出信号以清除脏页面,以确保可以快速处理检查点操作。通常,当清理页面的数量低于设置的阈值时,页面清理线程会清除脏页面。对于已排序的索引构建,脏页会被迅速刷新,以减少检查点开销,并使I/O和CPU活动并行化。

排序索引构建和优化器统计信息

排序后的索引构建可能会导致优化器统计信息与以前的索引创建方法生成的统计信息不同。但统计数据的差异预计不会影响工作负载性能,这是由于用于填充索引的算法不同。

MySQL如何用索引

MySQL使用索引方式:

  • 快速查找与WHERE子句匹配的行。
  • 如果要在多个索引之间进行选择,MySQL通常使用查找最少行数的索引(最有选择性的索引)。
  • 如果表具有多列索引,则优化器可以使用索引最左边的任何前缀来查找行。例如,如果对(col1,col2,col3)具有三列索引,则对(col1),(col1,col2)和(col1,col2,col3)具有索引搜索功能。对于(col1,col3),则部分有效(col1)。如果不是从最左边列开始则用不上索引,如(col2),(col3)、(col2,col3)。
  • 联接(join)检索(从其它表检索行),如果将连接的列声明为相同的类型和大小,MySQL可以更有效地使用它们。对于VARCHAR和CHAR,只要相同大小,则认为它们是相同的。例如,VARCHAR(10)和CHAR(10)的大小相同,但VARCHAR(10)和CHAR(15)的大小不同。
  • 对于非二进制字符串列之间的比较,两列应使用相同的字符集。例如,将utf8列与latin1列进行比较会排除索引的使用。
  • 比较不同的列(例如,将字符串列与时态或数字列进行比较)可能会阻止使用索引,如果不进行转换就无法直接比较值。对于给定的值(如数字列中的1),它可能与字符串列中的任意数量的值(如“1”、“1”、“00001”或“01.e1”)进行比较。这排除了对字符串列使用任何索引的可能性。
  • 查找索引列的MIN()或MAX()值,由预处理器优化。
  • order by或group by按最左边可用索引完成(例如,按key_part1、key_part2排序)。如果所字段后面都有DESC,则按相反顺序读取。
  • 在某些情况下,可以优化查询以检索值,而无需查询数据行。如果查询仅从表中使用包含在某些索引中的列,则可以从索引树中检索所选值以获得更快的速度(为查询提供所有必要结果的索引称为覆盖索引)。

对于小表(通常<300行数据)上的查询,或报表查询处理大部分或所有行的大表,索引不太重要。当查询需要访问大多数行时,按顺序读取要比处理索引快。即使查询不需要所有的行,顺序读取也可以最小化磁盘查找。

索引优化

  • 主键优化:主键是查询中优先使用的列或列集。使用InnoDB存储引擎,可以对表数据进行物理组织,以便根据主键列进行超快速查找和排序。
  • 外键优化:如果一个表有许多列,常查询许多不同的列组合,那么将使用频率较低的数据拆分为单独的表(每个表都有几列)通过外键同主表主键关联是一种有效的优化方法。这样,每个小表都可以有一个主键,用于快速查找其数据,并且可以使用联接操作查询所需的列集。根据数据的分布方式,查询可能会执行更少的I/O并占用更少的缓存内存(为了最大限度地提高性能,查询尝试从磁盘读取尽可能少的数据块;只有几列的表可以在每个数据块中容纳更多的行)。
  • 单列索引:最常见的索引类型只包括一列,该列值的副本存储在索引数据结构中,从而可以快速查找具有相应列值的行。B树数据结构使索引能够快速找到一个特定值、一组值或一系列值,这些值对应于WHERE子句中的运算符,如=、>、≤、BETWEEN、IN等。为了减少索引占用空间,在字符串列的索引规范中使用col_name(N)语法,可以创建仅使用列的前N个字符的索引。以这种方式仅对列值的前缀进行索引会使索引文件变得更小。为BLOB或TEXT列编制索引时,必须为索引指定前缀长度。使用前缀需注意:如果搜索项超过索引前缀长度,则将作为不匹配的行排除。
  • 复合索引:即在两个或以上列上建立的索引。一个索引最多可以由16列组成。如果按索引定义中顺序指定列查询,复合索引可以加快查询速度。复合索引查询必须包含最左列,否则可能导致索引失效。

索引失效

下表列出在SQL中可能导致索引失效的运算符;

运算符分类运算符会导致索引失效的运算符
否定操作符notnot
逻辑运算符and,oror
算数运算符*,/,+,-表达式左边使用
比较运算符=,>,>=,<,<=,<>或!=<>或!=
匹配运算符likelike非头部匹配,not like
null运算符is null, is not nullis null, is not null
包含in,existsin,not in,exists,not exists
范围between … and …not between … and …
当成特殊运算符内置函数或自定义函数表达式左边使用

另外,由于MySQL优化器作用,即使同一个SQL,索引可能有效也可能失效,失效原因是优化器认为不用索引效率会更高。举例如下:
1、orders表有48252条数据。
2、在create_time列上建立索引
3、查看orders表中按create_time的数据分布情况如图:
在这里插入图片描述
4、索引无效图:
在这里插入图片描述

5、索引有效图:
在这里插入图片描述

分析索引使用情况

用EXPLAIN语句可分析索引使用情况。

EXPLAIN SELECT ...;
EXPLAIN INSERT ..;
EXPLAIN UPDATE ..;
EXPLAIN DELETE ..;

EXPLAIN 提供了有关MySQL如何执行语句的信息,显示来自优化器的有关语句执行计划的信息。也就是说,MySQL解释了它将如何处理该语句,包括关于表如何连接以及按何种顺序连接的信息。
EXPLAIN 输出信息:

含义
idSELECT标识符
select_typeselect类型
table输出行的表
partitions匹配的分区
type联接类型
possible_keys可能选择的索引
key实际选择的索引
key_len所选索引的长度
ref与索引比较的列
rows要检查的行的估计
filtered按表条件筛选的行的百分比
Extra附加信息

这篇文章如果对您有所帮助或者启发的话,帮忙关注或点赞,有问题请评论,必有所复。您的支持是我写作的最大动力!

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

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

相关文章

vue常用指令(v-on传递参数和事件修饰符)

1、传 递 自 定 义 参 数 : 函 数 调 用 传 参 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title…

企业的多域名SSL证书

多域名SSL证书作为一种加密通信的方式&#xff0c;可以有效保护多个网站的用户数据在传输过程中的安全。不管个人或者企事业单位 都可以申请多域名SSL证书&#xff0c;提高网站的安全性&#xff0c;保护网站数据传输安全。今天就随SSL盾了解多域名SSL证书旗下的企业多域名SSL证…

详解SpringCloud微服务技术栈:深入ElasticSearch(4)——ES集群

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;详解SpringCloud微服务技术栈&#xff1a;深入ElasticSearch&#xff08;3&#xff09;——数据同步&#xff08;酒店管理项目&a…

盛水最多的容器(Python+Go)

给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。(不能倾斜容器) 输入&#xff1a;[1,8,6,2,5…

windows设置openDNS

windows环境搭建专栏&#x1f517;点击跳转 win系统环境搭建&#xff08;十九&#xff09;——windows设置openDNS 文章目录 win系统环境搭建&#xff08;十九&#xff09;——windows设置openDNS1.什么是openDNS&#xff1f;2.openDNS的ip是多少&#xff1f;3.设置DNS3.1 设置…

linux服务器上安装mysql

今天在华为云上安装mysql&#xff0c;安装命令很简单&#xff0c;就一行命令&#xff1a;sudo apt-get update && sudo apt-get install mysql-server 我安装的是mysql8.0版本&#xff0c;这里主要说一下安装mysql后怎么在外网连接&#xff1a; 1、注释掉 bind-add…

HCIP-Datacom(H12-821)61-70题解析

有需要完整题库的同学可以私信博主&#xff0c;博主看到会回复将文件发给你&#xff01;&#xff08;麻烦各位同学给博主推文点赞关注和收藏哦&#xff09; 61、以下哪个场景不适合部署接口策略路由 A.企业网络多ISP出口的场景下&#xff0c;内网不同的网段通过不同的ISP出口访…

PHP的线程安全与非线程安全模式选哪个

曾经初学PHP的时候也很困惑对线程安全与非线程安全模式这块环境的选择&#xff0c;也未能理解其中意。近来无意中看到一个教程对线程安全&#xff08;饿汉式&#xff09;&#xff0c;非线程安全&#xff08;懒汉式&#xff09;的描述&#xff0c;虽然觉得现在已经能够很明了透彻…

设计模式_迭代器模式_Iterator

案例引入 编写程序展示一个学校院系结构: 需求是这样&#xff0c;要在一个页面中展示出学校的院系组成&#xff0c;一个学校有多个学院&#xff0c;一个学院有多个系 【传统方式】 将学院看做是学校的子类&#xff0c;系是学院的子类&#xff0c;小的组织继承大的组织 分析&…

串口通信(基于51单片机)

师从江科大 串口介绍 1、串口可以实现两个设备的相互通信。 2、单片机的串口可以使单片机与单片机&#xff0c;单片机与电脑&#xff0c;单片机与多种模块相互通信 3、单片机内部自带UART&#xff08;通用异步收发器&#xff09;&#xff0c;可实现单片机的串口通信 硬件电…

MT6785(Helio G95)芯片性能参数_MTK联发科4G处理器

联发科MT6785平台采用台积电 12 nm FinFET 制程工艺&#xff0c;2*A766*A55架构&#xff0c;搭载Android 12.0/13.0操作系统&#xff0c;主频最高达2.05GHz&#xff0c;搭载HyperEngine 游戏技术&#xff0c;通过四个增强领域的整体增强功能。 搭载 Arm Mali-G76 MC4 GPU 运行速…

【2024】大三寒假再回首:缺乏自我意识是毒药,反思和回顾是解药

2024年初&#xff0c;学习状态回顾 开稿时间&#xff1a;2024-1-23 归家百里去&#xff0c;飘雪送客迟。 搁笔日又久&#xff0c;一顾迷惘时。 我们饱含着过去的习惯&#xff0c;缺乏自我意识是毒药&#xff0c;反思和回顾是解药。 文章目录 2024年初&#xff0c;学习状态回顾一…

线性表的链式表示【单链表】

单链表的优缺点 优点缺点 1. 插入和删除操作不需要移动元素&#xff0c;只需要修改指针 2. 不需要大量的连续存储空间 1. 单链表附加指针域&#xff0c;也存在浪费存储空间的缺点。 2. 查找操作需要从表头开始遍历&#xff0c;依次查找&#xff0c;不能随机存取。 单链表结…

【重温设计模式】构建器及其Java示例

设计模式中的构建器模式介绍 在编程的世界里&#xff0c;设计模式是一种让我们的代码更加优雅、可读、可维护的工具。其中&#xff0c;构建器模式是一种创建型模式&#xff0c;它提供了一种高效且灵活的方式来创建复杂对象。这种模式的主要特点是&#xff0c;它分离了对象的构…

【wine】Ubuntu 22.04 x86_64 源码编译 wine 9.1 编译版本不能启动微信,apt安装版本可以使用微信

git clone https://gitee.com/winehq/wine.git git checkout wine-9.1 x86_64 注意&#xff08;没有--enable-win32选项&#xff01;&#xff09; sudo apt install build-essential git libtool m4 autoconf automake pkg-config libc6-dev-i386 zlib1g-dev libncurses5-de…

transformer_正余弦位置编码代码笔记

transformer_正余弦位置编码代码笔记 transformer输入的序列中&#xff0c;不同位置的相同词汇可能会表达不同的含义&#xff0c;通过考虑位置信息的不同来区分序列中不同位置的相同词汇。 位置编码有多种方式&#xff0c;此处仅记录正余弦位置编码 正余弦位置编码公式如下&…

【Java】阻塞队列

目录 BlockingQueue BlockingQueue接口 三个主要实现类介绍&#xff1a; ArrayBlockingQueue&#xff1a;有界队列 LinkedBlockingQueue&#xff1a;无界队列 SynchronousQueue:同步队列 队列对比 BlockingQueue 对于Queue而言&#xff0c;BlockingQueue是主要的线程安全…

Windows IIS服务如何配置并制作web站点结合内网穿透实现公网访问

文章目录 1. 安装IIS必要WebDav组件2. 客户端测试3. cpolar内网穿透3.1 打开Web-UI管理界面3.2 创建隧道3.3 查看在线隧道列表3.4 浏览器访问测试 4. 安装Raidrive客户端4.1 连接WebDav服务器4.2 连接成功4.2 连接成功总结&#xff1a; 自己用Windows Server搭建了家用NAS主机&…

vue3-深入组件-插槽

插槽 Slots 组件用来接收模板内容 插槽内容与出口 <slot> 元素是一个插槽出口 (slot outlet),&#xff0c;标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。 插槽内容可以是任意合法的模板内容&#xff0c;不局限于文本。例如我们可以传入多个元素&#xff0…

静态时序分析:时序弧以及其时序敏感(单调性)

相关阅读 静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html?spm1001.2014.3001.5482 在静态时序分析中&#xff0c;不管是组合逻辑单元&#xff08;如与门、或门、与非门等&#xff09;还是时序逻辑&#xff08;D触发器等&#xff09;在时序建模时…