Mysql专栏 - mysql索引(三)

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
简介: 上一节我们详细解释了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计划即可,这是一个十分强大好用的工具。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
6月前
|
存储 SQL 关系型数据库
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
|
6月前
|
存储 关系型数据库 MySQL
MySQL数据库索引的数据结构?
MySQL中默认使用B+tree索引,它是一种多路平衡搜索树,具有树高较低、检索速度快的特点。所有数据存储在叶子节点,非叶子节点仅作索引,且叶子节点形成双向链表,便于区间查询。
205 4
|
8月前
|
存储 关系型数据库 MySQL
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
|
10月前
|
关系型数据库 MySQL 数据库
Mysql的索引
MYSQL索引主要有 : 单列索引 , 组合索引和空间索引 , 用的比较多的就是单列索引和组合索引 , 空间索引我这边没有用到过 单列索引 : 在MYSQL数据库表的某一列上面创建的索引叫单列索引 , 单列索引又分为 ● 普通索引:MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一点。 ● 唯一索引:索引列中的值必须是唯一的,但是允许为空值 ● 主键索引:是一种特殊的唯一索引,不允许有空值 ● 全文索引: 只有在MyISAM引擎、InnoDB(5.6以后)上才能使⽤用,而且只能在CHAR,VARCHAR,TEXT类型字段上使⽤用全⽂文索引。
|
6月前
|
存储 SQL 关系型数据库
MySQL 核心知识与索引优化全解析
本文系统梳理了 MySQL 的核心知识与索引优化策略。在基础概念部分,阐述了 char 与 varchar 在存储方式和性能上的差异,以及事务的 ACID 特性、并发事务问题及对应的隔离级别(MySQL 默认 REPEATABLE READ)。 索引基础部分,详解了 InnoDB 默认的 B+tree 索引结构(多路平衡树、叶子节点存数据、双向链表支持区间查询),区分了聚簇索引(数据与索引共存,唯一)和二级索引(数据与索引分离,多个),解释了回表查询的概念及优化方法,并分析了 B+tree 作为索引结构的优势(树高低、效率稳、支持区间查询)。 索引优化部分,列出了索引创建的六大原则
157 2
|
SQL 关系型数据库 MySQL
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
2648 10
|
7月前
|
存储 关系型数据库 MySQL
MySQL覆盖索引解释
总之,覆盖索引就像是图书馆中那些使得搜索变得极为迅速和简单的工具,一旦正确使用,就会让你的数据库查询飞快而轻便。让数据检索就像是读者在图书目录中以最快速度找到所需信息一样简便。这样的效率和速度,让覆盖索引成为数据库优化师傅们手中的尚方宝剑,既能够提升性能,又能够保持系统的整洁高效。
185 9
|
8月前
|
机器学习/深度学习 关系型数据库 MySQL
对比MySQL全文索引与常规索引的互异性
现在,你或许明白了这两种索引的差异,但任何技术决策都不应仅仅基于理论之上。你可以创建你的数据库实验环境,尝试不同类型的索引,看看它们如何影响性能,感受它们真实的力量。只有这样,你才能熟悉它们,掌握什么时候使用全文索引,什么时候使用常规索引,以适应复杂多变的业务需求。
213 12
|
12月前
|
存储 关系型数据库 MySQL
MySQL索引学习笔记
本文深入探讨了MySQL数据库中慢查询分析的关键概念和技术手段。
762 81
|
9月前
|
SQL 存储 关系型数据库
MySQL选错索引了怎么办?
本文探讨了MySQL中因索引选择不当导致查询性能下降的问题。通过创建包含10万行数据的表并插入数据,分析了一条简单SQL语句在不同场景下的执行情况。实验表明,当数据频繁更新时,MySQL可能因统计信息不准确而选错索引,导致全表扫描。文章深入解析了优化器判断扫描行数的机制,指出基数统计误差是主要原因,并提供了通过`analyze table`重新统计索引信息的解决方法。
252 3

推荐镜像

更多