Mysql专栏 - mysql索引(三)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: Mysql专栏 - mysql索引(三)


Mysql专栏 - mysql索引(三)

前言

上一节我们详细解释了mysql的聚簇索引部分以及mysql的索引使用匹配规则,其中最重要的内容是最左匹配的规则,由此可以推导出很多规则的应用,所以需要重点进行关,而其他的内容只需要学习即可。

学习内容:

  1. 学习如何设计索引
  2. 设计索引如何避坑
  3. 如何让你的查询百分百能用上索引

建立索引的建议

下面是日常建立索引的一些建议:

  • 经常被查询或者排序的字段
  • 值比较多的字段,对于优化索引的查询价值越高
  • 对于字段比较小的类型进行查询,比如tinyint , char 等等
  • 尽量使用主键自增而不是使用uuid
  • 索引不需要设计太多
  • **如果使用了范围查询,多数情况下是无法使用索引的,**所以应该把范围查询放到查询的最右边。
  • 第一个范围查询可以用上索引,第二个无法用上索引,所以范围查询最好只有一个

索引的使用问题:

分页与排序

在上一节我们讨论过对于大多数的分页以及排序,其实都是没有办法使用索引的,因为联合索引必须按照最左侧的方式进行查找。

案例:

比如我们在查询省份城市和性别,有时候要按照不同的字段进行查询,所以很多情况下无法应用最左匹配的原则。

解决办法:

与其如此,还不如就把类似省份、城市和性别三个字段,都放在联合索引的最左侧,这样跟其他字段组合,联合索引后,让大部分的查询都可以直接通过索引树就可以把where条件指定的数据筛选出来了。

建议:在设计的时候可以按照多设计几个字段的索引并且按照从左到右的查询方式进行匹配,最后一个使用范围值进行处理,这样就可以使得整个查询都可以用得上索引了。

mysql执行计划

什么是执行成本?

首先是执行计划的成本,我们在计算的时候,会把CPU的成本,符合成本就是0.2,从磁盘读取到内存的成本被设置为1

如何计算成本:首先我们可以:show table status like "表名",对于innodb来说,这个rows是估计值,下面是对应的估计值内容:

  • Rows: 就是表里的记录数,
  • data_length: 就是表的聚簇索引的字节数大小

页数量如何计算:

  • data_length除以1024就是kb为单位的大小,然后再除以16kb(默认一页的大小),就是有多少页
  • IO成本就是:数据页数量 * 1.0 + 微调值,CPU成本就是:行记录数 * 0.2 + 微调值

索引访问速度估算

  1. 首先需要估算计算的范围,比如按照NAME的范围值,如果只存在一个范围,通常在一个数据页进行扫描。
  2. 假设二级索引的效率为100页,然后使用0.2也就是20,这是二级索引的速度
  3. 然后二级索引需要回表操作,此时就需要回到聚簇索引的表进行查找 。

常见的优化方式:

常量替换

在sql进行优化查询的时候,会把一些范围查询的值转为常量搜索,select * from t1 join t2 on t1.x1=t2.x1 and t1.id=1,经过替换后如下:select t1表中id=1的那行数据的各个字段的常量值,最终替换的结果为:t2.* from t1 join t2 on t1表里x1字段的常量值 =t2.x1

子查询

首先,一个子查询会分为两个语句,首先会根据主键的聚簇索引开始对于内容进行查找。 对于上述的子查询,执行计划会被优化为,先执行子查询,也就是select x2 from t2 where x3=xxx这条SQL语句,把查出来的数据都写入一个临时表里,也可以叫做物化表,意思就是说,把这个中间结果集进行物化。

半连接的优化

首先,MYSQL没有半链接这种语法,这是底层对于JOIN以及IN查询的一种优化手段,select t1.* from t1 semi join t2 on t1.x1=t2.x2 and t2.x3=xxx,如果使用半链接的手段,其实可以只链接符合ON条件的半链接表即可。

执行计划和SQL语句的关系:虽然索引可以解决不太复杂的单表查询的情况,但是很多时候,统计,汇总,函数等SQL的使用还是会降低整个SQL的查询和使用速度。

性能指标:

下面是三条基本的原则:

  1. 主键索引查询肯定是CONST
  2. 二级索引想要是是CONST,你的索引必须是唯一索引 才行 - UNIQUE KEY。但是如果使用 IS NULL这种查询方式,依然使用的REF的方式。
  3. 另外,如果查询的是按照索引的顺序列进行查询,但是WHERE条件不是,一样可以使用索引直接找叶子节点的方式。
  4. 类似于select * from table where name=x and name IS NULL,那么此时在执行计划里就叫做ref_or_null
  5. 普通索引的查询方式是REF,类似INDEX(NAME, AGE)
  6. 范围查询的时候会使用RANGE的查询方式
  7. 针对这种只要遍历二级索引就可以拿到你想要的数据,而不需要回源到聚簇索引的访问方式,就叫做index访问方式!INDEX的方式需要遍历某个二级索引,但是因为二级索引比较小,所以遍历性能也还可以的。

现在我们停一下脚步,思考一下,之前说的const、ref和range,本质都是基于索引树的二分查找和多层跳转来查询,所以性能一般都是很高的,然后接下来到index这块,速度就比上面三种要差一些了,因为他是走遍历二级索引树的叶子节点的方式来执行了,那肯定比基于索引树的二分查找要慢多了,但是还是比全表扫描好一些的。

驱动表和被驱动表

驱动表:指的是关联查询条件先需要进行筛选的表,通常位于表的前面

被驱动表:通常需要根据一个表的关联数据找到另一张表的内容进行关联,所以叫被驱动表。

驱动规则

循环嵌套规则:我们假设在驱动表里面找到了10条数据,通过驱动表的部分字段找到被驱动的数据,就意味着需要在被驱动表里面执行驱动表次数的查找。

比如驱动表为10次,被驱动表就需要扫描整个表10次。

explain计划

基本的字段格式:

首先需要了解EXPLAIN的基本格式

  1. 首先,一个select就会出现一个id, 通常在复杂的查询里面会包含多张表的查询,比如join, in等等
  2. SelecT_TYPE:这个表示的是查询的类型
  3. Table:表名称
  4. Partitions:这个表示表空间,分区的概念
  5. Type : 比如查询的优化等级, const, index, all,分别代表了聚簇索引,二级索引,全表扫描的查询搜索方式
  6. PossiblEkeys:和type一样确定访问方式,确定有哪些索引可以选择,
  7. Key:确定有哪些可以提供选择,同时提供索引的对应长度
  8. Key_len: 表示的是索引的长度
  9. Ref: 等值匹配的时候出现的一些匹配的相关信息
  10. Rows: 预估通过所索引或者别的方式读取多少条数据
  11. Filtered:经过搜索条件过滤之后的剩余数据百分比。
  12. extra:额外的信息不重要。

下面为一个简单的案例:

expain select * from (select x1,count(*) as cnt from t1 group by x1) as _t1 where cnt > 10

查询的结果如下:

DERIVED:表示子查询的结果会物化为一个内部的临时表,然后外层的查询针对临时表物化开始进行搜索分组聚合的时候,使用的索引的方式,所以是index的扫描速度。

关于查询等级:

  1. const: 一般是主键查询的时候
  2. Ref: 基于某个耳机索引的时候进行查询
  3. Eq_ref: 表示连接查询是根据二级索引索引关联的
  4. Eq_ref_null: 二级索引的关联的时候根据Null值允许进行关联查询
  5. Index_merge: ×询可能会基于多个索引提取数据后进行合并
  6. Range:而查询方式是range的话就是基于二级索引进行范围查询

Using filesort

这个会在排序的时候见到,特别是分页的排序查询,这个需要极力的避免,因为不走索引的排序是非常非常慢的,需要使用Memory表进行数据的操作。

Using temprory

通常出现在大量的group union distinct 等等的时候会出现和filesort类似,也会出现数据量过大而产生临时表的问题。

结论

核心重点就是,尽量利用一两个复杂的多字段联合索引,抗下你80%以上的 查询,然后用一两个辅助索引抗下剩余20%的非典型查询,保证你99%以上的查询都能充分利用索引,就能保证你的查询速度和性能!

其他

关于7天是否登录的表设计

7天是否登录过是一个比较常见的小需求了,最简单的方式其实并不是范围查询,而是使用增加一个是否7天登录的flag值并且通过定时任务定时刷新这个字段的值即可。如果要让这种查询用上索引,可以设计一个联合索引为:(province, city, sex, hobby, character,does_login_in_latest_7_days, age),然后搜索的时候,一定会在where条件里带上一个does_login_in_latest_7_days=1,最后再跟上age范围查询,这样就可以让你的where条件里的字段都用索引来筛选。

设计辅助索引的案例

使用辅助索引,比如加入一个辅助的索引来加快排序和筛选操作。

写在最后

索引的最后部分其实更多的是和执行计划进行结合,对于MYSQL来说优化的最好方式就是学习好MYSQL的explain计划即可,这是一个十分强大好用的工具。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
12天前
|
缓存 关系型数据库 MySQL
MySQL索引策略与查询性能调优实战
在实际应用中,需要根据具体的业务需求和查询模式,综合运用索引策略和查询性能调优方法,不断地测试和优化,以提高MySQL数据库的查询性能。
|
2月前
|
存储 关系型数据库 MySQL
阿里面试:为什么要索引?什么是MySQL索引?底层结构是什么?
尼恩是一位资深架构师,他在自己的读者交流群中分享了关于MySQL索引的重要知识点。索引是帮助MySQL高效获取数据的数据结构,主要作用包括显著提升查询速度、降低磁盘I/O次数、优化排序与分组操作以及提升复杂查询的性能。MySQL支持多种索引类型,如主键索引、唯一索引、普通索引、全文索引和空间数据索引。索引的底层数据结构主要是B+树,它能够有效支持范围查询和顺序遍历,同时保持高效的插入、删除和查找性能。尼恩还强调了索引的优缺点,并提供了多个面试题及其解答,帮助读者在面试中脱颖而出。相关资料可在公众号【技术自由圈】获取。
|
2月前
|
存储 NoSQL 关系型数据库
为什么MySQL不使用红黑树做索引
本文详细探讨了MySQL索引机制,解释了为何添加索引能提升查询效率。索引如同数据库的“目录”,在数据量庞大时提高查询速度。文中介绍了常见索引数据结构:哈希表、有序数组和搜索树(包括二叉树、平衡二叉树、红黑树、B-树和B+树)。重点分析了B+树在MyISAM和InnoDB引擎中的应用,并讨论了聚簇索引、非聚簇索引、联合索引及最左前缀原则。最后,还介绍了LSM-Tree在高频写入场景下的优势。通过对比多种数据结构,帮助理解不同场景下的索引选择。
88 6
|
2月前
|
SQL 关系型数据库 MySQL
案例剖析:MySQL唯一索引并发插入导致死锁!
案例剖析:MySQL唯一索引并发插入导致死锁!
117 0
案例剖析:MySQL唯一索引并发插入导致死锁!
|
2月前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
64 3
Mysql(4)—数据库索引
|
25天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
136 1
|
2月前
|
存储 关系型数据库 MySQL
如何在MySQL中进行索引的创建和管理?
【10月更文挑战第16天】如何在MySQL中进行索引的创建和管理?
70 1
|
26天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
56 0
|
2月前
|
监控 关系型数据库 MySQL
MySQL数据表索引命名规范
MySQL数据表索引命名规范
76 1
|
2月前
|
存储 SQL 关系型数据库
mysql中主键索引和联合索引的原理与区别
本文详细介绍了MySQL中的主键索引和联合索引原理及其区别。主键索引按主键值排序,叶节点仅存储数据区,而索引页则存储索引和指向数据域的指针。联合索引由多个字段组成,遵循最左前缀原则,可提高查询效率。文章还探讨了索引扫描原理、索引失效情况及设计原则,并对比了InnoDB与MyISAM存储引擎中聚簇索引和非聚簇索引的特点。对于优化MySQL性能具有参考价值。