暂无图片
MySQL 关联查询执行计划问题
我来答
分享
嘿嘿嘿
2024-03-22
MySQL 关联查询执行计划问题

同一个查询,条件不一样执行计划有差异

res表数据量40W,p表数据量17W,

res表表结构:

PRIMARY KEY (`id`),
UNIQUE KEY `idx_telnum` (`telNum`) USING BTREE,
KEY `idx_updatetime` (`updateTime`) USING BTREE,
KEY `idx_appid` (`appId`) USING BTREE,
KEY `idx_cm_group_id` (`cm_group_id`) USING BTREE,
KEY `channel_accid` (`channel_accid`),
KEY `idx_area_code` (`area_code`) USING BTREE

p表表结构

PRIMARY KEY (`id`),
UNIQUE KEY `idx_number` (`number`) USING BTREE,
KEY `idx_create_time` (`create_time`),
KEY `idx_area_code` (`area_code`) USING BTREE,
KEY `idx_status` (`status`) USING BTREE


加isVideo=0之后执行很慢,几乎查不出来,执行计划如图:


不添加isVideo这个条件执行很快几秒左右,执行计划如图


我来答
添加附件
收藏
分享
问题补充
4条回答
默认
最新
徐孝亮

原因:  因为你添加isVideo=0之后,走的执行计划都变了。 两张表的关联顺序变了,走的索引也变了。

分析:

两张表的关联方法是嵌套循环链接。嵌套循环链接的原理:驱动表返回多少行,被驱动表就需要被扫描多少次。

不加isVideo=0,p表是驱动表,走的idx_status索引,虽然该索引选择性差,但是就扫描一次。res是被驱动表,走了唯一性较好的telNum字段的索引。

加isVideo=0之后,res表扫描一次,返回8930行,p表此时作为被驱动表,就要被扫描8930次,因为走的还是idx_status索引,这个唯一性不好的索引造成的性能瓶颈就被放大了。

优化建议:

1.  添加hint force index (idx_number) 强制p表走idx_number字段的索引。 --如果还走不上,我怀疑你两张表的数据类型不一致,建议修改下数据类型,或者通过函数转一下。

2.  使用straight_join强制让p表先走,res表做被驱动表。

--不知道有没有说清楚,有任何问题可以再提问我。。

暂无图片 评论
暂无图片 有用 1
打赏 0
暂无图片
张sir

你可以试试加个组合索引:(area_code,isVideo,tagcode),

暂无图片 评论
暂无图片 有用 2
打赏 0
嘿嘿嘿
题主
2024-03-22
强制走telnum这个索引速度即可,我的疑问是加不加isVideo为何执行计划有如此差异
张sir
答主
2024-03-25
你可以看下这篇文章,如果你这个数据库版本是5.7的话,基本可以断定是由于filtered不准导致的差异。由于加了isvideo这是一个没有索引的字段,且没有直方图,filtered收到了影响,可以参考这篇文章:https://www.jianshu.com/p/e70de1f7cdcf
zhou

telnum 和number 类型贴一下最好是完整的ddl,看着一个像是varchar 一个是整型,统计信息不准,40万17万的两表统计信息只看出8万和16万

暂无图片 评论
暂无图片 有用 1
打赏 0
嘿嘿嘿
题主
2024-03-25
telnum varchar20,number varchar16
chengang

MySQL总是会选小表当驱动表 不加isVideo 条件 p表当然是小表。加了isVideo条件,MySQL认为过滤性很好,从执行计划的filtered = 0.05 可以推算出 MySQL评估认为 最终只有 8930 *0.05 = 446.50行参与最终的JOin 题主可以用condition_fanout_filter参数验证,这里贴了我的一篇文章 可以看看https://www.modb.pro/db/1752165858076086272

暂无图片 评论
暂无图片 有用 2
打赏 0
zhou
2024-03-23
假设随机读:10ms,顺序读:0.1ms 一个page 40条记录 执行计划1: filtered = 0.05 可以推算出 MySQL评估认为 最终只有 8930 *0.05/100 = 5 5*10 + 5*82979/40*0.1=11S 执行计划2: 82979/40*0.1 +82979*10*0.05=41S 粗糙IO COST比较 执行计划1<执行计划2, 但实际运行完全不同,代表执行计划高估了res filter,实际filter没有0.05%,应该高于0.4%才会导致比执行计划2慢 组合索引才是王道,估算出来的(a,b,c)filter= a filter * b filter * c filter 经常高估了filter isvideo filter 1%? select count(distinct isvideo) from res res filter= tagcode filter * isvideo filter 可能tagcode 与area_code 有关联性,isvideo 与 area_code也有关联性?
嘿嘿嘿
题主
2024-03-25
isVideo=0的数据有40W+,占据了99%
嘿嘿嘿
题主
2024-03-25
统计信息有误导致的?
回答交流
Markdown


请输入正文
提交
相关推荐
mysql 表数据库如果不小心删了如何恢复数据。
回答 1
已采纳
如果不小心删除了MySQL表中的数据,可以尝试以下几种方法来恢复数据:利用备份:如果你做了表的备份,可以通过还原备份文件来恢复数据。使用类似mysqluusernamepdatabase&lt;bac
MySQL什么情况下应不建或少建索引
回答 4
已采纳
1、如果表数据量太少可以不建索引,有时候全表扫描可能比索引快。2、对于DML操作很频繁的表不建议,前提是保证查询性能的情况下。3、表数据重复且分布平均的表字段,比如表记录10万行,取值只有男或者女。4
mysql 8.0报错 在插入表时提示 The table '/tmp/#sql124e7_b_1d' is full
回答 2
已采纳
看看/tmp目录的使用情况,是不是空间分配太小了,再检查一下MySQL里tmptablesize是不是配置的太大了。
如何定位出导致单核cpu高的慢查询语句
回答 4
做到实时很难,总要有一个采样周期。如果该SQL执行频率比较低,其实危害是有限的。如果是高频慢SQL,调整慢查询时间或者多次执行showprocesslist,大概率是能捕获到的。
MySQL企业版好吗
回答 1
已采纳
官方一直推企业版。而且企业版的功能多还有支持。推荐使用
学习openGauss还是MySql?
回答 3
目前oracle、mysql等国外的数据库依然是主流,但未来国产数据库肯定拥有不可小觑的发展,只是这个时间跨度暂无法预测,所以,建议各种数据库都去了解下
mysqld 在什么情况下会进入 do_signal 状态?
回答 1
可能遇到mysqlbug
mysql怎么像sqlserver那样使用print效果?
回答 1
在MySQL中,可以使用SELECT语句来输出打印内容。例如,以下代码可以输出“HelloWorld”:SELECT&x27;HelloWorld&x27;;
MySQL 备份还原是不是还可以在不同的版本中进行?
回答 3
已采纳
可以的,用逻辑备份导出sql语句,不但可以跨版本,还能跨系统,跨数据库.物理备份的话,就不一定了,跨小版本应该没得问题.
最近几年公司逐渐使用各种数据库,有什么好工具能够快速管理多种数据库吗?
回答 1
DBeaver、Navicat这两款相对来说是支持较多且通用的数据库管理工具和SQL客户端。你可以尝试试用一下,找适合自己的。但是通用的缺点肯定是没那些专用的好用的。就像Oracle,使用plsqld