MySQL索引最左匹配原则及优化原理(下)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: MySQL索引最左匹配原则及优化原理(下)

3.4 Btree索引的限制

  • 若不是从索引的最左列开始查找,则无法使用索引
  • 使用索引时不能跳过索引中的列
  • Not in和<>操作无法使用索引
  • 若查询中有某列的范围查询,则其右边所有列都无法使用索引

3.4.1 即使设置索引,也无法使用

  • “%”开头的LIKE语句,模糊匹配
  • OR语句,前后没有同时使用索引
  • 数据类型出现隐式转化(如varchar不加单引号,可能会自动转int型)

3.4.2 索引选择性与前缀索引

既然索引可加速查询,是否只要是查询语句,就建索引?

NO!因为索引虽然加速查询,但索引也有代价:索引文件本身要消耗存储空间。


索引会加重插入、删除和修改记录时的负担,增加写操作的成本

太多索引会增加查询优化器的分析选择时间

MySQL在运行时也要消耗资源维护索引

但索引绝非银弹,并非越多越好:

不推荐创建索引的场景

  • 查询中很少涉及的列
  • 例如,在查询中很少使用的列,有索引并不能提高查询的速度,相反增加了系统维护时间和消耗了系统空间

重复值较多的列

“性别”列只有列值“男”和“女”,增加索引并不能显著提高查询的速度

定义为text、image和bit数据类型的列

这些数据类型的数据列的数据量要么很大,要么很小,不利于使用索引

表记录比较少

例如一两千条甚至只有几百条记录的表,没必要建索引,让查询做全表扫描就好了

索引的选择性较低

索引的选择性(Selectivity),是指不重复的索引值(也叫基数,Cardinality)与表记录数(#T)的比值

Index Selectivity = Cardinality / #T

CREATE INDEX index_ name ON table(col_ name(n));

image.png

显然选择性的取值范围为(0, 1],选择性越高的索引价值越大,这是由B+Tree的性质决定的。

例如,上文用到的employees.titles表,如果title字段经常被单独查询,是否需要建索引,我们看一下它的选择性

image.png

title的选择性不足0.0001(精确值为0.00001579),所以实在没有什么必要为其单独建索引

前缀索引

用列的前缀代替整列作为索引key,当前缀长度合适时,可实现既使得前缀索引的选择性接近全列索引,又因为索引key变短而减少索引文件的大小和维护开销。

以employees.employees表为例介绍前缀索引的选择和使用。

从图12可以看到employees表只有一个索引<emp_no>,那么如果我们想按名字搜索人,就只能全表扫描

image.png

如果频繁按名字搜索员工,显然效率很低,考虑建索引。

有两种选择,建

  1. <first_name>
  2. <first_name, last_name>

看两个索引选择性:

image.png

<first_name>显然选择性太低,<first_name, last_name>选择性很好。

但first_name和last_name加起来长度30,有没有兼顾长度和选择性的办法?


可以考虑用first_name和last_name的前几个字符建立索引,例如<first_name, left(last_name, 3)>,看看其选择性

image.png

选择性还不错,但离0.9313还是有点距离,那么把last_name前缀加到4

image.png

这时选择性已很理想,而该索引长度仅18,比<first_name, last_name>短了一半。

把该前缀索引建上:


ALTER TABLE employees.employees

ADD INDEX first_name_last_name4 (first_name, last_name(4));

再执行一遍按名字查询,比较建索引前的结果

image.png

  • 性能提升显著,查询加速120多倍。

前缀索引兼顾索引大小和查询速度,但其

缺点

  • 不能用于ORDER BY和GROUP BY
  • 也不能用于Covering index(即当索引本身包含查询所需全部数据时,不再访问数据文件本身)

索引诗歌

全值匹配我最爱,最左前缀要遵守

带头大哥不能死,中间兄弟不能断

索引列上少计算,范围之后全失效

Like百分写最右,覆盖索引不写*

不等空值还有or,索引失效要少用

字符引号不能丢,SQL高级也不难

3.5 InnoDB的主键选择与插入优化

在使用InnoDB存储引擎时,如果没有特别的需要,请永远使用一个与业务无关的自增字段作为主键

经常看到有帖子或博客讨论主键选择问题,有人建议使用业务无关的自增主键,有人觉得没有必要,完全可以使用如学号或身份证号这种唯一字段作为主键。不论支持哪种论点,大多数论据都是业务层面的。

如果从数据库索引优化角度看,使用InnoDB引擎而不使用自增主键绝对是一个糟糕的主意


上文讨论过InnoDB的索引实现,InnoDB使用聚集索引,数据记录本身被存于主索引(一颗B+Tree)的叶子节点上。这就要求同一个叶子节点内(大小为一个内存页或磁盘页)的各条数据记录按主键顺序存放,因此每当有一条新的记录插入时,MySQL会根据其主键将其插入适当的节点和位置,如果页面达到装载因子(InnoDB默认为15/16),则开辟一个新的页(节点)。


如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页。如下图所示:

image.png

这样就会形成一个紧凑的索引结构,近似顺序填满

由于每次插入时也不需要移动已有数据,因此效率很高,也不会增加很多开销在维护索引上。

如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置:

image.png

此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增加了很多开销,同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。


因此,只要可以,请尽量在InnoDB上采用自增字段做主键。


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
16天前
|
关系型数据库 MySQL 索引
mysql 分析5语句的优化--索引添加删除
mysql 分析5语句的优化--索引添加删除
12 0
|
1天前
|
存储 缓存 关系型数据库
掌握MySQL数据库这些优化技巧,事半功倍!
掌握MySQL数据库这些优化技巧,事半功倍!
|
1天前
|
缓存 关系型数据库 MySQL
MySQL数据库优化技巧:提升性能的关键策略
索引是提高查询效率的关键。根据查询频率和条件,创建合适的索引能够加快查询速度。但要注意,过多的索引可能会增加写操作的开销,因此需要权衡。
|
2天前
|
SQL Oracle 关系型数据库
下次老板问你MySQL如何优化时,你可以这样说,老板默默给你加工资
现在进入国企或者事业单位做技术的网友越来越多了,随着去O的力度越来越大,很多国企单位都开始从Oracle向MySQL转移,相对于Oracle而言,MySQL最大的问题就是性能,所以,这个时候,在公司如果能够处理好MySQL的性能瓶颈,那么你也就很容易从人群中脱颖而出,受到老板的青睐。
20 1
|
10天前
|
SQL 关系型数据库 数据库
【后端面经】【数据库与MySQL】SQL优化:如何发现SQL中的问题?
【4月更文挑战第12天】数据库优化涉及硬件升级、操作系统调整、服务器/引擎优化和SQL优化。SQL优化目标是减少磁盘IO和内存/CPU消耗。`EXPLAIN`命令用于检查SQL执行计划,关注`type`、`possible_keys`、`key`、`rows`和`filtered`字段。设计索引时考虑外键、频繁出现在`where`、`order by`和关联查询中的列,以及区分度高的列。大数据表改结构需谨慎,可能需要停机、低峰期变更或新建表。面试中应准备SQL优化案例,如覆盖索引、优化`order by`、`count`和索引提示。优化分页查询时避免大偏移量,可利用上一批的最大ID进行限制。
37 3
|
12天前
|
存储 关系型数据库 MySQL
【MySQL实战笔记】 04 | 深入浅出索引(上)-02
【4月更文挑战第9天】InnoDB数据库使用B+树作为索引模型,其中主键索引的叶子节点存储完整行数据,非主键索引则存储主键值。主键查询只需搜索一棵树,而非主键查询需两次搜索,因此推荐使用主键查询以提高效率。在插入新值时,B+树需要维护有序性,可能导致数据页分裂影响性能。自增主键在插入时可避免数据挪动和页分裂,且占用存储空间小,通常更为理想。然而,如果场景仅需唯一索引,可直接设为主键以减少查询步骤。
15 1
【MySQL实战笔记】 04 | 深入浅出索引(上)-02
|
15天前
|
关系型数据库 MySQL 数据库
6. 了解过Mysql的索引嘛 ?
了解MySQL的索引类型,包括单列索引(普通、唯一、主键和全文索引)和组合索引。单列索引用于一列,如普通索引允许重复值,唯一索引和主键索引不允许,后者不允许空值。全文索引适用于特定文本字段。组合索引是多列的,遵循左前缀原则,通常推荐用于提高查询效率,除非是主键。
16 0
|
17天前
|
关系型数据库 MySQL 数据库
mysql卸载、下载、安装(window版本)
mysql卸载、下载、安装(window版本)
|
6天前
|
关系型数据库 MySQL 数据库
《MySQL 简易速速上手小册》第1章:MySQL 基础和安装(2024 最新版)
《MySQL 简易速速上手小册》第1章:MySQL 基础和安装(2024 最新版)
28 4
|
30天前
|
Ubuntu 关系型数据库 MySQL
Ubuntu 中apt 安装MySQL数据库
Ubuntu 中apt 安装MySQL数据库
69 0