如何定位并优化慢查询 SQL?大致思路如下:

  • 根据慢查询日志定位慢查询 SQL;
  • 使用 explain 等工具分析 SQL;
  • 修改 SQL 或者尽量让 SQL 走索引。

获取有性能问题的 SQL 的两种方法:

  • 通过慢查日志获取存在性能问题的 SQL;
  • 实时获取存在性能问题的 SQL;

慢SQL定位

1.根据慢查询日志定位慢查询 SQL

MySQL 慢查询日志是一种性能开销比较低的解决方案,主要性能开销在磁盘 IO 和存储日志所需要的磁盘空间。对于磁盘 IO 来说,由于写日志是顺序存储,开销基本上忽略不计,所以主要需要关注的还是磁盘空间。

首选,需要确认是否已经开启了慢查询日志:

show 

MySQL 提供了以下参数用于控制慢查询日志:

slow_query_log

开启慢查询日志有两种方式:

  • 通过配置 /etc/my.cnf 文件开启,是永久性的
  • 通过设置全局变量开启,MySQL 重启后会失效。

设置全局变量的 SQL 如下:

set 

和二进制日志不同,慢查询日志会记录所有符合条件的 SQL,包括查询语句、数据修改语句、已经回滚的 SQL。

慢查询日志中记录的内容:

# Query_time: 0.000220             //执行时间,可以精确到毫秒,220毫秒

通常情况下,在一个繁忙的系统中,短时间内就可以产生几个 G 的慢查询日志,人工检查几乎是不可能的,为了快速分析慢查询日志,必须借助相关的工具。

常用的慢查询日志工具:

  • mysqldumpslow:一个常用的,MySQL 官方提供的慢查询日志分析工具,随着 MySQL 服务器的安装而被安装。可以汇总除查询条件外其他完全相同的 SQL,并将分析结果按照参数中所指定的顺序输出。
  • pt-query-digest:用于分析 MySQL 慢查询的一个工具。

2.实时获取性能问题SQL

为了更加及时的发现当前的性能问题,我们还可以通过实时的方法来获取有性能问题的 SQL。最方便的一种方法就是利用 MySQL information_schema 数据库下的 PROCESSLIST 表来实现实时的发现性能问题 SQL。例如下面这条 SQL 表示查询出当前服务器中执行时间超过 1 秒的 SQL:

SELECT 

然后我们可以通过脚本周期性的来执行这条 SQL,实时的发现哪些 SQL 执行的是比较慢的。

explain分析SQL

explain 可以帮助我们分析 select 语句,让我们知道查询效率低下的原因。这个关键字一般放在 select 语句的前面,用于描述 MySQL 如何执行查询操作以及 MySQL 成功返回结果集需要执行的行数,执行会输出一些 explain 的字段。例如:

EXPLAIN 

需要注意的是,执行 explain 并不会真正的执行 SQL,而是对 SQL 做了一些分析,速度非常快。

explain 关键字段:

id

type 字段:

type 字段的返回值,性能从最优到最差:

system -> const -> eq_ref -> ref -> fulltext -> ref_or_null -> index_merge -> unique_subquery -> index_subquery -> range -> index -> all

index 和 all 表示本次查询走的是全表扫描。如果 type 值是这两个,表明 SQL 是需要优化的。

Extra字段

Extra 中出现了以下两种意味着 MySQL 根本不能使用索引,效率会受到重大影响,应尽可能对此进行优化:

Extra 项 说明
Using filesort 表示 MySQL 会对结果使用一个外部索引排序,而不是从表里按索引次序读到相关内容。可能在内存或者磁盘上进行排序。MySQL 中无法利用索引完成的排序操作称为 “文件排序”。
Using temporary 表示 MySQL 在对查询结果排序时使用的临时表,常见于排序 order by 和分组查询 group by。

特定SQL的查询优化

  1. 大表/大数据量的更新和删除

对于大表的数据修改最好要分批处理,比如我们要在一个 1000 万行记录的表中删除/更新 100 万行记录,那么我们最好分多个批次进行删除/更新,一次只删除/更新 5000 行记录,避免长时间的阻塞,并且为了减少对主从复制带来的压力,每次删除/修改数据后需要暂停几秒。这里提供一个可以完成这样工作的 MySQL 存储过程的实例:

DELIMITER 

2. 如何修改大表的表结构

对于 InnoDB 存储引擎来说,对表中的列的字段类型进行修改或者改变字段的宽度时还是会锁表,同时也无法解决主从数据库延迟的问题。

解决方案:

在主服务器上建立新表,新表的结构就是修改之后的结构,再把老表的数据导入到新表中,并且在老表上建立一系列的触发器,把老表数据的修改同步更新到新表中,当老表和新表的数据同步后,再对老表加一个排它锁,然后重新命名新表为老表的名字,最好删除重命名的老表,这样就完成了大表表结构修改的工作。这样处理的好处是可以尽量减少主从延迟,以及在重命名之前不需要加任何的锁,只需要在重命名的时候加一个短暂的锁,这对应用通常是无影响的,缺点就是操作比较复杂。好在有工具可以帮我们实行这个过程,这个工具同样是 percona 公司 MySQL 工具集中的一个,叫做 pt-online-schema-change:

pt-online-schema-change 

这个命令就是把 db_name 数据库下的 table_name 表中 c 列的宽度改为 VARCHAR(150)。

3. 如何优化not in和<>查询

MySQL 查询优化器可以自动的把一些子查询优化为关联查询,但是对于存在not in和<>这样的子查询语句来说,就无法进行自动优化了,这就造成了会循环多次来查找子表来确认是否满足过滤条件,如果子查询恰好是一个很大的表的话,这样做的效率会非常低,所以我们在进行 SQL 开发时,最好把这类查询自行改写成关联查询。

改写前:

SELECT 

优化改写后:

SELECT 

4. 优化COUNT()查询

COUNT函数的作用:

  • 统计某个列的数量
  • 统计行数

统计列值的时候要求列值是非空的。列值为空的列将不会被统计到。

当MySQL确认括号内的表达式值不可能为空时,实际上是在统计行数。

5. 优化关联查询

优点建议:

  • 确保关联查询的列上有索引。通常只需要在关联顺序中的第二个表的相应列创建索引。
  • 确保任何分组和排序的表达式中只涉及一个表中的列。

6. 优化子查询

优化建议 - 尽可能使用关联查询代替。

优化group和distinct

优化建议:

  • 如果需要对关联查询表中的某个列做分组,通常采用主表的标识列分组效率会更高

优化Limit分页

偏移量大的时候,查询效率会很糟糕。

优化建议: - 尽量使用索引覆盖扫描,再做关联查询返回所需的列。

例如:

原SQL:

select 

改写之后:

select 

优化UNION查询

优化建议:

  • 除非确定要消除重复的行,否则就一定要使用UNION ALL。如果没有ALL关键字,会给临时表加上distinct选项,导致对整个临时表数据做唯一性检查,代价非常高。

如何在sql存储过程中打log_SQL语句优化相关推荐

  1. 如何在sql存储过程中打log_教你如何记录Entity Framework框架自动生成的SQL语句

    有两种方法可以记录执行的SQl语句: · 使用DbContext.Database.Log属性 · 实现IDbCommandInterceptor接口 1使用DbContext.Database.Lo ...

  2. 如何在SQL Server中实现错误处理

    错误处理概述 (Error handling overview) Error handling in SQL Server gives us control over the Transact-SQL ...

  3. 如果不使用 SQL Mail,如何在 SQL Server 中发送电子邮件

    如果不使用 SQL Mail,如何在 SQL Server 中发送电子邮件 察看本文应用于的产品 文章编号 : 312839 最后修改 : 2006年12月21日 修订 : 10.1 本页 概要 SQ ...

  4. @sql 单元测试_如何在SQL单元测试中使用假表?

    @sql 单元测试 In this article on SQL unit testing, we will talk about how to isolate SQL unit tests from ...

  5. pl/sql 测试函数_如何在SQL单元测试中使用伪函数?

    pl/sql 测试函数 In this article series, we are exploring SQL unit testing, in general, and also we are r ...

  6. sql server 数组_如何在SQL Server中实现类似数组的功能

    sql server 数组 介绍 (Introduction) I was training some Oracle DBAs in T-SQL and they asked me how to cr ...

  7. 如何在SQL Server中比较表

    介绍 (Introduction) If you've been developing in SQL Server for any length of time, you've no doubt hi ...

  8. 在SQL存储过程中给条件变量加上单引号

    在SQL存储过程中给条件变量加上单引号,不加语句就会出问题,以下就是在存储过程中将条件where设置成了动态变化的,给where赋完值再和前面的语句拼接,再execute(SQL) set @wher ...

  9. oracle存储过程ddl,Oracle 存储过程中的DDL语句

    Oracle的存储过程,是我们使用数据库应用开发的重要工具手段.在存储过程中,我们大部分应用场景都是使用DML语句进行数据增删改操作.本篇中,我们一起探讨一下数据定义语句DDL在存储过程中使用的细节和 ...

最新文章

  1. mysql ssd 性能测试 写入_MySQL服务器的SSD性能问题分析和测试详解
  2. RxJava 教程第一部分:为何使用RxJava
  3. python质数判断if isprime_使用Python判断质数(素数)的简单
  4. Jenkins+SonarQube6.5.5+SonarScanner2.5代码质量管理平台
  5. Spring核心——Bean的生命周期
  6. 自定义EventSource(一)EventCounter
  7. 机器学习的概念性的总结
  8. Android自定义View之上拉、下拉列表 头部元素跟随 缩放、平移效果的实现
  9. 使用MybatisPlus在实体中添加数据库表中不存在的字段
  10. sql server 左右连接 内外连接
  11. Spring Security OAuth2实现单点登录
  12. 好烦,一封报警邮件,大量服务节点 redis 响应超时,又得要捉“虫”!
  13. python findall_Python 正则表达式:findall
  14. 计算机主板电源管理线路图,笔记本电源维修方法详解【图文教程】
  15. 维修 工具 资料 点位图
  16. excel如何把多张表合并成一个表_excel如何快速把多个工作表合并到一个excel表
  17. ThinkPHP微信小说小程序源码-自带采集带安装教程
  18. 第P9周:YOLOv5-Backbone模块实现
  19. 2019牛客国庆集训派对day2 K 2018(容斥)
  20. OpenCV学习笔记03:缩放裁剪图像与调整图像色调

热门文章

  1. Python学习之路day03——008用户输入input()方法
  2. 火车图 、jackson图
  3. [转]跨库数据表复制
  4. 通过路由器的IP映射来解决,两个不同IP地址的PC机之间的从LAN口到WAN口的单向通讯问题
  5. 禁止chrome浏览器自动填充表单的解决方案
  6. C++自定义异常处理
  7. 【算法实践】搜狗信息流推荐算法交流.pdf(附下载链接)
  8. 【报告分享】2020中国消费市场发展报告.pdf(附下载链接)
  9. 一张图看懂字节跳动8年创业史,太励志了吧
  10. 推荐算法工程师必备!!!协同过滤推荐算法总结