Mysql专栏 - mysql索引(三)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用版 2核4GB 50GB
简介: 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
相关文章
|
3天前
|
SQL 存储 关系型数据库
mysql加索引真的会锁表吗?揭秘背后的技术细节与规避策略
【8月更文挑战第16天】在数据库管理中,添加索引能大幅提升查询效率。MySQL执行此操作时的锁定行为常引起关注。文章详细解析MySQL中索引添加时的锁定机制及其原理。不同存储引擎及SQL语句影响锁定策略:MyISAM需全表锁定;InnoDB提供更灵活选项,如使用`ALTER TABLE... LOCK=NONE`可在加索引时允许读写访问,尽管可能延长索引构建时间。自MySQL 5.6起,在线DDL技术可进一步减少锁定时间,通过`ALGORITHM=INPLACE`和`LOCK=NONE`实现近乎无锁的表结构变更。合理配置这些选项有助于最小化对业务的影响并保持数据库高效运行。
11 4
|
3天前
|
SQL JavaScript 关系型数据库
Mysql索引不当引发死锁问题
本文通过真实案例解析了MySQL在高并发环境下出现死锁的问题。数据库表`t_award`包含多个索引,但在执行特定SQL语句时遭遇索引失效,导致更新操作变慢并引发死锁。分析发现,联合索引`(pool_id, identifier, status, is_redeemed)`因`identifier`允许为空值而导致索引部分失效。此外,`pool_id`上的普通索引产生的间隙锁在高并发下加剧了死锁风险。为解决此问题,文中提出了调整索引顺序至`(pool_id, status, is_redeemed, identifier)`等方案来优化索引使用,进而减轻死锁现象。
|
5天前
|
缓存 NoSQL Redis
一天五道Java面试题----第九天(简述MySQL中索引类型对数据库的性能的影响--------->缓存雪崩、缓存穿透、缓存击穿)
这篇文章是关于Java面试中可能会遇到的五个问题,包括MySQL索引类型及其对数据库性能的影响、Redis的RDB和AOF持久化机制、Redis的过期键删除策略、Redis的单线程模型为何高效,以及缓存雪崩、缓存穿透和缓存击穿的概念及其解决方案。
|
19天前
|
存储 SQL 关系型数据库
(六)MySQL索引原理篇:深入数据库底层揭开索引机制的神秘面纱!
《索引原理篇》它现在终于来了!但对于索引原理及底层实现,相信大家多多少少都有了解过,毕竟这也是面试过程中出现次数较为频繁的一个技术点。在本文中就来一窥`MySQL`索引底层的神秘面纱!
|
19天前
|
SQL 存储 关系型数据库
(五)MySQL索引应用篇:建立索引的正确姿势与使用索引的最佳指南!
在本篇中,则重点讲解索引应用相关的方式方法,例如各索引优劣分析、建立索引的原则、使用索引的指南以及索引失效与索引优化等内容。
|
23天前
|
SQL 缓存 关系型数据库
MySQL 查询索引失效及如何进行索引优化
MySQL 查询索引失效及如何进行索引优化
59 1
|
26天前
|
SQL 缓存 关系型数据库
面试题MySQL问题之实现覆盖索引如何解决
面试题MySQL问题之实现覆盖索引如何解决
30 1
|
26天前
|
存储 SQL 索引
面试题MySQL问题之使用SQL语句创建一个索引如何解决
面试题MySQL问题之使用SQL语句创建一个索引如何解决
31 1
|
13天前
|
缓存 关系型数据库 MySQL
MySQL调优秘籍曝光!从索引到事务,全方位解锁高可用秘诀,让你的数据库性能飞起来!
【8月更文挑战第6天】MySQL是顶级关系型数据库之一,其性能直接影响应用的高可用性与用户体验。本文聚焦MySQL的高性能调优,从索引设计到事务管理,逐一解析。介绍如何构建高效索引,如联合索引`CREATE INDEX idx_order_customer ON orders(order_id, customer_id);`,以及索引覆盖查询等技术。
36 0
|
19天前
|
存储 SQL 关系型数据库
(四)MySQL之索引初识篇:索引机制、索引分类、索引使用与管理综述
本篇中就对MySQL的索引机制有了全面认知,从索引的由来,到索引概述、索引管理、索引分类、唯一/全文/联合/空间索引的创建与使用等内容,进行了全面概述。