MySQL-慢sql优化思路

news2024/11/17 9:51:36

目录

1、开启Mysql慢查询

1.1、查看慢查询相关配置

1.2、查询慢查询sql耗时临界点

1.3、开启Mysql慢查询

2、explain查看SQL执行计划

2.1、Select_type

2.2、Type

2.3、Possible_keys

2.4、Key

2.5、Key_len

2.6、Rows

2.7、Extra

3、profile 分析执行耗时

3.1、查询profile开启状态

3.2、开启profiling

3.3、查看最近运行的SQL

3.3.1、show profiles

3.3.2、show profile for query id

4、Optimizer Trace分析详情

4.1、分析流程

4.2、结果分析

5、慢查询经典案例总结

5.1、隐式类型转换

5.2、最左匹配

5.3、limit深分页问题

5.4、in元素过多

5.5、order走文件排序导致的慢查询

5.6、索引字段使用is null 或 is not null可能导致索引失效

5.7、索引字段上使用(!= 或者 < >, not in)可能导致索引失效

5.8、左右连接,关联的字段编码格式不一致

5.9、delete + in子查询不走索引


1、开启Mysql慢查询

1.1、查看慢查询相关配置

show variables like 'slow_query_log%'

  • slow_query_log 表示慢查询开启的状态

  • slow_query_log_file 表示慢查询日志存放的位置

1.2、查询慢查询sql耗时临界点

show variables like 'long_query_time'

  • long_query_time  表示查询超过多少秒才记录到慢查询日志。

1.3、开启Mysql慢查询

  • 方式一:修改配置文件开启慢查询

        在my.ini增加如下配置

# 定义sql耗时多少秒就算是慢查询,记录慢查询日志
long_query_time=2

# 开启慢查询
slow_query_log=on

# 定义慢查询日志文件名
slow_query_log_file=/usr/local/mysql/mysql-slow-query.log
  • 方式二:通过命令开启慢查询
set global slow_query_log=ON    # 开启慢查询日志
set global long_query_time=2    # SQL查询时间大于2秒,则记录慢查询日志

2、explain查看SQL执行计划

explain + SQL,查看SQL的执行计划。重点关注type、rows、extra、key指标。

2.1、Select_type

查询类型:

  • SIMPLE : 表示查询语句不包含子查询或union
  • PRIMARY:表示此查询是最外层的查询
  • UNION:表示此查询是UNION的第二个或后续的查询
  • DEPENDENT UNION:UNION中的第二个或后续的查询语句,使用了外面查询结果
  • UNION RESULT:UNION的结果
  • SUBQUERY:SELECT子查询语句
  • DEPENDENT SUBQUERY:SELECT子查询语句依赖外层查询的结果

2.2、Type

存储引擎查询数据时采用的方式:

性能:NULL > const > eq_ref > ref > range > index > ALL

  • ALL:表示全表扫描,性能最差。
  • index:表示基于索引的全表扫描,先扫描索引再扫描全表数据。
  • range:表示使用索引范围查询。使用>、>=、<、<=、in等等。
  • ref:表示使用非唯一索引进行单值查询。
  • eq_ref:一般情况下出现在多表join查询,表示前面表的每一个记录,都只能匹配后面表的一行结果。
  • const:表示使用主键或唯一索引做等值查询,常量查询。
  • NULL:表示不用访问表,速度最快。

2.3、Possible_keys

        表示查询时可能使用到的索引。

2.4、Key

        查询时真正使用到的索引。

2.5、Key_len

        表示查询使用了索引的字节数量。可以判断是否全部使用了组合索引。

  • 字符串类型

        字符串长度跟字符集有关:latin1=1、gbk=2、utf8=3、utf8mb4=4

        char(n):n*字符集长度

        varchar(n):n * 字符集长度 + 2字节

  • 数值类型

        TINYINT:1个字节        SMALLINT:2个字节        MEDIUMINT:3个字节

        INT、FLOAT:4个字节        BIGINT、DOUBLE:8个字节

  • 时间类型

        DATE:3个字节        TIMESTAMP:4个字节        DATETIME:8个字节

  • 字段属性

        NULL属性占用1个字节,如果一个字段设置了NOT NULL,则没有此项

2.6、Rows

        SQL查询扫描的行数,行数越小越好。MySQL查询优化器会根据统计信息,估算SQL要查询到结果需要扫描多少行记录。

2.7、Extra

额外信息。

  • Using where:表示查询需要通过索引回表查询数据。
  • Using index:表示查询需要通过索引,索引就可以满足所需数据。
  • Using filesort:表示查询出来的结果需要额外排序,数据量小在内存,大的话在磁盘,因此有Using filesort建议优化。
  • Using temprorary:查询使用到了临时表,一般出现于去重、分组等操作。
  • Using index condition:MySQL5.6之后新增的索引下推。在存储引擎层进行数据过滤,而不是在服务层过滤,利用索引现有的数据减少回表的数据。

3、profile 分析执行耗时

观测SQL真正的执行线程状态及消耗的时间。

3.1、查询profile开启状态

show variables like '%profil%'

  • have_profiling:确定是否支持 profile
  • profiling:是否开启profiling
  • profiling_history_size:定义MySQL服务器最近接收到的SQL条数。

3.2、开启profiling

执行如下SQL:

set profiling=ON
set profiling_history_size=30

3.3、查看最近运行的SQL

3.3.1、show profiles

查询最近SQL的执行耗时。

-- 查询最近profiling_history_size条SQL
show profiles;

3.3.2、show profile for query id

查询一条SQL从开始到结束整个生命周期各个阶段的执行耗时。

-- 根据query_id查询指定SQL执行耗时
show profile for query id

4、Optimizer Trace分析详情

        profile只能查询SQL执行耗时,无法看到SQL具体的执行信息。

        Optimizer Trace:可以跟踪执行语句的解析优化执行的全过程。

4.1、分析流程

  • 打开开关
set optimizer_trace="enabled=on"
  • 执行需要分析的SQL
  • 执行跟踪
select * from information_schema.optimizer_trace

4.2、结果分析

  • join_preparation:准备阶段

  • join_optimization:分析阶段

  • join_execution:执行阶段

5、慢查询经典案例总结

以user表为例举例说明:

CREATE TABLE user (
  id int(11) NOT NULL AUTO_INCREMENT,
  user_id varchar(32) NOT NULL,
  age  varchar(16) NOT NULL,
  name varchar(255) NOT NULL,
  PRIMARY KEY (id),
  KEY idx_userid (userId) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

5.1、隐式类型转换

把userId设为索引,如果在查询条件中把一个数字传给user_id,则索引失效。

# user_id索引失效,传的是数字123,索引user_id类型为字符串,两者类型不匹配
# MySql会将user_id转换为字符串再进行比较。
select *from user where user_id = 123

# 走userId索引
select *from user where user_id = '123'

5.2、最左匹配

        不满足最左匹配原则,索引不生效。

5.3、limit深分页问题

MySql会查询满足条件的100010行,然后丢弃前100000行,返回最后10行。

select *from user where age > 20 limit 100000,10

解决方案:减少回表

  • 标签记录法:

        标记一下上次查询到哪一条了,下次再来查的时候,从该条开始往下扫描。

# 标签记录法:局限是要求id连续
select *from user where id > 100000 limit 10
  • 延迟关联法:

        把条件转移到主键索引树,减少回表。

# 为age字段创建索引,通过age索引查询到满足条件的id,再与原表通过id内连接
select user1.id, user1.age, user1.name 
FROM user user1 
INNER JOIN (
    SELECT u.id FROM user u WHERE u.age > 20 limit 100000, 10
) AS user2 on user1.id= user2.id;

5.4、in元素过多

        如果in中的元素过多,建议分组查询,一次200个。

select * from user where user_id in (1,2,3...200)
union all
select * from user where user_id in (201,202,203...400)

5.5、order走文件排序导致的慢查询

        执行计划如下,Extra中包含了Using filesort(文件排序)。

  • 因为数据是无序的,所以就需要排序。如果数据本身是有序的,那就不会再用到文件排序啦。而索引数据本身是有序的,我们通过建立索引来优化order by语句。

  • 我们还可以通过调整max_length_for_sort_data、sort_buffer_size等参数优化;

5.6、索引字段使用is null 或 is not null可能导致索引失效

        有时可能因为数据量问题,导致MySQL优化器放弃走索引。另外,用explain分析SQL的时候,需要注意type=range时,可能会因为数据量问题,导致索引无效。

5.7、索引字段上使用(!= 或者 < >, not in)可能导致索引失效

        如果优化器觉得即使走了索引,还是需要扫描很多很多行的哈,它觉得不划算,不如直接不走索引。

5.8、左右连接,关联的字段编码格式不一致

select u.name, j.name, j.job
from user u
left join user_job j on u.name = j.name

将user表的name字段以及user_job表的name字段均设置索引

  • 假设user表的name字段编码为utf8,user_job表的name字段编码为utf8mb4,则上述sql查询不走索引。
  • 假设user表的name字段编码和user_job表的name字段编码均为utf8,则上述sql查询走索引。

5.9、delete + in子查询不走索引

delete from user where name in (select name from old_user)
  • delete + in子查询不走索引
  • select + in子查询走索引

        这是因为,实际执行的时候,MySQL对select in子查询做了优化,把子查询改成join的方式,所以可以走索引。但是对于delete in子查询,MySQL却没有对它做这个优化。

以上内容为个人学习理解,如有问题,欢迎在评论区指出。

部分内容截取自网络,如有侵权,联系作者删除。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/137781.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

gin web开发模板渲染

一、模板输出模板输出首先需要指定模板所放位置 r.LoadHTMLGlob("templates/**/*")参数中&#xff1a; **代表匹配任意名称的目录 *代表匹配任意名称的模板文件"templates/**/*" 代表可以匹配指定模板文件到 templates目录下的 hello/index.tmpl user/inde…

自然语言处理 第八章 机器翻译复习

机器翻译机器翻译概述典型神经机器翻译模型神经机器翻译 ( Neural Machine Translation, NMT神经机器翻译系统相关技术罕见词处理技术&#xff08;词表受限问题&#xff09;解决办法subword 方法beam searchcoverage penalty &#xff08;翻译覆盖率问题&#xff09;推敲网络&a…

qt运行外部exe并自定义外部功能界面(QWidget添加工具栏QToolBar)

先放效果图&#xff0c;就是在qt运行的界面中&#xff0c;不只是运行出了外部exe的界面&#xff0c;还可以在外围放置自定义的功能按钮。&#xff08;本质就是在QWidget中添加工具栏QToolBar&#xff09; 关于如何只运行出外部的exe&#xff0c;我之前写过教程&#xff1a;ht…

序列生成策略——束搜索、贪心搜索、穷举搜索

序列搜索策略包括贪心搜索、穷举搜索和束搜索。 贪心搜索所选取序列的计算量最小&#xff0c;但精度相对较低。 穷举搜索所选取序列的精度最高&#xff0c;但计算量最大。 束搜索通过灵活选择束宽&#xff0c;在正确率和计算代价之间进行权衡。 在序列到序列学习&#xff08…

Java集合面试题汇总大全

每个集合的出现一定是为了解决某种问题的解决方案。 集合流程图 JAVA中集合和数组的区别Collection和Collections的区别ArrayList和LinkedList 和Vector的区别list/set/map的区别HashSet和TreeSet和LinkedHashSet区别HashMap和Hashtable的比较HashMap和ConcurrentHashMap区别H…

【零基础】学python数据结构与算法笔记5

文章目录前言30.归并排序归并31.归并排序实现32.归并排序时间复杂度讨论33.NB三人组小结总结前言 学习python数据结构与算法&#xff0c;学习常用的算法&#xff0c; b站学习链接 30.归并排序归并 将两个箭头指向两个列表的首个元素&#xff0c;比较&#xff0c;哪个大就把它…

Java IO流 - 字符流的使用详细介绍

文章目录字符流的使用文件字符输入流创建字符输入流字符输入流读取文件字符输出流创建字符输出流字符输出流写入字符流的使用 字节流读取中文输出会存在什么问题&#xff1f; 会乱码。或者内存溢出。 读取中文输出&#xff0c;哪个流更合适&#xff0c;为什么&#xff1f; 字符…

MAX78000训练自己的神经网络模型

参考&#xff1a; The MAX78000 Microcontroller, Some Coffee, and Artificial Intelligence GitHub - MaximIntegratedAI/ai8x-training: Model Training for ADIs MAX78000 and MAX78002 AI Devices ai8x-synthesis/WSL2.md at develop MaximIntegratedAI/ai8x-synthesi…

移动金融管理系统设计与开发实训(课程设计报告)——基于Android+Django的银行系统部分功能设计与实现

阅读过程中若有不解和需要可私信&#xff0c;乐于解答 项目代码文档都保存着 基于AndroidDjango的银行系统部分功能开发与设计 摘要&#xff1a; 随着信息技术的快速发展以及经济的快速发展&#xff0c;金融界的信息化的进程也在不断推进&#xff0c;信息技术的不断成熟和人…

JavaWeb:EL表达式JSTL标签

1&#xff0c;EL表达式 1.1 概述 EL&#xff08;全称Expression Language&#xff09;表达式语言&#xff0c;用于简化JSP页面内的Java代码。 EL表达式的主要作用是 获取数据 。其实就是从域对象中获取数据&#xff0c;然后将数据展示在页面上。 而EL表达式的语法也比较简单…

HR软件七步帮助企业管理员工

对于中小企业&#xff08;SMB&#xff09;来说&#xff0c;员工就意味着一切。你的员工几乎掌握着企业的整体增长和发展&#xff0c;他们可以成就企业&#xff0c;但也能破坏企业的发展。为了提高员工效率&#xff0c;中小型企业需要出色的人力资源管理。员工只有在受到重视和培…

【Linux】Linux环境变量的理解

加油布鲁斯&#xff0c;你能行的&#xff01; 文章目录一、环境变量PATH中的系统默认搜索路径1.将程序安装到/usr/bin目录&#xff08;不带./运行自己写的程序&#xff09;2.将程序路径添加到PATH环境变量里面&#xff08;不带./运行自己写的程序&#xff09;二、环境变量的深…

PyTorch基础部分——毕设进行时

为了完成毕设准备开始学习PyTorch&#xff0c;第一步到蓝桥云课搜索实验项目&#xff0c;找到了“PyTorch入门与实战&#xff08;第二版&#xff09;”&#xff0c;开始边实验边学习&#xff08;本身有了一点点点点的相关基础了&#xff09;学习传送门&#xff1a;PyTorch基础入…

SQL WHERE 子句

WHERE 子句用于过滤记录。 SQL WHERE 子句 WHERE 子句用于提取那些满足指定条件的记录。 SQL WHERE 语法 SELECT column1, column2, ... FROM table_name WHERE condition; 参数说明&#xff1a; column1, column2, ...&#xff1a;要选择的字段名称&#xff0c;可以为多个…

06SpringCloudAlibaba负载均衡服务调用-OpenFeign

目录 SpringCloud Feign 查看此博客&#xff1a;005SpringCloud--Feign&#xff1a;负载均衡(基于服务端)_gh_xiaohe的博客-CSDN博客 OpenFegin概述 OpenFeign是什么&#xff1a; OpenFegin能干什么 Feign和OpenFeign两者区别 OpenFeign使用步骤 服务消费者 接口注解 微…

TP相关知识

说明 该文章来源于徒弟lu2ker转载至此处&#xff0c;更多文章可参考&#xff1a;https://github.com/lu2ker/ 文章目录说明PHP中有一些内置类PHP反序列化问题绕过姿势&#xff1a;魔术方法&#xff08;反序列化如何利用&#xff09;CMS可能存在的部分逻辑问题$_REQUEST相关安全…

小游戏引擎选型参考指南

写在前面 前面写了几期有关于小游戏的文章&#xff0c;主要从小游戏开发、小游戏运营、小游戏变现等多个角度进行了较为粗略的介绍&#xff0c;很多同学表示对小游戏引擎部分很感兴趣&#xff0c;希望能够有一些更为深入的分析介绍。今天就对目前主流的小游戏引擎进行探讨。 …

Java 并发编程 (二)CountDownLatch和CyclicBarrier的使用

CountDownLatch和CyclicBarrier CountDownLatch 功能介绍 CountDownLatch 是一个同步功能的辅助类 线程计数不为0时呈wait状态如果为0则继续执行。通过await 和 countDown 两个方法来实现等待和继续运行。 作用&#xff1a;一个线程或多个线程等待另一个线程或多个线程完成后…

2003-2021年高铁列车信息

2003-2021年高铁列车信息 1、时间&#xff1a;2003-2021年 2、指标&#xff1a; 列车车次、出发站、出发站所属地级市、出发站所属省份、出发站类型、到达站、到达站所属地级市、到达站所属省份、到达站类型、车型、开车时间、到站时间、运行时间、里程 3、指标说明&#x…

58. 微调(fine-tuning)

前面的一些章节介绍了如何在只有6万张图像的Fashion-MNIST训练数据集上训练模型。 我们还描述了学术界当下使用最广泛的大规模图像数据集ImageNet&#xff0c;它有超过1000万的图像和1000类的物体。 然而&#xff0c;我们平常接触到的数据集的规模通常在这两者之间。 假如我们…