首页 > 数据库 >MySQL-索引优化实战

MySQL-索引优化实战

时间:2024-04-27 23:12:47浏览次数:24  
标签:实战 sort 使用 查询 回表 索引 MySQL 排序

 

针对联合索引来说,如果第一列就是用范围查询,例如大于小于这些,就会认为查询的行很多,如果不是覆盖索引,那么就不再使用这个二级索引,认为使用二级索引还要频繁的去回表查询等等,消耗更大,所以就会去全表扫描。

但是可以使用force index(索引名称)去强制使用指定的索引,但是一般不建议这么做;要相信MySQL自己的优化结果。

in和or使用时,如果后面括号里面的值不多,并且表里面的数据很多,就会走索引,否则可能不会走索引。

针对like 'xx%';这样的查询一般都会去走索引的;因为5.6版本之后引入了一个索引下推的技术;

索引下推

如果ABC三个列建立了联合索引,查询条件是 A like 'xx%' and B = '' and C = '';在5.6版本之前,会去联合索引中找到符合A列的所有主键值,去主键索引中进行回表,然后将这些数据加载到内存中,然后进行B和C条件的匹配。这样回表次数会比较多,并且返回的数据量也很大,带宽压力也大。

5.6版本之后,引擎进行了优化,在匹配符合A列的条件之后,还会在二级索引中去进一步匹配B和C这两列的查询条件,这样一来会减少最终查询的值的数量,然后就会减少回表的次数,然后也会减少返回给调用方的数据量,减少网络带宽的压力。

使用索引下推的场景一般都是对于非主键的联合索引,这样可以减少回表次数,进而减少数据量

 

为什么范围查找Mysql没有用索引下推优化?

因为对MySQL来说,认为一般情况下范围查询的数据量是很大的,而like模糊查询的数据量是较少的;这样就可以减少查询到的主键的数据量,减少回表次数。当然这个like使用索引下推并不是绝对的,大于小于这种范围查询不使用索引下推也不是绝对的。

 

trace

trace工具可以展示出来经过引擎优化之后的查询语句,但是这个功能默认是关闭的,开启会消耗性能。

set session optimizer_trace="enabled=on",end_markers_in_json=on; ‐‐开启trace select * from 表名 where 条件 > 'a' order by 条件; SELECT * FROM information_schema.OPTIMIZER_TRACE; 注意,两个select要一起执行,这样第二个才能在控制台输出优化后的SQL语句等。 第一阶段是sql格式化; 第二阶段是SQL优化,针对条件是否要挪位等等; 第三阶段就是评估使用各个索引的查询成本,这个只是一个预估值。 第四阶段就是确定最终使用哪个索引来进行查询。 注意每次查询只能使用一个索引。(回表使用的是主键索引)   set session optimizer_trace="enabled=off"; ‐‐关闭trace

 

常见sql深入优化

Order by与Group by优化

针对排序和分组来说,通过explain分析之后,我们主要是看extra这一列。主要有两个值,有using index和using filesort。using index是使用到了索引(这个是最佳情况),using filesort是文件排序。

MySQL不会对order by和group by后面的查询条件进行优化,例如挪位。(联合索引是AB,开发者写的条件是BA,此时就是using filesort) 小总结:
  1. MySQL使用order by支持index和filesort两种排序,index是能使用到已有索引的,效率高;filesort无法使用到索引,效率低。
  2. 满足using index的情况:1.order by后面的查询严格符合联合索引的最左前缀原则;2.where条件和order by的条件完全符合最左前缀原则。
  3. 排序时尽量使用已有的索引列,尽量使用到索引;
  4. 查询能使用覆盖索引就使用覆盖索引。
group by和order by类似,但是group by之前会先进行order by一次;如果不需要排序可以加上order by null; 注意,where高于having,能写在where中的限定条件就不要去having限定了。  

using filesort文件排序原理

分为单路排序和双路排序。

单路排序:就是一次性将符合条件的数据全部加载出来,在系统的sort buffer中进行排序;用trace工具可以看到sort_mode信息里显示< sort_key, additional_fields >或者< sort_key,packed_additional_fields >。

该排序的好吃就是一次性就将数据加载出来,无需进行回表操作,但是对内存大小要求较高。

双路排序:也叫做回表排序,就是根据条件先取出来排序字段和能直接定位到行的主键值,然后在sort buffer中排序,之后要进行回表将别的要查询的值查询出来填充进去。用trace工具可以看到sort_mode信息里显示< sort_key, rowid >。

该排序的好处就是对内存压力小,但是需要进行二次回表,IO压力变大。

  MySQL 通过比较系统变量 max_length_for_sort_data(默认1024字节) 的大小和需要查询的字段总大小来判断使用哪种排序模式。 如果 字段的总长度小于max_length_for_sort_data ,那么使用 单路排序模式; 如果 字段的总长度大于max_length_for_sort_data ,那么使用 双路排序模式。   这个值是可以修改的,通过命令set max_length_for_sort_data = 10,但是并不建议修改,非专业DBA不要去修改这些默认配置。 排序中有这样一个参数:"number_of_tmp_files": 3, ‐‐表示使用临时文件的个数,这个值如果为0代表全部使用的sort_buffer内存排序,否则使用的磁盘文件排序。尽量使用内存排序,这样更高效。 如果排序内存sort_buffer比较小,可以适当改小max_length_for_sort_data 值,让优化器选择使用双路排序算法,可以在sort_buffer 中一次排序更多的行,只是需要再根据主键回到原表取数据。

注意,如果全部使用sort_buffer内存排序一般情况下效率会高于磁盘文件排序,但不能因为这个就随便增大sort_buffer(默认1M),mysql很多参数设置都是做过优化的,不要轻易调整。  

索引设计原则

1. 索引不是越多越好,索引多了,第一是占用空间,第二维护麻烦。

2. 代码先行,待开发功能差不多完成时,将相关表的操作全部整理出来,进行分析,而不是建表时想当然的创建索引。

3. 尽量使用联合索引,因为每次查询只能命中一个索引,所以要尽可能的让查询条件都命中索引,可以适当设计三四个左右的联合索引。

4. 尽量在区分度大的列上建立索引,最好不要在性别字段加索引,因为性别就女和男,这样区分度太小,类似全表扫描。

5. 针对长字段来说,可以截取前20位当作索引,这样可以减少索引所占的空间,也能起到良好的查询效果。当然如果业务要求必须这个字段整体作为索引,那么也不能为了节省空间而去想别的方式,技术是为了业务而服务的。还有一点就是如果使用了前缀,那么对这个字段进行分组或者排序的时候是无法使用索引的,因为针对这个字段的整体来说是无序的。 6. where和order by冲突时,要优先以where为基准,先过滤,经过过滤会少很多的数据,此时再去排序就会快很多的。 7. 基于慢查询进行优化。MySQL的慢查询默认是关闭的,因为开启会影响部分性能;慢查询默认是以十秒为基准的,低于十秒的不记录。  

实战开发原则:

首先是分析针对表的所有查询语句,争取让百分之八十以上的查询都走索引,并且尽量使用到覆盖索引。 当一个联合索引不能覆盖查询场景的时候,可以创建别的联合索引来满足查询业务,一张表可以设计三到四个联合索引。 同时针对场景进行分析,特定的场景抽取特定的字段去创建索引,并且尽量让范围模糊查询的字段放到最后面,这样保证索引的高效使用。 针对一些时间范围的查询,可以新增一个冗余的标识字段,额外启动一个定时器,进行字段值的修改。 SQL语句的查询条件尽量符合联合索引的最左前缀原则。        

 

 

 

 

 

 

 

 

 

 

先过滤,再去排序

标签:实战,sort,使用,查询,回表,索引,MySQL,排序
From: https://www.cnblogs.com/0630sun/p/18162285

相关文章

  • 【mysql】mysql安装使用教程
    参考说明:更改时区部分,摘自:2024年MySQL8.0安装配置教程最简易(保姆级)_mysql安装-CSDN博客一、下载安装包1、进入官网,下载mysql社区版安装包MySQL::下载MySQL安装程序 二、安装1、安装包下载完成后,双击安装包,进入安装指引2、安装指引中,选择自定义安装Custom,并点击......
  • MySQL 中表空间的查看和清理
    /*查看所有数据库容量大小*/SELECTtable_schema,table_name,data_free,ENGINEFROMinformation_schema.tablesWHEREtable_schemaNOTIN('sys','mysql','performance_schema','information_schema','test')ANDdata......
  • MySQL(1)-索引底层为什么用B+树
    最近在看面经,发现有很多跟B+树相关的问题,为此需要单独总结一下让自己形成一个体系。核心内容是为什么MySQL采用B+树作为索引?|小林coding所以可以直接看小林code的讲解,很到位。进入正题前,首先要对B树、B+树、二分查找树、自平衡二叉树、索引这些概念了初步解再分析具体问题......
  • Go语言高并发与微服务实战专题精讲——远程过程调用 RPC——优化RPC调用,缓解频繁请求
    远程过程调用RPC——优化RPC调用,缓解频繁请求导致的GC压力 在Go语言的高并发和微服务架构中,远程过程调用(RPC)是一种常用的通信机制。然而,当频繁发送RPC请求时,不断创建Request和Response结构体可能会带来额外的垃圾收集(GC)压力,进而影响应用的性能和响应时间。为了减......
  • js逆向实战之中国男子篮球职业联赛官方网站返回数据解密
    url:https://www.cbaleague.com/data/#/teamMain?teamId=29124分析过程看流量包,返回数据全是加密的字符串,要做的就是解密回显数据。由于这里的网址都比较特殊,里面都带有id号,所以通过url关键字去搜索不是一个很好的办法。看initiators,里面有很多异步传输。异步传输......
  • 深入理解Python协程:从基础到实战
    title:深入理解Python协程:从基础到实战date:2024/4/2716:48:43updated:2024/4/2716:48:43categories:后端开发tags:协程异步IO并发编程Pythonaiohttpasyncio网络爬虫第1章:协程基础1.1协程概念介绍协程(Coroutines)是一种特殊的软件构造,它允许程序在执......
  • Go语言高并发与微服务实战专题精讲——远程过程调用 RPC——客户端处理RPC请求的原理
    远程过程调用RPC——客户端处理RPC请求的原理及源代码分析 客户端无论是同步调用还是异步调用,每次RPC请求都会生成一个Call对象,并使用seq作为key保存在map中,服务端返回响应值时再根据响应值中的seq从map中取出Call,进行相应处理。 客户端发起RPC调用的过程大致如下所示,我们......
  • MySQL LIMIT 和 ORDER BY 优化
     MySQLLIMIT子句MySQLLIMIT子句是控制SELECT语句返回行数的重要工具。通过指定从结果集中获取的最大行数,它可以让你处理数据子集,尤其是在涉及大表的情况下。该功能可提高查询性能,并通过只获取必要的行来优化资源使用。 MySQLLIMIT子句的语法MySQL中的LIMIT子句......
  • MySQL学习之explain
     from之后的查询得到的表叫做衍生表,是临时表数据,生成临时表之后的数据是无法使用索引的,如果数据量大查询效率就会比较低,这就是查询要尽量少使用子查询这些临时表。  explain详解id:表示查询序号,也可以表示优先级;当值都不一样的时候,值越大表示优先级越高,越先执行;当值都一......
  • 深入mysql索引
    1.索引索引是对数据库表中一列或多列的值进行排序的一种结构。 MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询语句。简单类比一下,数据库......