MySQL(二)索引原理以及优化

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MySQL(二)索引原理以及优化



前言

MySQL数据库是用来保存海量数据的,但是海量数据涉及到一个快速查找问题,怎么从海量数据查找到我想要的数据呢?

常见的办法就是将表中每一列类比成索引来定位我是这一列哪一个单元。那我定位表中这一列的某一个数据,就通过索引去查找就好了。

但肯定不能一个一个去遍历,这里就涉及到MySQL 数据库的数据结构组成。用一些数据结构可以加快查找效率。

而MySQL常用的innodb存储引擎采用的是B+树作为索引的数据结构。

为什么选B+树?

简单说一下有哪些便于查找的数据结构和不足:

  • 有序数组+二分法:数组不便于增删节点,增删节点需变化节点之后的数据。
  • 二分查找树:解决了增删节点的问题,但是可能会退化成链表。
  • 平衡二叉树:解决了退化链表的问题,但是数据多了,树的高度会很高(二叉树的每多一层就需要多一次IO磁盘操作)。且插入删除数据自旋节点的次数会比较多。
  • 红黑树:不是完全平衡,但可以减少增删节点的自旋次数。同样有树的高度会很高的问题。
  • B树:解决了树高度问题,但是每个节点包含了索引和数据,IO操作会占用内存资源。并且范围查找效率也不是很高。

最后来到了B+树:解决了范围查找,IO磁盘次数这些问题。

详细内容参考https://www.xiaolincoding.com/mysql/index/why_index_chose_bpuls_tree.html


一、索引

索引存储结构分类:聚集索引和非聚集索引

刚刚提到MySQL 用的B+树存储索引。聚集索引和非聚集索引都是用各自的B+树存储的。

区别在于:

  • 聚集索引的叶子节点存放的是实际数据,所有完整的用户记录都存放在聚集索引的叶子节点。
  • 非聚集索引的叶子节点存放的是主键值(就是聚集索引值),而不是实际数据。

例子:S0001是辅助索引,生成的B+树的叶子节点存的是主键的值,通过辅助索引查数据时需要先找到主键,再在主键的表中找到相应的数据。

详细内容参考:https://juejin.cn/post/7001094401858469918


索引除了结构分类,还可以通过使用特性分类:主键索引、唯一索引、普通索引、组合索引、以及全文索引(elasticsearch);

主键索引

非空唯一索引,一个表只有一个主键索引;在 innodb 中,主键索引的 B+ 树包含表数据信息;

PRIMARY KEY(key)

唯一索引

不可以出现相同的值,可以有 NULL 值;

UNIQUE(key)

普通索引

允许出现相同的索引内容;

INDEX(key)
-- OR
KEY(key[,...])

组合索引

对表上的多个列进行索引

INDEX idx(key1,key2[,...]);
UNIQUE(key1,key2[,...]);
PRIMARY KEY(key1,key2[,...]);

使用组合索引可以减少开销,因为分开的话,一个索引需要建立一个B+树,而组合索引只需要一颗B+树。

全文索引

将存储在数据库当中的整本书和整篇文章中的任意内容信息查找出来的技术;关键词 FULLTEXT;

在短字符串中用 LIKE % ;在全文索引中用 match 和against ;

FULLTEXT(KEY)
SELECT * FROM article WHERE MATCH(title,content)AGAIN('查询字符串');

————————————————

上述只有主键索引是聚集索引,其他索引都是辅助索引;例如唯一索引,普通索引等。

二、主键选择

innodb 中表是索引组织表,每张表有且仅有一个主键,可以设置,也可以让系统自动生成;

如果显示设置 PRIMARY KEY ,则该设置的 key 为该表的主键;

如果没有显示设置,则从非空唯一索引中选择;

只有一个非空唯一索引,则选择该索引为主键;

有多个非空唯一索引,则选择声明的第一个为主键;

没有非空唯一索引,则自动生成一个 6 字节的 _rowid 作为主键;

约束

为了实现数据的完整性,对于 innodb,提供了以下几种约束,primary key,unique key,foreign key,default,not null;

外键约束

外键用来关联两个表,来保证参照完整性;MyISAM 存储引擎本身并不支持外键,只起到注释作用;而 innodb 完整支持外键,并具备事务性;

create table parent (
id int not null,
primary key(id)
) engine=innodb;
create table child (
id int,
parent_id int,
foreign key(parent_id) references parent(id)
ON DELETE CASCADE ON UPDATE CASCADE
) engine=innodb;
-- 被引用的表为父表,引用的表称为子表;
-- 外键定义时,可以设置行为 ON DELETE 和 ON UPDATE,行
为发生时的操作可选择:
-- CASCADE 子表做同样的行为
-- SET NULL 更新子表相应字段为 NULL
-- NO ACTION 父类做相应行为报错
-- RESTRICT 同 NO ACTION
INSERT INTO parent VALUES (1);
INSERT INTO parent VALUES (2);
INSERT INTO child VALUES (10, 1);
INSERT INTO child VALUES (20, 2);
DELETE FROM parent WHERE id = 1;

约束与索引的区别

创建主键索引或者唯一索引的时候同时创建了相应的约束;

约束是逻辑上的概念;

索引是一个数据结构既包含逻辑的概念也包含物理的存储方式;

索引存储

innodb 由段、区、页组成;段分为数据段、索引段、回滚段等;区大小为 1 MB(一个区由 64 个连续页构成);页的默认值为 16k;页为逻辑页,磁盘物理页大小一般为 4K 或者 8K;为了保证区中的页的连续,存储引擎一般一次从磁盘中申请4~5 个页;

页是 innodb 磁盘管理的最小单位;默认16K,可通过innodb_page_size 参数来修改;

特点:

B+ 树的一个节点的大小就是该页的值;

主键B+树非叶子节点中的页数据存储的是索引,叶子节点存储的是索引和表的行数据。

自增id

超过类型最大值会报错;

big int 类型 的范围:(-263 ,263-1)

假设采用 big int 类型的话,1 秒插入 1 亿条数据,大概需要 5849 年才会用完索引;

最左匹配原则

对于组合索引,从左到右依次匹配,遇到 > < between like就停止匹配会采用遍历查询。索引组合索引时尽量避免使用范围查询。

覆盖索引

从非聚集索引中就能找到数据,而不需通过聚集索引查找;利用非聚集索引树高度一般低于聚集索引树;较少磁盘 IO;所以用select时,尽量避免使用 select * from …。应该将所需要的列都标明。

索引下推

为了减少回表次数,提升查询效率;在 MySQL 5.6 的版本开始推出;

MySQL 架构分为 server 层和存储引擎层;

没有索引下推机制之前,server 层向存储引擎层请求数据,在server 层根据索引条件判断进行数据过滤;

有索引下推机制之后,将部分索引条件判断下推到存储引擎中过滤数据;最终由存储引擎将数据汇总返回给 server 层;

索引失效

  • select … where A and B 若 A 和 B 中有一个不包含索引,则索引失效;
  • 索引字段参与运算,则索引失效;例如:select * from student where id-1 = 1;
  • 索引字段发生隐式转换,则索引失效;例如:将列隐式转换为某个类型,实际等价于在索引列上作用了隐式转换函数;例如查询字符串时没用引号括起来,导致转换成int类型。
  • LIKE 模糊查询,通配符 % 开头,则索引失效;例如: select * from user where name like ‘%Mark’;
  • 组合索引中,没使用第一列索引,索引失效;
  • 查询条件中有or;例如SELECT * FROM student where id =1 or birthday = “2021-12-23”;

索引失效就会使用全表查询,也就是遍历查询,非常耗时。

索引原则

  • 查询频次较高且数据量大的表建立索引;索引选择使用频次较高,过滤效果好的列或者组合;
  • 使用短索引;节点包含的信息多,较少磁盘 IO 操作;比如:smallint , tinyint ;
  • 对于很长的动态字符串,考虑使用前缀索引;
  • 对于组合索引,考虑最左侧匹配原则和覆盖索引;
  • 尽量选择区分度高的列作为索引;该列的值相同的越少越好;
  • 尽量扩展索引,在现有索引的基础上,添加复合索引;最多6个索引。
  • 不要 select * ; 尽量只列出需要的列字段;方便使用覆盖索引;
  • 索引列,列尽量设置为非空;
  • 可选:开启自适应 hash 索引或者调整 change buffer;

后记

索引大大提高了查询速度,同时却会降低更新表的速度,比如对表进行INSERT,UPDATE和DELETE。因为更新表时,Mysql不仅要保存数据,还要保存一下索引文件,建立索引会占用磁盘空间的索引文件。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
打赏
0
0
0
0
1
分享
相关文章
Mysql的索引
MYSQL索引主要有 : 单列索引 , 组合索引和空间索引 , 用的比较多的就是单列索引和组合索引 , 空间索引我这边没有用到过 单列索引 : 在MYSQL数据库表的某一列上面创建的索引叫单列索引 , 单列索引又分为 ● 普通索引:MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一点。 ● 唯一索引:索引列中的值必须是唯一的,但是允许为空值 ● 主键索引:是一种特殊的唯一索引,不允许有空值 ● 全文索引: 只有在MyISAM引擎、InnoDB(5.6以后)上才能使⽤用,而且只能在CHAR,VARCHAR,TEXT类型字段上使⽤用全⽂文索引。
MySQL实现文档全文搜索,分词匹配多段落重排展示,知识库搜索原理分享
本文介绍了在文档管理系统中实现高效全文搜索的方案。为解决原有ES搜索引擎私有化部署复杂、运维成本高的问题,我们转而使用MySQL实现搜索功能。通过对用户输入预处理、数据库模糊匹配、结果分段与关键字标红等步骤,实现了精准且高效的搜索效果。目前方案适用于中小企业,未来将根据需求优化并可能重新引入专业搜索引擎以提升性能。
100 5
MySQL细节优化:关闭大小写敏感功能的方法。
通过这种方法,你就可以成功关闭 MySQL 的大小写敏感功能,让你的数据库操作更加便捷。
72 19
MySQL底层概述—8.JOIN排序索引优化
本文主要介绍了MySQL中几种关键的优化技术和概念,包括Join算法原理、IN和EXISTS函数的使用场景、索引排序与额外排序(Using filesort)的区别及优化方法、以及单表和多表查询的索引优化策略。
139 22
MySQL底层概述—8.JOIN排序索引优化
MySQL索引有哪些类型?
● 普通索引:最基本的索引,没有任何限制。 ● 唯一索引:索引列的值必须唯一,但可以有空值。可以创建组合索引,则列值的组合必须唯一。 ● 主键索引:是特殊的唯一索引,不可以有空值,且表中只存在一个该值。 ● 组合索引:多列值组成一个索引,用于组合搜索,效率高于索引合并。 ● 全文索引:对文本的内容进行分词,进行搜索。
RDS用多了,你还知道MySQL主从复制底层原理和实现方案吗?
随着数据量增长和业务扩展,单个数据库难以满足需求,需调整为集群模式以实现负载均衡和读写分离。MySQL主从复制是常见的高可用架构,通过binlog日志同步数据,确保主从数据一致性。本文详细介绍MySQL主从复制原理及配置步骤,包括一主二从集群的搭建过程,帮助读者实现稳定可靠的数据库高可用架构。
144 9
RDS用多了,你还知道MySQL主从复制底层原理和实现方案吗?
MySQL底层概述—7.优化原则及慢查询
本文主要介绍了:Explain概述、Explain详解、索引优化数据准备、索引优化原则详解、慢查询设置与测试、慢查询SQL优化思路
158 15
MySQL底层概述—7.优化原则及慢查询
MySQL底层概述—6.索引原理
本文详细回顾了:索引原理、二叉查找树、平衡二叉树(AVL树)、红黑树、B-Tree、B+Tree、Hash索引、聚簇索引与非聚簇索引。
125 11
MySQL底层概述—6.索引原理
基于SQL Server / MySQL进行百万条数据过滤优化方案
对百万级别数据进行高效过滤查询,需要综合使用索引、查询优化、表分区、统计信息和视图等技术手段。通过合理的数据库设计和查询优化,可以显著提升查询性能,确保系统的高效稳定运行。
73 9
MySQL和SQLSugar百万条数据查询分页优化
在面对百万条数据的查询时,优化MySQL和SQLSugar的分页性能是非常重要的。通过合理使用索引、调整查询语句、使用缓存以及采用高效的分页策略,可以显著提高查询效率。本文介绍的技巧和方法,可以为开发人员在数据处理和查询优化中提供有效的指导,提升系统的性能和用户体验。掌握这些技巧后,您可以在处理海量数据时更加游刃有余。
189 9