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

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 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不仅要保存数据,还要保存一下索引文件,建立索引会占用磁盘空间的索引文件。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
5天前
|
SQL 关系型数据库 MySQL
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
42 9
|
6天前
|
存储 SQL 关系型数据库
MySQL进阶突击系列(03) MySQL架构原理solo九魂17环连问 | 给大厂面试官的一封信
本文介绍了MySQL架构原理、存储引擎和索引的相关知识点,涵盖查询和更新SQL的执行过程、MySQL各组件的作用、存储引擎的类型及特性、索引的建立和使用原则,以及二叉树、平衡二叉树和B树的区别。通过这些内容,帮助读者深入了解MySQL的工作机制,提高数据库管理和优化能力。
|
9天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
50 18
|
2天前
|
存储 Oracle 关系型数据库
索引在手,查询无忧:MySQL索引简介
MySQL 是一款广泛使用的关系型数据库管理系统,在2024年5月的DB-Engines排名中得分1084,仅次于Oracle。本文介绍MySQL索引的工作原理和类型,包括B+Tree、Hash、Full-text索引,以及主键、唯一、普通索引等,帮助开发者优化查询性能。索引类似于图书馆的分类系统,能快速定位数据行,极大提高检索效率。
23 8
|
8天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
17 7
|
7天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化与慢查询优化:原理与实践
通过本文的介绍,希望您能够深入理解MySQL索引优化与慢查询优化的原理和实践方法,并在实际项目中灵活运用这些技术,提升数据库的整体性能。
27 5
|
12天前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
82 15
|
6天前
|
SQL 关系型数据库 MySQL
数据库数据恢复—Mysql数据库表记录丢失的数据恢复方案
Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、Mysql数据库表中无任何数据或只有部分数据。 2、客户端无法查询到完整的信息。
|
13天前
|
关系型数据库 MySQL 数据库
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。
|
17天前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。

推荐镜像

更多
下一篇
DataWorks