如何在sql存储过程中打log_SQL语句优化
如何定位并优化慢查询 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的查询优化
- 大表/大数据量的更新和删除
对于大表的数据修改最好要分批处理,比如我们要在一个 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语句优化相关推荐
- 如何在sql存储过程中打log_教你如何记录Entity Framework框架自动生成的SQL语句
有两种方法可以记录执行的SQl语句: · 使用DbContext.Database.Log属性 · 实现IDbCommandInterceptor接口 1使用DbContext.Database.Lo ...
- 如何在SQL Server中实现错误处理
错误处理概述 (Error handling overview) Error handling in SQL Server gives us control over the Transact-SQL ...
- 如果不使用 SQL Mail,如何在 SQL Server 中发送电子邮件
如果不使用 SQL Mail,如何在 SQL Server 中发送电子邮件 察看本文应用于的产品 文章编号 : 312839 最后修改 : 2006年12月21日 修订 : 10.1 本页 概要 SQ ...
- @sql 单元测试_如何在SQL单元测试中使用假表?
@sql 单元测试 In this article on SQL unit testing, we will talk about how to isolate SQL unit tests from ...
- pl/sql 测试函数_如何在SQL单元测试中使用伪函数?
pl/sql 测试函数 In this article series, we are exploring SQL unit testing, in general, and also we are r ...
- sql server 数组_如何在SQL Server中实现类似数组的功能
sql server 数组 介绍 (Introduction) I was training some Oracle DBAs in T-SQL and they asked me how to cr ...
- 如何在SQL Server中比较表
介绍 (Introduction) If you've been developing in SQL Server for any length of time, you've no doubt hi ...
- 在SQL存储过程中给条件变量加上单引号
在SQL存储过程中给条件变量加上单引号,不加语句就会出问题,以下就是在存储过程中将条件where设置成了动态变化的,给where赋完值再和前面的语句拼接,再execute(SQL) set @wher ...
- oracle存储过程ddl,Oracle 存储过程中的DDL语句
Oracle的存储过程,是我们使用数据库应用开发的重要工具手段.在存储过程中,我们大部分应用场景都是使用DML语句进行数据增删改操作.本篇中,我们一起探讨一下数据定义语句DDL在存储过程中使用的细节和 ...
最新文章
- mysql ssd 性能测试 写入_MySQL服务器的SSD性能问题分析和测试详解
- RxJava 教程第一部分:为何使用RxJava
- python质数判断if isprime_使用Python判断质数(素数)的简单
- Jenkins+SonarQube6.5.5+SonarScanner2.5代码质量管理平台
- Spring核心——Bean的生命周期
- 自定义EventSource(一)EventCounter
- 机器学习的概念性的总结
- Android自定义View之上拉、下拉列表 头部元素跟随 缩放、平移效果的实现
- 使用MybatisPlus在实体中添加数据库表中不存在的字段
- sql server 左右连接 内外连接
- Spring Security OAuth2实现单点登录
- 好烦,一封报警邮件,大量服务节点 redis 响应超时,又得要捉“虫”!
- python findall_Python 正则表达式:findall
- 计算机主板电源管理线路图,笔记本电源维修方法详解【图文教程】
- 维修 工具 资料 点位图
- excel如何把多张表合并成一个表_excel如何快速把多个工作表合并到一个excel表
- ThinkPHP微信小说小程序源码-自带采集带安装教程
- 第P9周:YOLOv5-Backbone模块实现
- 2019牛客国庆集训派对day2 K 2018(容斥)
- OpenCV学习笔记03:缩放裁剪图像与调整图像色调