一个奇怪的MySQL慢查询,打懵了一群不懂业务的DBA!

MySQL慢查询日志使用 mysql慢日志查询,不要被网上一些关于mysql慢查询的相关文章所迷惑——他们对此参数的解释是(如果设置了,所有没有使用索引的查询也将被记录),我看了就奇怪了,这不和参数log-queries-not-using-indexes的功能是一样的么,于是百度之,可笑的是,即然有很多文章都是类似描述,这些只知道copy的站长或那些只顾转载的朋友,你要我怎么说你们呢。通过查看慢查询日志可以发现,很乱,数据量大的时候,可能一天会产生几个G的日志,根本没有办法去清晰明了的分析。所以,这里,采用工具进行分析。 阅读详情

前言

最近,开发人员需要定期的删除表里一定时间以前的数据,SQL如下:

mysql > delete from testtable WHERE biz_date <= '2017-08-21 00:00:00'  AND status = 2  limit 500\G

前段时间在优化的时候,我们已经在相应的查询条件上加上了索引,如下:

KEY `idx_bizdate_st` (`biz_date`,`status`)

但是实际执行的SQL依然非常慢,为什么呢,我们来一步步分析验证下。

分析

表上的字段既然都有索引,那么按照之前的文章分析,是两个字段都可以走上索引的。

既然能够利用索引,表的总大小也就是200M左右,那么为什么形成了慢查呢?

我们查看执行计划,去掉limit 后,发现他选择了走全表扫描。

mysql > desc  select * from testtable   WHERE biz_date <= '2017-08-21 00:00:00';
+----+-------------+-----------+------+----------------+------+---------+------+--------+-------------+
| id | select_type | table     | type | possible_keys  | key  | key_len | ref  | rows   | Extra       |
+----+-------------+-----------+------+----------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | testtable | ALL  | idx_bizdate_st | NULL | NULL    | NULL | 980626 | Using where |
+----+-------------+-----------+------+----------------+------+---------+------+--------+-------------+
1 row in set (0.00 sec)

-- 只查询biz_date
-- 关键点:rows:980626;type:ALL

mysql > desc  select * from testtable   WHERE biz_date <= '2017-08-21 00:00:00' and status = 2;
+----+-------------+-----------+------+----------------+------+---------+------+--------+-------------+
| id | select_type | table     | type | possible_keys  | key  | key_len | ref  | rows   | Extra       |
+----+-------------+-----------+------+----------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | testtable | ALL  | idx_bizdate_st | NULL | NULL    | NULL | 980632 | Using where |
+----+-------------+-----------+------+----------------+------+---------+------+--------+-------------+
1 row in set (0.00 sec)

-- 查询biz_date + status 
-- 关键点:rows:980632;type:ALL

mysql > desc  select * from testtable   WHERE biz_date <= '2017-08-21 00:00:00' and status = 2 limit 100;
+----+-------------+-----------+-------+----------------+----------------+---------+------+--------+-----------------------+
| id | select_type | table     | type  | possible_keys  | key            | key_len | ref  | rows   | Extra                 |
+----+-------------+-----------+-------+----------------+----------------+---------+------+--------+-----------------------+
|  1 | SIMPLE      | testtable | range | idx_bizdate_st | idx_bizdate_st | 6       | NULL | 490319 | Using index condition |
+----+-------------+-----------+-------+----------------+----------------+---------+------+--------+-----------------------+
1 row in set (0.00 sec)

-- 查询biz_date + status+ limit 
-- 关键点:rows:490319;

mysql > select count(*)  from testtable   WHERE biz_date <= '2017-08-21 00:00:00' and status = 2;
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.34 sec)

mysql > select count(*)  from testtable   WHERE biz_date <= '2017-08-21 00:00:00';
+----------+
| count(*) |
+----------+
|   970183 |
+----------+
1 row in set (0.33 sec)

mysql > select count(*)  from testtable;
+----------+
| count(*) |
+----------+
|   991421 |
+----------+
1 row in set (0.19 sec)

mysql > select distinct biz_status from testtable;
+------------+
| biz_status |
+------------+
|          1 |
|          2 |
|          4 |
+------------+

通过以上查询,我们可以发现如下几点问题:

  • 通过 biz_date 预估出来的行数 和 biz_date + status=2 预估出来的行数几乎一样,为98w。
  • 实际查询表 biz_date + status=2 一条记录都没有。
  • 整表数据量达到了99万,MySQL发现通过索引扫描需要98w行(预估)

因此,MySQL通过统计信息预估的时候,发现需要扫描的索引行数几乎占到了整个表,放弃了使用索引,选择了走全表扫描。

那是不是他的统计信息有问题呢?我们重新收集了下表统计信息,发现执行计划的预估行数还是一样,猜测只能根据组合索引的第一个字段进行预估(待确定)。

那我们试下直接强制让他走索引呢?

mysql > select * from testtable   WHERE biz_date <= '2017-08-21 00:00:00' and status = 2;
Empty set (0.79 sec)


mysql > select * from testtable force index(idx_bizdate_st)  WHERE biz_date <= '2017-08-21 00:00:00' and status = 2;
Empty set (0.16 sec)

我们发现,强制指定索引后,查询耗时和没有强制索引比较,的确执行速度快了很多,因为没有强制索引是全表扫描嘛!但是!依然非常慢!

那么还有什么办法去优化这个本来应该很快的查询呢?

大家应该都听说过要选择性好的字段放在组合索引的最前面?

选择性好的索引在前面并不是对所有的场景都通用的,这个场景可以将status放前面,sql速度会更快。

那,能不能让他不要扫描索引的那么多范围呢?之前的索引模型中也说过,MySQL是通过索引去确定一个扫描范围,如果能够定位到尽可能小的范围,那是不是速度上会快很多呢?

并且业务逻辑上是定期删除一定日期之前的数据。所以逻辑上来说,每次删除都是只删除一天的数据,直接让SQL扫描一天的范围。那么我们就可以改写SQL啦!

mysql > select * from testtable WHERE biz_date >= '2017-08-20 00:00:00' and biz_date <= '2017-08-21 00:00:00' and status = 2;
Empty set (0.00 sec)

mysql > desc select * from testtable WHERE biz_date >= '2017-08-20 00:00:00' and biz_date <= '2017-08-21 00:00:00' and status = 2;
+----+-------------+------------------+-------+----------------+----------------+---------+------+------+-----------------------+
| id | select_type | table            | type  | possible_keys  | key            | key_len | ref  | rows | Extra                 |
+----+-------------+------------------+-------+----------------+----------------+---------+------+------+-----------------------+
|  1 | SIMPLE      | testtable        | range | idx_bizdate_st | idx_bizdate_st | 6       | NULL |  789 | Using index condition |
+----+-------------+------------------+-------+----------------+----------------+---------+------+------+-----------------------+
1 row in set (0.00 sec)

-- rows降低了很多,乖乖的走了索引

mysql > desc select * from testtable WHERE biz_date >= '2017-08-20 00:00:00' and biz_date <= '2017-08-21 00:00:00' ;
+----+-------------+------------------+-------+----------------+----------------+---------+------+------+-----------------------+
| id | select_type | table            | type  | possible_keys  | key            | key_len | ref  | rows | Extra                 |
+----+-------------+------------------+-------+----------------+----------------+---------+------+------+-----------------------+
|  1 | SIMPLE      | testtable        | range | idx_bizdate_st | idx_bizdate_st | 5       | NULL | 1318 | Using index condition |
+----+-------------+------------------+-------+----------------+----------------+---------+------+------+-----------------------+
1 row in set (0.00 sec)

-- 即使没有status,也是肯定走索引啦

小结

这个问题,我原本打算用hint,强制让他走索引,但是实际上强制走索引的执行时间并不能带来满意的效果。结合业务逻辑,来优化SQL,是最好的方式,也是终极法宝,一定要好好利用。不了解业务的DBA,不是一个好DBA…

sap2000 api matlab,SAP2000_API入门指南.pdf SAP2000_API入门指南北 京 金 土 木 软 件 技 术 有 限 公 司Beijing Civil King Software TechnologyCo., Ltd.SAP2000 API 入门指南余承飞 韦群跃 汤娣概述SAP2000 API 是从 SAP2000 V11 开始引进的,即应用软件编程接口。用户可以编写程序,通过API 随心所欲地调用 SAP2000... 阅读详情

相关推荐

Win11实时字幕还能这么玩?手把手教你打造专属‘AI字幕机’,告别视频网站无字幕困扰

本文详细介绍了如何利用Win11的实时字幕功能打造全平台通用的AI字幕系统。通过C#抓取程序、Node.js中转服务和前端展示界面的组合,实现自动抓取系统字幕并实时推送到任意网页视频的方案,有效解决在线视频无字幕的困扰。

weixin_33735077的博客 395

mysql group by 查询慢_一个奇怪的MySQL慢查询,打懵了一群不懂业务的DBA!

一、前言开发需要定期的删除表里一定时间以前的数据,SQL如下mysql > delete from testtable WHERE biz_date <= '2017-08-21 00:00:00' AND status = 2 limit 500G前段时间在优化的时候,已经在相应的查询条件上加上了索引KEY `idx_bizdate_st` (`biz_date`,`status...

weixin_39887221的博客 489

创新实训项目博客:基于LoRA的医疗大模型高效微调实战

预训练大语言模型(LLMs)虽然具备了广泛的知识和一定的通用能力,但在特定领域(如医疗)或特定任务(如遵循特定指令格式进行思考链推理)上,其表现往往不尽如人意。微调(Fine-tuning)能够使模型学习到特定领域的数据分布和任务模式,从而在目标任务上获得更好的性能,使其更贴合实际应用需求。使用Unsloth框架加载并以4-bit量化模型。基于数据集,构建了包含明确思考链引导的训练Prompt。配置了LoRA参数,并使用SFTTrainer在单张T4 GPU上对模型进行了高效微调。

m0_73556916的博客 1291

mysql删除key_一个奇怪的MySQL慢查询,打懵了一群不懂业务的DBA!

# 前言最近,开发人员需要定期的删除表里一定时间以前的数据,SQL如下:mysql > delete from testtable WHERE biz_date <= '2017-08-21 00:00:00' AND status = 2 limit 500\G前段时间在优化的时候,我们已经在相应的查询条件上加上了索引,如下:KEY `idx_bizdate_st` (...

weixin_39628342的博客 85

Keil5 安装与卸载全攻略:从零开始到完美避坑

本文提供了Keil5集成开发环境的完整安装与卸载指南。针对嵌入式开发新手,详细解析了安装前的关键准备、MDK核心与C51双环境的安装激活步骤、常见问题排查,并重点介绍了如何彻底卸载软件以避免残留问题,帮助用户从零开始搭建稳定高效的开发环境。

weixin_29172963的博客 636

halcon 深度学习标注_Halcon deep learning之目标检测笔记(一)

设置输入输出的路径输入路径有两个,一个是图像路径HalconImageDir,一个是Json文件路径PillBagJsonFile。这两个参数用于后续在图像路径中读取coco文件。输出路径首先定义一个新的文件夹路径,用于存放样本和模型文件等数据。设置基于深度学习的目标检测模型的路径,该模型文件以.hdl结尾。设置样本数据文件夹ExampleDataDir:'detect_pills_data'数据...

weixin_27885313的博客 2700

mysql去掉两个最高分_一个奇怪的MySQL慢查询,打懵了一群不懂业务的DBA!

一、前言开发需要定期的删除表里一定时间以前的数据,SQL如下mysql > delete from testtable WHERE biz_date <= '2017-08-21 00:00:00' AND status = 2 limit 500G前段时间在优化的时候,已经在相应的查询条件上加上了索引KEY `idx_bizdate_st` (`biz_date`,`status...

weixin_30143813的博客 69

YOLOv13添加WDBB模块,map提升5.34!!,召回率提升6.55,准确率提升3.23

本文提出了一种基于YOLOv13改进的目标检测模型,通过引入WDBB模块显著提升了检测性能。实验结果表明,添加WDBB模块后,mAP提升11.34,召回率提升14.55,准确率提升3.23。文章详细介绍了模型移植方法,包括创建新的yaml配置文件、修改tasks.py和__init__.py文件,以及实现rep_block.py中的核心转换函数。改进后的模型通过深度卷积、通道注意力等模块优化了特征提取能力,同时保持了轻量化的特点。该工作为YOLO系列模型的性能提升提供了新的思路和技术实现。

FJN110的博客 2624

一个奇怪的MySQL慢查询,打懵了一群不懂业务的DBA

但是实际执行的SQL依然非常慢,为什么呢,我们来一步步分析验证下。

weixin_74412978的博客 647

高通SDX35:SGMII接口PHY RTL8211FSI-CG驱动适配

高通SDX35 RTL8211F SGMII

不秃头的程序猿Gabriel的博客 787

为分析表明卡诺电池技术(或热泵式储电技术)-是目前最佳的储能技术!!!-2021年

卡诺电池(Carnot Battery)是一种基于热力学循环的储能技术,其核心原理是通过热力循环将电能转化为热能存储,并在需要时将热能重新转换为电能输出。这种技术得名于热力学中的卡诺循环原理,由法国工程师卡诺于1824年提出。

qq_15963745的博客 657

一个奇怪的MySQL慢查询,打懵了不懂业务的DBA!

前言 最近,开发人员需要定期的删除表里一定时间以前的数据,SQL如下: mysql > delete from testtable WHERE biz_date

m0_63437643的博客 114

YOLOv11改进 | 损失函数改进篇 | 2024最新高质量的目标检测边界框回归损失Unified-IoU、FocalUIoU、FocalInvUIoU(设置动态epoch参数)

本文给大家带来的改进机制是最近新提出的高质量的目标检测边界框回归损失,其通过动态调整模型对不同质量预测框的关注,优化目标检测中的边界框回归精度。UIoU引入了FocalBox方法,通过缩放预测框与真实框分配权重,并采用了退火策略(引入动态参数epoch),逐渐将模型的注意力从低质量预测框转移到高质量预测框,平衡了训练速度与检测精度。其还有一定的解决样本不平衡问题,同时该损失函数可以和现有的任何边界框回归损失函数进行结合,例如ShapeIoU和其结合可以形成二次创新,它是一种类似于之前的Inner的机制.

Snu77的博客 4588

一个奇怪的MySQL慢查询,打懵了不懂业务的DBA!看完记得收藏!

前言 最近,开发人员需要定期的删除表里一定时间以前的数据,SQL如下: mysql > delete from testtable WHERE biz_date <= '2017-08-21 00:00:00' AND status = 2 limit 500\G 前段时间在优化的时候,我们已经在相应的查询条件上加上了索引,如下: KEY `idx_bizdate_st` (`b...

weixin_46898270的博客 150

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

一个奇怪的MySQL慢查询,打懵了不懂业务的DBA

前言 最近,开发人员需要定期的删除表里一定时间以前的数据,SQL如下: mysql>deletefromtesttableWHEREbiz_date<='2017-08-2100:00:00'ANDstatus=2limit500\G 前段时间在优化的时候,我们已经在相应的查询条件上加上了索引,如下: KEY`idx_bizdate_st`(`biz_date`,`status`) 但是实际执行的SQL依然非常慢,为什么呢,我们来一步步...

代码界的扛把子 131

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

mysql between 查询不出来_一个奇怪的MySQL慢查询,打懵了不懂业务的DBA!

文章来源;来源 | https://urlify.cn/ayYBvu前言最近,开发人员需要定期的删除表里一定时间以前的数据,SQL如下:mysql > delete from testtable WHERE biz_date <= '2017-08-21 00:00:00' AND status = 2 limit 500G前段时间在优化的时候,我们已经在相应的查询条件上加上了索引...

weixin_29051149的博客 425

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

mysql怪异的执行计划_一个奇怪的MySQL慢查询,打懵了不懂业务的DBA!

来源 |https://urlify.cn/ayYBvu前言最近,开发人员需要定期的删除表里一定时间以前的数据,SQL如下:mysql>deletefromtesttableWHEREbiz_date<='2017-08-2100:00:00'ANDstatus=2limit500\G前段时间在优化的时候,我们已经在相应的查询条件上加上了索引,如下:...

weixin_39859061的博客 128

mysql group by 查询慢_一个奇怪的MySQL慢查询,打懵了不懂业务的DBA!

文章来源;来源 | https://urlify.cn/ayYBvu前言最近,开发人员需要定期的删除表里一定时间以前的数据,SQL如下:mysql > delete from testtable WHERE biz_date <= '2017-08-21 00:00:00' AND status = 2 limit 500G前段时间在优化的时候,我们已经在相应的查询条件上加上了索引...

weixin_39873208的博客 124

mysql 慢查询日志

慢查询定义及作用 慢查询日志,顾名思义,就是查询慢的日志,是指mysql记录所有执行超过long_query_time参数设定的时间阈值的SQL语句的日志。该日志能为SQL语句的优化带来很好的帮助。默认情况下,慢查询日志是关闭的,要使用慢查询日志功能,首先要开启慢查询日志功能。 开启慢查询日志 在mysql的配置文件中的mysqld下方添加以下参数 log-slow-queries =

大头爸爸的博客 1万+

mysql慢查询相当

show variables like '%slow%'; 这上命令能看到mysql慢查询日志在哪 慢查询定义及作用 慢查询日志,顾名思义,就是查询慢的日志,是指MySQL记录所有执行超过long_query_time参数设定的时间阈值的SQL语句的日志。该日志能为SQL语句的优化带来很好的帮助。默认情况下,慢查询日志是关闭的,要使用慢查询日志功能,首先要开启慢查询日

laomengnevergiveup的博客 430
上一篇: MySQL锁:InnoDB行锁需要避免的坑
下一篇: Mysql 单表适合的最大数据量是多少?如何优化其性能?
Java技术那些事儿
博客等级 码龄5年 2306粉丝 2584原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值