MySQL 表和索引优化实战|学习笔记(一)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 快速学习 MySQL 表和索引优化实战

开发者学堂课程【MySQL 实战进阶MySQL 表和索引优化实战】学习笔记,与课程紧密联系,让用户快速学习知识

课程地址:https://developer.aliyun.com/learning/course/83/detail/1310


MySQL 表和索引优化实战


内容介绍:

一、主键索引

二、二级索引

三、数学分析

四、索引的作用

 

一、主键索引

本课程和大家分享 RDS for MySQL 表和索引的优化经验。

作为数据库的使用者来说,避免不了会接触两个概念,一个是表,一个是索引。在日常的思维中表是用来存储表中的数据,索引一般是用来加速查询访问。

RDS for MySQL innodb 引擎下的数据真正物理组织,是怎么组织的?首先有这样一张表

image.png

它的主键是一个 mp  四个字节的整形的 id 作为主键,后面跟着一个单字符的clumn1,还有一个 int 类型的 column 2,单字符的 column 3。在c1字段上会有一个索引,就是一个很简单的一张表。

下面看它的数据是如何组织的。

 image.png

首先说明一下在 innodb 引擎下实际上数据是存储在主键中的,数据是通过主键来物理组织的。它跟 airkong 本身默认的堆表不一样,airkong 本身默认创建的表如果不特定指定的话,是一个堆表,它真的有一个对象数据结构堆的数据结构来存储数据,同时主键是另外一个数据结构,是真的是这样两份的数据。对于 MySQL innodb 的引擎,它本身的数据是存储在主键的叶子节点中的,column1column2column3这三列数据都存储在主键的叶子节点中。

主键本身从数据结构存储的数据结构上来看是 B+TRee,说明一下 B+TRee 本身是一个 b 树,b 指的是 balance TRee,就是平衡树,完整的名字叫做多路平衡树。多路平衡树本身是一个平衡树,而不是binary TReebinary TRee 是一个二叉树,这是作为数据库 DBA 的基本功。多路平衡树和二叉树的区别在于二叉树只有左分支和右分支,而且不限定左分支和右分支的深度,也可以理解为树的高度,不限定左分支和右分支的高度必须一致的;多路平衡树首先是一个平衡树,

image.png

最上面的节点叫做根节点,从根节点到任何一个叶子节点,通走的节点数是要一致的,树高从任何一个维度来看,从任何一个叶子节点到根,从根到任何一个叶子节点必须得是一致的,就是左右是平衡的。多路的意思是每一个节点的分支节点也好,根节点也好,下面可以有多个子节点,而不只限定只有左节点、右节点。

同时在整个的结构里面,如果对 oracle 比较熟,oracle 有一个叫 block size,在 oracle 体系中对于每一个存储的基础来源叫做block

MySQL 当中叫做叶,叫做配置,实际上是一样的概念。在 MySQL 里面,如果不特意指定的话,默认16KB 作为叶。如果从磁盘上访问一行数据,哪怕需要访问一个字节,也要这16 KB 的磁盘块,注意这是一个区的,不是真正的这个磁盘的,大小磁盘可能是4KB 的。四个4 KB 的组成一个16KB 的逻辑块,需要读16 KB 的数据到内存中。

这个结构里面,数据组织结构之后有几个关键的地方,第一个是数据是存储在主键中的,创建这张表的时候,最佳时间就是必须要显示的定义主键。

不显示定义主键的话,会出现两种情况,一种情况是在做数据传输的时候,没有办法决定这张数据是否重复,是否是唯一的,主键的定义是非空、唯一。另外一种情况是当 RDS for MySQL 的备份还原到线下的开源版本中,没有主键的表,读取的时候会发现字段对不上的情况。因为内部阿里的 sql ,实际上 RDS for MySQL MySQL  的生态体系中是正式的阿里 sql,是一个 MySQL  的分支。对于这个分支来说,为了避免出现没有定义主键,导入了很多问题,如果这张表不显示定义主键,默认的会隐式的给它增加一个字段,这个字段对应用和用户来说都是不可见的,但是把物理备份还原到本地的时候,会发现访问这张表多出一个字段,这个隐式的字段会导致恢复的时候这张表不可访问。

所以最佳时间,既然是一棵树,数据要存储在树里面,存储在主键里面,就要显示定义主键。

image.png

这张表每个数据块的大小都是16 KB,这个分支节点也是16 KB,是不是这个分支节点下胯的节点数越多,这棵树可以越扁,就是树高可以越小。树高是从根节点到叶子节点中间走过多少配置,就是它的树高,树高跟性能相关。

日常访问的表,如果不是非常频繁访问的表,而且内存容量比较有限的情况下,根和分支节点都是在内存中的。但是需要访问数据块的话,需要从根访问到分支,再到叶子节点。

如果树高很高的话,而且内存很紧张,分支如果不在内存中的话,需要把分支节点先读进来,在到读叶子节点。数高越高,需要读的16 KB的块数就越多,也就是说,同样访问一行数据,需要比树高小的索引,要访问额外多的数据量,这种承载IO本身紧张的资源的情况下,就会导致查询更慢。因为访问数据花费的代价要比别人多,树高越高,访问叶子节点的代价就越大。这导致了在块的尺寸固定的情况下,如果里面可呆的条目数越多,下胯的节点数就越多,节点数越多,就可以让叶子节点数量在固定的情况下,已知的情况下,树高就越小,这个数据越扁平。

大家可以想一想,一个公司组织架构里面,如果中层领导越强,下面呆的部门越多,整个公司的组织结构会越扁平化。

第三件事情,在块的尺寸固定的情况下,这里面的条目数越多,树高越小,访问数据的代价就低。这取决于本身对主键的数据类型是有要求的,如果在 int 类型四个字节,big int 八个字节,如果这是一个个 ychar,但是它会保留固定的长度。如果使用一个字符串,是在 utf8 这个字符集的情况下,像column 1 这个类型,utf8 至少需要三个字节,utf8mb4 需要4个字节,所以最佳的时间就是主键尽量是 int 或者是 big int,最终整形。因为它本身很小,四个字节、八个字节,通常情况下,一个16 KB 的块能放几百个这样的条目。正常情况下,能放几百个条目,树高就很容易控制在三或者四,三是常见的,四已经不小了,三或者四这个水平量。或者是数据的分析,这是第三件事情。

第四件事情,它是一个平衡树。平衡树的要求就在于左边的分支,从根到任何一个叶子节点,树高都要固定。当这棵树不断的被修改,不断的增删改的情况下,这棵树实际上是在时刻变化的。为了保证根始终到树高是一致的,保证树跟着数据修改随时在变化,这个时候会带来一个问题,如果每次插入的数据都是在中间,而这棵树本身已经很大,一亿行记录了一张表,每次插入的数据都不是可预期的,都是随机的插到树的不同的地方。是不是经常需要把链表打开,把结构打开,到内存里把链表打开,然后把它重新组织成需要的合理的树,然后再拼在一起。这个对写的代价会非常大,尤其对于 insert 来说,写的代价非常大。

因为每次插入的数据都不是可预期的,不是朝着一个方向来变化的,每次都是随机的,就会导致写入的 rt 响应时间变得不可预期,总体指令会比较高。第四件事情就是主键除了数据类型有要求以外,建议用 or to improvement 正向递增,或者使用 SQL 字段,比如说有 RDS polar x 的场景下,或者是 SQL 引擎的情况下,sql 或者or to improvement 保证它单向递增,保证每次写入或插入的操作性能比较一致,避免总要把一棵树拆开,再拼在一起。这是这张表在做表设计的时候,它本身是一个主键,根据主键存储的物理存储的数据结构,引出了四个。第一个是必须定义主键,第二个主键数据类型要尽量的小,第三个介绍了树高、16 KB 的块,第四个auto increment 要正向的去插。

 

二、二级索引

MySQL key index 是同义词,除了主键以外的索引都称之为二级索引,看下图所示的索引

image.png

 

这个索引跟主键一样,也是 B+TRee 索引,它下面的每一个链表,跟叶子节点之间是双向链表,也是一颗多路平衡树。但是它跟 oracle 本身在设计上有一点不一样,c1 字段做了一个索引,但实际上在存储值的时候,因为数据是存储在主键中的,所以数据在停止的时候没有必要放数据的真正的物理地址,在 oracle 里放的是物理地址,但是在 MySQL 里面这里直接放的是主键的值,因为知道主键的值,就能唯一的定位到这行记录。实际上,虽然在这里放了c1,但是真正在存储的时候是把叶子节点值存起来的,反过来也就是说,主键的数据类型,导致了存储长度要尽量的小,如果主键真的很大的话,会出现问题。

补充一下,主键除了之前说的单向递增数据类型要小以外,比如说像 uuid 这种不建议做主键,因为太长了。如果字段太长的话,磁盘块里的方子会很小,数额会变得很臃肿。存储相同的数据量索引会占更大的空间,这对 IO 来说会产生很大的影响,相同硬件条件下比别人要慢,访问数据速度要慢,因为开销大,成本高。

 

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
4月前
|
缓存 关系型数据库 MySQL
MySQL索引策略与查询性能调优实战
在实际应用中,需要根据具体的业务需求和查询模式,综合运用索引策略和查询性能调优方法,不断地测试和优化,以提高MySQL数据库的查询性能。
385 66
|
2月前
|
存储 关系型数据库 MySQL
MySQL索引学习笔记
本文深入探讨了MySQL数据库中慢查询分析的关键概念和技术手段。
301 80
|
4月前
|
SQL 关系型数据库 MySQL
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
MySQL慢查询优化、索引优化,是必知必备,大厂面试高频,本文深入详解,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
|
5月前
|
存储 SQL 关系型数据库
Mysql学习笔记(二):数据库命令行代码总结
这篇文章是关于MySQL数据库命令行操作的总结,包括登录、退出、查看时间与版本、数据库和数据表的基本操作(如创建、删除、查看)、数据的增删改查等。它还涉及了如何通过SQL语句进行条件查询、模糊查询、范围查询和限制查询,以及如何进行表结构的修改。这些内容对于初学者来说非常实用,是学习MySQL数据库管理的基础。
219 6
|
3月前
|
缓存 关系型数据库 MySQL
MySQL 索引优化与慢查询优化:原理与实践
通过本文的介绍,希望您能够深入理解MySQL索引优化与慢查询优化的原理和实践方法,并在实际项目中灵活运用这些技术,提升数据库的整体性能。
218 5
|
4月前
|
SQL 关系型数据库 MySQL
MySQL慢查询优化、索引优化、以及表等优化详解
本文详细介绍了MySQL优化方案,包括索引优化、SQL慢查询优化和数据库表优化,帮助提升数据库性能。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
MySQL慢查询优化、索引优化、以及表等优化详解
|
4月前
|
关系型数据库 MySQL Java
MySQL索引优化与Java应用实践
【11月更文挑战第25天】在大数据量和高并发的业务场景下,MySQL数据库的索引优化是提升查询性能的关键。本文将深入探讨MySQL索引的多种类型、优化策略及其在Java应用中的实践,通过历史背景、业务场景、底层原理的介绍,并结合Java示例代码,帮助Java架构师更好地理解并应用这些技术。
150 2
|
5月前
|
SQL 关系型数据库 MySQL
Mysql学习笔记(三):fetchone(), fetchmany(), fetchall()详细总结
MySQL中用于数据检索的`fetchone()`, `fetchmany()`, `fetchall()`函数的功能、SQL语句示例和应用场景。
149 3
Mysql学习笔记(三):fetchone(), fetchmany(), fetchall()详细总结
|
5月前
|
SQL Ubuntu 关系型数据库
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用
本文为MySQL学习笔记,介绍了数据库的基本概念,包括行、列、主键等,并解释了C/S和B/S架构以及SQL语言的分类。接着,指导如何在Windows和Ubuntu系统上安装MySQL,并提供了启动、停止和重启服务的命令。文章还涵盖了Navicat的使用,包括安装、登录和新建表格等步骤。最后,介绍了MySQL中的数据类型和字段约束,如主键、外键、非空和唯一等。
119 3
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用
|
4月前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
737 1