首页 > 数据库 >【MySql】Sql优化(三)——性能优化

【MySql】Sql优化(三)——性能优化

时间:2023-05-06 18:32:58浏览次数:39  
标签:Sql MySql 使用 查询 索引 sql SQL 优化


一、前言

      当数据库数据达到一定数量的时候,结合数据库连接池Druid的可视化监控界面,对系统中运行的sql语句进行检测,对使用频繁、执行时间长的sql语句进行优化。

二、优化方案原则

  • [原则一:选择需要优化的SQL]

1,选择需要优化的SQL:不是所有的SQL都需要优化,在优化的过程中,首选更需要优化的SQL;
2,SQL运行较慢有两个影响原因,IO和CPU,明确性能瓶颈所在;
3,明确优化目标;

  • [原则二:从Explain和Profile入手]

1,任何SQL的优化,都从Explain语句开始;Explain语句能够得到数据库执行该SQL选择的执行计划;
2,首先明确需要的执行计划,再使用Explain检查;
3,使用profile明确SQL的问题和优化的结果;

  • [原则三:永远用小结果集驱动大的结果集]
  • [原则四:在索引中完成排序]
  • [原则五:使用最小Columns]

1,减少网络传输数据量;
2,特别是需要使用column排序的时候.为什么?MYSQL排序原理,是把所有的column数据全部取出,在排序缓存区排序,再返回结果;如果column数据量大,排序区容量不够的时候,就会使用先column排序,再取数据,再返回的多次请求方式;

  • [原则六:使用最有效的过滤条件]

1,过多的WHERE条件不一定能够提高访问性能;
2,一定要让where条件使用自己预期的执行计划;

  • [原则七:避免复杂的JOIN和子查询]

1,复杂的JOIN和子查询,需要锁定过多的资源,MYSQL在大量并发情况下处理锁定性能下降较快;
2, 不要过多依赖SQL的功能,把复杂的SQL拆分为简单的SQL;
3,MySQL子查询性能较低,应尽量避免使用;

三、优化思路

3.1 各个系统的Druid监控界面

系统

开发

测试

权限

http://192.168.22.201:8084/authorityManagement-service/druid/datasource.html

http://192.168.22.194:8084/authorityManagement-service/druid/datasource.html

单表

http://192.168.22.202:8083/singleTableMaintain-service/druid/datasource.html

http://192.168.22.195:8083/singleTableMaintain-service/druid/datasource.html

基础

http://192.168.22.202:8084/basicInfo-service/druid/sql.html

http://192.168.22.195:8084/basicInfo-service/druid/sql.html

权限

http://192.168.22.202:8082/teachingManagement-service/druid/datasource.html

http://192.168.22.195:8082/teachingManagement-service/druid/datasource.html

考评

http://192.168.22.201:8082/examinationEvaluation-service/druid/datasource.html

http://192.168.22.194:8082/examinationEvaluation-service/druid/datasource.html

成绩

http://192.168.22.201:8083/achievement-service/druid/sql.html

http://192.168.22.194:8083/achievement-service/druid/sql.html

      举例说明:
      以基础为例,打开测试网址




【MySql】Sql优化(三)——性能优化_性能优化


      按照sql执行次数排序,选择执行时间(单位是微妙,1秒(s)=1000毫秒(ms)),挑选执行时间过长的sql进行优化。
优化方向从两个方向优化:1.SQL语句 2.索引优化



【MySql】Sql优化(三)——性能优化_mysql_02


3.2 SQL语句优化

3.2.1 Where子句优化

  • 删除不必要的括号
((a AND b) AND c OR (((a AND b) AND (c AND d))))
-> (a AND b AND c) OR (a AND b AND c AND d)
  • 持续折叠:
(a<b AND b=c) AND a=5
-> b>5 AND b=c AND a=5
  • 恒定的条件去除(因为不断的折叠)
(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)
-> B=5 OR B=6

3.2.2 Join优化

       A JOIN B:通过A表的结果集作为循环基础,一条一条的通过结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果;

      JOIN的优化原则:

1,尽可能减少Join 语句中的Nested Loop 的循环总次数,用小结果集驱动大结果集; 注意不是:小表连接大的快,而是结果集
2,优先优化Nested Loop 的内层循环; 做索引
3,保证Join 语句中被驱动表上Join 条件字段已经被索引;
4,扩大join buffer的大小;

      举例:



【MySql】Sql优化(三)——性能优化_sql_03


3.3 explain查看执行计划

      Explain命令可以让我们查看MYSQL执行一条SQL所选择的执行计划;

3.3.1 使用方式

explain SQL;

      举例:



【MySql】Sql优化(三)——性能优化_sql_04


3.3.2 返回字段说明

1.ID:执行查询的序列号;

2.select_type:使用的查询类型

1,DEPENDENT SUBQUERY:子查询中内层的第一个SELECT,依赖于外部查询的结果集;
2,DEPENDENT UNION:子查询中的UNION,且为UNION 中从第二个SELECT 开始的后面所有SELECT,同样依赖于外部查询的结果集;
3,PRIMARY:子查询中的最外层查询,注意并不是主键查询;
4,SIMPLE:除子查询或者UNION 之外的其他查询;
5,SUBQUERY:子查询内层查询的第一个SELECT,结果不依赖于外部查询结果集;
6,UNCACHEABLE SUBQUERY:结果集无法缓存的子查询;
7,UNION:UNION 语句中第二个SELECT 开始的后面所有SELECT,第一个SELECT 为PRIMARY
8,UNION RESULT:UNION 中的合并结果;

3.table:这次查询访问的数据表;

4.type:对表所使用的访问方式:

1,all:全表扫描
2,const:读常量,且最多只会有一条记录匹配,由于是常量,所以实际上只需要读一次;
3,eq_ref:最多只会有一条匹配结果,一般是通过主键或者唯一键索引来访问;
4,fulltext:全文检索,针对full text索引列;
5,index:全索引扫描;
6,index_merge:查询中同时使用两个(或更多)索引,然后对索引结果进行merge 之后再读取表数据;
7,index_subquery:子查询中的返回结果字段组合是一个索引(或索引组合),但不是一个主键或者唯一索引;
8,rang:索引范围扫描;
9,ref:Join 语句中被驱动表索引引用查询;
10,ref_or_null:与ref 的唯一区别就是在使用索引引用查询之外再增加一个空值的查询;
11,system:系统表,表中只有一行数据;
12,unique_subquery:子查询中的返回结果字段组合是主键或者唯一约束;

5.possible_keys:可选的索引;如果没有使用索引,为null;

6.key:最终选择的索引;

7.key_len:被选择的索引长度;

8.ref:过滤的方式,比如const(常量),column(join),func(某个函数);

9.rows:查询优化器通过收集到的统计信息估算出的查询条数;

10.Extra:查询中每一步实现的额外细节信息

1,Distinct:查找distinct 值,所以当mysql 找到了第一条匹配的结果后,将停止该值的查询而转为后面其他值的查询;
2,Full scan on NULL key:子查询中的一种优化方式,主要在遇到无法通过索引访问null值的使用使用;
3,Impossible WHERE noticed after reading const tables:MySQL Query Optimizer 通过收集到的统计信息判断出不可能存在结果;
4,No tables:Query 语句中使用FROM DUAL 或者不包含任何FROM 子句;
5,Not exists:在某些左连接中MySQL Query Optimizer 所通过改变原有Query 的组成而使用的优化方法,可以部分减少数据访问次数;
6,Select tables optimized away:当我们使用某些聚合函数来访问存在索引的某个字段的时候,MySQL Query Optimizer 会通过索引而直接一次定位到所需的数据行完成整个查询。当然,前提是在Query 中不能有GROUP BY 操作。如使用MIN()或者MAX()的时候;
7,Using filesort:当我们的Query 中包含ORDER BY 操作,而且无法利用索引完成排序操作的时候,MySQL Query Optimizer 不得不选择相应的排序算法来实现。
8,Using index:所需要的数据只需要在Index 即可全部获得而不需要再到表中取数据;
9,Using index for group-by:数据访问和Using index 一样,所需数据只需要读取索引即可,而当Query 中使用了GROUP BY 或者DISTINCT 子句的时候,如果分组字段也在索引中,Extra 中的信息就会是Using index for group-by;
10,Using temporary:当MySQL 在某些操作中必须使用临时表的时候,在Extra 信息中就会出现Using temporary 。主要常见于GROUP BY 和ORDER BY 等操作中。
11,Using where:如果我们不是读取表的所有数据,或者不是仅仅通过索引就可以获取所有需要的数据,则会出现Using where 信息;
12,Using where with pushed condition:这是一个仅仅在NDBCluster 存储引擎中才会出现的信息,而且还需要通过打开Condition Pushdown 优化功能才可能会被使用。控制参数为engine_condition_pushdown 。

3.4 索引优化

      通过使用Explain SQL查看sql的执行计划,可以看出sql中是否是按照程序员的预想计划执行的,如果不是,需要我们再次对sql进行优化,添加索引是最快,最有效果的优化。

      默认情况下,一旦创建了一个表,这个表设置了主键,那么MYSQL会自动的为这个主键创建一个unique的索引。

      根据sql语句的执行计划,具体分析添加单列索引还是符合索引。

3.4.1 举例说明

      表结构如下:三列,不带索引,存储100w数据。



【MySql】Sql优化(三)——性能优化_mysql_05




【MySql】Sql优化(三)——性能优化_sql_06


      执行sql查询:SELECT * FROM t_school WHERE address =’大米时代9’
      用时0.864s



【MySql】Sql优化(三)——性能优化_性能优化_07


      通过explain命令查询执行计划:
      分析结果:采用全表扫描,没有使用索引,查询总行数为997002行



【MySql】Sql优化(三)——性能优化_数据库_08


      对address添加索引后:



【MySql】Sql优化(三)——性能优化_性能优化_09


      查询:用时0.010s,速度提升了86倍。(有一定因素是,缓存影响的)



【MySql】Sql优化(三)——性能优化_mysql_10


      使用explain分析执行计划:使用了index_address索引,查询了1999行,查询行数明显变少



【MySql】Sql优化(三)——性能优化_sql_11


3.4.2 索引的使用限制

1.BLOB 和TEXT 类型的列只能创建前缀索引

2.MySQL 目前不支持函数索引(在MYSQL中,索引只能是一个列的原始值,不能把列通过计算的值作为索引);

实例:请查询1981年入职的员工:

SELECT * FROM emp WHERE year(hire_date)='1981';

问题:查询的列是在过滤之前经过了函数运算;所以,就算hire_date作为索引,year(hire_date)也不会使用索引;
解决方案:
1,SELECT * FROM emp WHERE hire_date BETWEEN ‘1981-01-01’ AND ‘1981-12-31’;
2,在创建一列,这列的值是year(hire_date),然后把这列的值作为索引;

3.使用不等于(!= 或者<>)的时候MySQL 无法使用索引

4.过滤字段使用了函数运算后(如abs(column)),MySQL 无法使用索引

5.Join 语句中Join 条件字段类型不一致的时候MySQL 无法使用索引

6.使用LIKE 操作的时候如果条件以通配符开始( ‘%abc…’)MySQL 无法使用索引

1,字符串是可以用来作为索引的;
2,字符串创建的索引按照字母顺序排序;
3,如果使用LIKE,实例:

SELECT * FROM userinfo WHERE realName LIKE '王%';

这种情况是可以使用索引的;但是LIKE '_王雷' 或者LIKE '%王雷'都是不能使用索引的;

7.使用非等值查询的时候MySQL 无法使用Hash 索引


五、小结

      汇总就是对sql语句、数据库机构、硬件方面的优化,通过各种方法提高sql操作的速度,这个就是我们要整理的。


标签:Sql,MySql,使用,查询,索引,sql,SQL,优化
From: https://blog.51cto.com/u_16100820/6251025

相关文章

  • Semi-Join Subquery优化策略
    Semi-JoinSubquery优化策略Semi-JoinSubquery(半连接子查询):对应IN或EXISTS子查询,仅需要检查"外表记录"在"子查询结果集"中是否存在匹配记录,不需要计算"子查询结果集"中记录匹配次数,也不需要返回"子查询结果集"中匹配记录内容在MariaDB(MySQL)中,常用优化Semi-Join(半连接)的策......
  • SQL语法之:连表查询:union all
    1、准备两条sql查询出来的字段数必须一致表1字段:数据:表2字段:数据:2、使用1、两张表结构完全一样,查询字段顺序也一样selectID,NAME,SEX,AGE,NAME2fromT_01UNIONALLselectID,NAME,SEX,AGE,NAME2fromT_02;结果:2、查询字段顺序不一样,但是对应的......
  • MySQL如何获取binlog的开始时间和结束时间
    MySQL数据库恢复到指定时间点时,我们必须通过MySQL全备+MySQL增量备份(可选)+MySQL的二进制日志(binlog)进行重放来恢复到指定时间点,实际的生产环境中,可能一段时间内生成了多个二进制日志文件(binlog),MySQL本身不会存储二进制日志文件(binlog)的开始时间和结束时间,如果要还原到某个时间点......
  • Flink Cdc MySQL 整库同步到 StarRocks
    这段时间开始调研使用StarRocks做准实时数据仓库:flinkcdc实时同步数据到StarRocks,然后在StarRocks中做分层计算,直接把StarRocks中的ADS层提供给BI查询。架构如下:由于用到的表比较多,不能用FlinkSQL给每个表都做个CDC的任务(任务太多不好维护、对数据库又可能有......
  • mysql查询某条数据出现两次以上
    查询order_id重复出现两次以上selectorder_idfromt_testwhere1=1GROUPBYorder_idHAVINGcount(order_id)>1;查询order_id,phone重复出现两次以上select*fromt_testwhere1=1GROUPBYorder_id,phoneHAVINGcount(order_id+phone)>1; ......
  • 前端性能优化
    1.如果应用层响应超时怎么处理解决?如果响应超时,可以采取以下措施来处理解决:增加超时时间:可以增加请求的超时时间来尝试避免响应超时。可以在发起请求时,设置超时时间,如果在指定时间内未收到响应,则认为响应超时。减少请求负载:如果请求负载过大,服务器响应可能会受到影响,从......
  • HiveSQL调优-最常用的调优方式
    系统和其它层面:让经常where的字段进行分区,合理的多分桶、数据使用压缩、建宽表的时候用列式的orc存储、开启严格模式:会产生笛卡尔积、orderby排序后未加limit、查询分区表时未指定列的HiveSQL语句直接执行出错开启列裁剪和分区裁剪:即只查询要读取的列和分区,避免全表扫描或全列......
  • sql注入原理和mybatis解决sql注入
    转载:https://www.bilibili.com/video/BV1ZR4y1Y745/?spm_id_from=333.880.my_history.page.click&vd_source=46d50b5d646b50dcb2a208d3946b1598https://juejin.cn/post/7064740474057146398#heading-11......
  • jvm调优总结(从基本概念 到 深度优化)
    关键字:jvm调优总结(从基本概念到深度优化)JVM参数详解Java虚拟机中,数据类型可以分为两类:基本类型和引用类型。基本类型的变量保存原始值,即:他代表的值就是数值本身;而引用类型的变量保存引用值。“引用值”代表了某个对象的引用,而不是对象本身,对象本身存放......
  • oracle大数据量优化
    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在where及orderby涉及的列上建立索引。2.应尽量避免在where子句中对字段进行null值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:selectidfromtwherenumisnull可以在num上设置默认值0,......