深入浅出MySQL-06-【索引的设计和使用】

文章目录

  • 前言
  • 1.索引概述
  • 2.设计索引的原则
  • 3.索引设计的误区
  • 4.索引设计的一般步骤
  • 5.BTREE索引和HASH索引
  • 6.索引在MySQL 8.0中的改进
    • 6.1.不可见索引
    • 6.2.倒序索引
  • 7.总结

前言

环境:

  • Windows11
  • MySQL-8.0.35

1.索引概述

所有MySQL列类型都可以被索引,对相关列使用索引是提高SELECT操作性能的最佳途径。根据存储引擎可以定义每个表的最大索引数和最大索引长度,每种存储引擎(如MyISAM、InnoDB、BDB、MEMORY等)对每个表至少支持16个索引,总索引长度至少为256字节。大多数存储引擎有更高的限制。

MyISAM 和InnoDB存储引擎的表默认创建的都是BTREE索引。除了直接在单列或者多列上直接创建索引外,MySQL5.7之后可以通过虚拟列索引来实现函数索引的功能,同时MySQL也支持前缀索引,即对索引字段的前N个字符创建索引。前缀索引的长度跟存储引擎相关。

MySQL中还支持全文本(FULLTEXT)索引,该索引可以用于全文搜索。ImnnoDB和MyISAM存储引擎虽然支持FULLTEXT索引,但只限于 CHAR、VARCHAR 和 TEXT列。索引总是对整个列进行的,不支持局部(前缀)索引。

MySQL也可以为空间列类型创建索引,MySQL5.7中,InnoDB存储引擎也开始支持空间类型索引,索引以R-Trees的数据结构保存。

索引在创建表的时候可以同时创建,也可以随时增加新的索引。创建新索引的语法如下:

// 使用mysql的帮助文档查看创建索引的SQL语句
mysql> ? create index;
Name: 'CREATE INDEX'
Description:
Syntax:
CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX index_name
    [index_type]
    ON tbl_name (key_part,...)
    [index_option]
    [algorithm_option | lock_option] ...

key_part: {col_name [(length)] | (expr)} [ASC | DESC]
... ...

也可以使用ALTER TABLE的语法来增加索引,语法类似。

索引的删除语句如下:

mysql> ? drop index;
Name: 'DROP INDEX'
Description:
Syntax:
DROP INDEX index_name ON tbl_name
    [algorithm_option | lock_option] ...
 ... ...

2.设计索引的原则

索引的设计可以遵循一些已有的原则,创建索引的时候尽量考虑这些原则,便于提升索引的使用效率、更高效的使用索引:

  • 要在条件列上创建索引,而不是查询列。也就是说最适合索引的列是出现在 WHERE子句中的列,或连接子句中指定的列,而不是出现在 SELECT 关键字后的选择列表中的列。
  • 尽量使用唯一索引。考虑某列中值的分布。索引的列的基数越大,索引的效果越好。例如,存放出生日期的列具有不同值,很容易区分各行。而用来记录性别的列,只含有“M”和“F”,则对此列进行索引没有多大用处,因为不管搜索哪个值,都会得出大约一半的行。
  • 使用短索引。如果对字符串列进行索引,应该指定一个前缀长度,只要有可能就应该这样做。例如,有一个 CHAR(200)列,如果在前 10 个或 20 个字符内,多数值是唯一的,那么就不要对整个列进行索引。对前 10个或 20个字符进行索引能够节省大量索引空间,也可能会使查询更快。较小的索引涉及的磁盘IO较少,较短的值比较起来更快。更为重要的是,对于较短的键值,索引高速缓存中的块能容纳更多的键值,因此,MySQL也可以在内存中容纳更多的值。这样就增加了找到行而不用读取索引中较多块的可能性。
  • 利用最左前缀。在创建一个n列的索引时,实际相当于创建了MySQL可利用的n个索引。多列索引可起几个索引的作用,因为可利用索引中最左边的列集来匹配行。这样的列集称为最左前缀。例如以 a、b、c的顺序在3列上创建一个组合索引之后,利用 a=?或者 a=? and b=?或者 a=?and b=?andc=?这3种条件的查询,都可以使用这个索引。通过这种方式,可以有效的降低索引的数量,提高索引的使用效率。
  • 对于 InnoDB 存储引擎的表,尽量手工指定主键。记录默认会按照一定的顺序保存,如果有明确定义的主键,则按照主键顺序保存。如果没有主键,但是有唯一索引,那么就是按照唯一索引的顺序保存。如果既没有主键又没有唯一索引,那么表中会自动生成一个内部列,按照这个列的顺序保存。按照主键或者内部列进行的访问是最快的,所以 InnoDB 表尽量自己指定主键。当表中同时有几个列都是唯一的,都可以作为主键的时候,要选择最常作为访问条件的列作为主键,提高查询的效率。另外,还需要注意,InnoDB表的普通索引都会保存主键的键值,所以主键要尽可能选择较短的数据类型,有效地减少索引的磁盘占用,提高索引的缓存效果。
  • 对于 InnoDB 存储引擎的表,尽量手工指定主键。记录默认会按照一定的顺序保存,如果有明确定义的主键,则按照主键顺序保存。如果没有主键,但是有唯一索引,那么就是按照唯一索引的顺序保存。如果既没有主键又没有唯一索引,那么表中会自动生成一个内部列,按照这个列的顺序保存。按照主键或者内部列进行的访问是最快的,所以 ImnoDB 表尽量自己指定主键。当表中同时有几个列都是唯一的,都可以作为主键的时候,要选择最常作为访问条件的列作为主键,提高查询的效率。另外,还需要注意,InnoDB表的普通索引都会保存主键的键值,所以主键要尽可能选择较短的数据类型,有效地减少索引的磁盘占用,提高索引的缓存效果。

3.索引设计的误区

设计索引时,有一些常见的误区,总结如下:

  • 不是所有的表都需要创建索引。通常来说,数据量很小的表,除了主键外,再创建索引没有太大的意义,索引扫描和全表扫描相比,并不会带来性能的大幅提升。而大表的查询、更新、删除操作则要尽可能通过索引。对于大表来说,任何全表扫描对于系统来说都会是非常大的冲击,因此每个操作都尽可能通过索引进行。这类表要经常统计操作频率较高的 SQL,然后对这些 SQL进行分析,提取最常用的一些选择性高的列来创建索引。
  • 不要过度索引。不要以为索引“越多越好”,什么东西都用索引是错误的。每个额外的索引都要占用额外的磁盘空间,并降低写操作的性能。在修改表的内容时,索引必须进行更新,有时可能需要重构,因此,索引越多,所花的时间越长。如果有一个索引很少利用或从不使用,那么会不必要地减缓表的修改速度。此外,MySQL在生成一个执行计划时,要考虑各个索引,这也要花费时间。创建多余的索引给查询优化带来了更多的工作。索引太多,也可能会使 MySQL选择不到所要使用的最好索引。因此,只保持所需的索引有利于查询优化。
  • 谨慎创建低选择度索引。对于选择性低并且数据分布均衡的列,因为过滤的结果集大,创建索引的效果通常不好;但如果列的选择性低但数据分布不均衡,比如男女比例为99%:1%,那么此时创建索引对于查询条件为’女"的过滤结果集就比较小,索引的效率较高,此时创建索引就比较合适。在MySQL8.0之后也可以使用直方图取得类似的优化效果。

4.索引设计的一般步骤

通过上面的介绍,当对一个大表做索引设计时,一般可以采取下面的步骤:

  1. 整理表上的所有SQL,重点时select、update 和 delete 操作的where条件所用到的列的组合、关联查询的关联条件等。
  2. 整理所有查询 SQL的预期执行频率。
  3. 整理所有涉及的列的选择度,列的不同值相比总非空行数的比例越大,选择度越好,比如全部都是唯一值的主键列选择度最高。当然,上面所提到的查询频率、选择度,都是估算的值,能够在设计索引时作为参考即可。
  4. 遵照之前提到的设计原则,给表选择合适的主键。
  5. 优先给那些执行频率最高的SQL创建索引,执行频率很高的SQL,使用到的索引的效率对整体性能影响也会比较大,选择其中选择度最高的列来创建索引,如果选择度都不够好,那么应该考虑是否可以使用其他选择度更好的条件,或者选择创建联合索引。
  6. 按执行频率排序,依次检查是否需要为每个SQL创建索引,可以复用之前已经创建的索引的SQL,无须再重复创建索引,除非SQL执行频率很高,新创建的索引,对选择度提升也很大。
  7. 索引合并,利用复合索引来降低索引的总数,充分利用最左前缀的原则,让索引可以被尽可能多地复用,同时在保证复用率的情况下,把选择度更高的列放到索引的更左侧。
  8. 上线之后,通过慢查询分析、执行计划分析、索引使用统计,来确定索引的实际使用情况,并根据情况做出调整。

5.BTREE索引和HASH索引

BTREE索引 和 HASH索引,这两种不同类型的索引各有其不同的适用范围。HASH索引有一些重要的特征在使用时需特别注意,如下所示:

  • 只用于使用=或<=>( NULL-safe 的等于操作符)操作符的等式比较。
  • 优化器不能使用 HASH 索引来加速 ORDER BY 操作。
  • MySQL 不能确定在两个值之间大约有多少行。如果将一个 MyISAM 表改为 HASH索引的MEMORY表,会影响一些查询的执行效率。
  • 只能使用整个关键字来搜索一行。

而对于 BTREE 索引,当使用>、<、>=、<=、BETWEEN、!=或者>,或者 LIKE‘pattern’(其中’pattern’不以通配符开始)操作符时,都可以使用相关列上的索引。例如下面这个查询适用于BTREE和HASH索引:

select * from t1 where key_col = 1 or key_col in (15, 18, 20);

下列的查询只适用于BTREE索引:

select * from t1 where key_col > 1 and key_col < 10;
select * from t1 where key_col like 'ab%' and key_col between 'zhangsan' and 'wangwu';

当对索引字段进行范围查询的时候,只有BTREE索引可以通过索引访问,而HASH索引实际上是全盘扫描的。

6.索引在MySQL 8.0中的改进

索引的正确使用,对于MySQL的性能优化,起着非常关键的作用。在MySQL8.0中索引也引人了不少新的特性。下面介绍几个比较重点的改进。

6.1.不可见索引

所谓不可见,指的是对于查询优化器不可见,SQL在执行时自然也就不会选择,但是在查看表结构的时候索引仍然看得见,也可以通过 information_schema.statistics 或 show index 来查看索引是否可见的状态。

索引默认是可见的,可以通过创建索引时指定 invisible 关键字来创建不可见索引:

CREATE TABLE t1 (
	col int,
	col2 int
	INDEX col_idx(col) INVISIBLE
) ENGINE = InnoDB

也可以通过命令来单独添加不可见索引:

CREATE INDEX col_idx(col) INVISIBLE;
ALTER TABLE t1 ADD INDEX_col_idx(col) INVISIBLE;

可以通过 alter table 命令来修改索引是否可见:

ALTER TABLE t1 ALTER INDEX col_idx INVISIBLE;
ALTER TABLE t1 ALTER INDEX col_idx VISIBLE;

为什么数据库中要设计这么一种消耗资源,却又不能够对SQL起到任何优化左右的索引呢?实际上,引入不可见索引的目的,主要是为了减小对于表上的索引进行调整时的潜在风险。

随着表的数据量增大,达到了几百GB几TB甚至更大的时候,如果此时对表上的索引进行调整,往往面临着很大的风险。例如,当删除一个认为不再需要的索引时,一旦系统中还存在个别使用这个索引的SOL,那么这些SOL的执行计划有可能会变成对这个大表的全表扫描,这会对数据库服务器造成巨大冲击或直接导致服务不可用。而由于表的数据量大,重建索引需要的时间和消耗的系统资源也会很大,很难马上通过重建索引解决问题。

有了不可见索引,当需要删除一个表上的冗余索引时,可以先将索引设置为不可见,而不是直接删除,一旦发现没有这个索引之后,对系统性能产生了负面影响,可以很方便地恢复这个索引,而不再需要重建索引。

同样,当增加一个索引之后,如果发现对系统带来了负面影响,可以首先将索引设置为不可见,待系统负载恢复正常后,再做索引的删除,避免了系统压力大的时候雪上加霜。

6.2.倒序索引

在 MySQL8.0中,正式增加了对于倒序索引(descending index)的支持,在之前的版本中虽然在创建索引的时候可以指定 desc关键字,但是实际上 MySQL仍然会保存为正序索引。

MySQL中的倒序索引起到的作用比较弱,这里不做讨论了。

7.总结

索引用于快速找出在某个列中有某个特定值的行。如果不使用索引,MySQL必须从第1条记录开始然后读完整个表直到找出相关的行。表越大,花费的时间越多。如果表中查询的列有一个索引,MySQL能快速到达一个位置去搜寻数据文件的中间,没有必要看所有数据。如果一个表有1000行,这比顺序读取至少快100倍。注意如果需要访问大部分行,顺序读取要快得多,因为此时应避免磁盘搜索。

大多数 MySQL索引(如PRIMARY KEY、UNIQUE、INDEX和FULLTEXT等)在 BTREE中存储。只是空间列类型的索引使用BTREE,并目MEMORY表还支持HASH索引。

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

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

相关文章

大数据005-hadoop003-了解MR及Java的简单实现

了解MapReduce MapReduce过程分为两个阶段&#xff1a;map阶段、reduce阶段。每个阶段搜键-值对作为输入和输出。 要执行一个MR任务&#xff0c;需要完成map、reduce函数的代码开发。 Hellow World 【Hadoop权威指南】中的以分析气象数据为例&#xff0c;找到每年的最高气温。…

基于Springboot的校园博客系统

基于SpringbootVue的校园博客系统 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 文章信息 系统公告 后台登录 后台首页 博主管理 文章分类管理 文章信息管理 举报投诉管…

将要上市的自动驾驶新书《自动驾驶系统开发》中摘录片段

全书共分15章&#xff1a;第1章是自动驾驶系统的概述&#xff08;场景分类、开发路径和数据闭环等&#xff09;&#xff0c;第2章简介自动驾驶的基础理论&#xff0c;即计算机视觉和深度学习等&#xff0c;第3&#xff5e;4章是自动驾驶的软硬件平台分析&#xff0c;包括传感器…

面试:Redis

目录 一、缓存穿透 1、解决方案一&#xff1a; 2、解决方案二&#xff1a; 二、缓存击穿 1、解决方案一&#xff1a; 2、解决方案二&#xff1a; 三、缓存雪崩 1、解决方案一&#xff1a; 2、解决方案二&#xff1a; 3、解决方案三&#xff1a; 4、解决方案四&#x…

创建基于时间的 UUID

概述 在本文中&#xff0c;我们将会 对 UUIDs 和基于时间的 UUIDs&#xff08;time-based UUIDs&#xff09; 进行一些探讨。 当我们在对基于时间的 UUIDs 进行选择的时候&#xff0c;总会遇到一些好的方面和不好的方面&#xff0c;如何进行选择&#xff0c;也是我们将要简要…

数字签名学习

1 基本概念 数字签名是一种加密技术&#xff0c;用于验证信息来源的身份和数据的完整性。 就是对一个东西签上自己的名&#xff1b;收到的人可以验证这东西是你发的&#xff1b;这里是用数字的方式&#xff1b; 对字符串也可以签名&#xff0c;签名以后&#xff0c;还是一个…

《面向云计算的零信任体系第1部分:总体架构》行业标准正式发布

中华人民共和国工业和信息化部公告2024年第4号文件正式发布行业标准&#xff1a;YD/T 4598.1-2024《面向云计算的零信任体系 第1部分&#xff1a;总体架构》&#xff08;后简称“总体架构”&#xff09;&#xff0c;并于2024年7月1日正式施行。 该标准由中国信通院牵头&#xf…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-6.5

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

web安全---CSRF漏洞/OWASP-CSRFTester的使用

what 跨站请求伪造 Cross Site Request Forgery how 攻击者诱骗点击恶意网页&#xff0c;盗用&#xff08;伪造&#xff09;受害者的身份&#xff0c;以受害者的名义向服务器发送恶意请求,而这种恶意请求在服务端看起来是正常请求 CSRF&&XSS区别 他们最本质区别就…

什么是中间件?中间件有哪些?

什么是中间件&#xff1f; 中间件&#xff08;Middleware&#xff09;是指在客户端和服务器之间的一层软件组件&#xff0c;用于处理请求和响应的过程。 中间件是指介于两个不同系统之间的软件组件&#xff0c;它可以在两个系统之间传递、处理、转换数据&#xff0c;以达到协…

ArcGIS基础:便捷分享图层包和地图包

1、分享图层包&#xff1a; 首先&#xff0c;选中要分享的数据&#xff0c;右键创建图层包&#xff0c;修改保存路径。 找到项目描述那一栏&#xff0c;将摘要、标签、描述都填写分享图层包的相关内容。 一切设置好之后&#xff0c;点击右上角的【分析】按钮。 点击分析之后…

linux下安装anaconda

顺手点个关注吧&#xff0c;谢谢&#xff01; 一、下载安装包 https://repo.anaconda.com/archive/ 或者使用命令 wget https://repo.anaconda.com/archive/Anaconda3-5.3.1-Linux-x86_64.sh2.赋予权限并安装 # 给文件执行权限 chmod 777 Anaconda3-5.3.1-Linux-x86_64.sh# 执…

高频面试题:在浏览器搜索框中输入一个URL的完整请求过程?

相信很多小伙伴在校招或者社招面试中都遇到过这个问题 面试官&#xff1a;小伙子&#xff0c;了解 在浏览器搜索框中输入一个URL的完整请求过程吗&#xff1f;详细说说我&#xff1a;eeemm&#xff0c;不太清出具体的过程。整体过程应该是HTTP请求的过程。 如果在面试中不能很…

FinClip :可以让小程序脱离微信环境最快运行在自有App中

&#x1f9d0; 什么是FinClip&#xff1f; FinClip&#xff0c;一个可以让小程序脱离微信环境&#xff0c;最快运行在自有App中的神器。它支持在iPhone、Android、Windows、Linux、macOS、统信等平台下的应用中运行小程序&#xff0c;这意味着&#xff0c;无论是移动端、PC端&…

uniapp自定义返回事件(封装)

uniapp自定义返回事件 在我们使用uniapp时&#xff0c;我们导航栏一般都是自定义的&#xff0c;比如用uview框架的导航栏&#xff0c;那么返回事件通常会遇到以下几个问题 返回事件前需要做一些额外的处理 h5项目刷新页面后返回失效 返回按钮点击后到指定页面 如果只是监听返…

技术团队的管理方法和日常总结建议

管理学家德鲁克有言“管理是一种实践&#xff0c;其本质不在于知&#xff0c;而在于行&#xff0c;其验证不在于逻辑&#xff0c;而在于成果&#xff0c;其唯一的权威就是成就” &#xff0c;因此管理重实践看效果&#xff0c;但如果管理实践有理论依凭&#xff0c;那么实践起来…

新媒体运营-----短视频运营-----PR视频剪辑----视频调色

新媒体运营-----短视频运营-----PR视频剪辑-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/138079659 文章目录 1. Lumetri调色&#xff0c;明暗对比度2. Lumetri调色&#xff0c;创意与矢量示波器2.1 创意2.2 矢量示波器 3. L…

滑块验证码破解----Java使用opencv后端破解滑块验证

使用技术:Java SpringBootopenCV 在windows上首先需要下载opencv进行安装,先去官网:Releases - OpenCV 下载这个windows版本的安装包 下载后直接安装解压就行,然后需要,然后找到安装位置里的这个文件: 你下载的是什么版本的,这里的数字就是多少,比如我下载4.5.3版本那么这…

分治策略 --- 快排归并

目录 分治-快排 一、颜色分类 二、排序数组 三、数组中的第K个最大元素 四、库存管理 分治-归并 一、排序数组 二、交易逆序对的总数 三、计算右侧小于当前元素的个数 四、翻转对 分治是一种思想&#xff0c;也就是将大问题分解成小问题&#xff0c;一直分到小问题可…

2024年云仓酒庄新动态合肥北京双城开课,持续培训助力酒业发展

云仓酒庄合肥北京双城开课&#xff0c;持续培训助力酒业发展 随着国内酒类市场的不断繁荣与消费需求的日益增长&#xff0c;云仓酒庄作为行业内的稳扎稳打之一的企业&#xff0c;始终致力于提升服务质量和品牌影响力。近日&#xff0c;云仓酒庄在合肥与北京两地同时开设培训课…