mysql in查询优化

都说in查询比较慢,要改成子查询模式,ChatGPT大模型告诉了我,SQL中替换In查询的10种方法,太赞了,按照这个说的集中方法,验证一下。因为实际项目中确实存在in很多的情况。

查询执行的先后顺序对优化有必要,因此下面的逻辑需要了解。

sh 复制代码
in 先执行子查询,使用于内小,外大
exist 先执行外层表驱动表,适用于外小,内大
in适合 外层大, 内层小, 先执行内层子查询,过滤出来一小部分数据,再用来查外层
exist适用于外层小,内层大,先执行外层驱动表查询,出来一部分数据,再查内层表

下面的in里面的值不是固定的,

sql 复制代码
SELECT id, as_id, aa_type, CODE, NAME, mnemonic, remark, STATUS, create_user, create_time, update_user, update_time FROM acc_assisting_accounting WHERE ( STATUS IN ('01', '02') AND as_id = 1 AND id IN ( 374663, 510330, 510333, 374826, 194, 230, 111, 233, 357, 564001, 96, 564000, 10, 11, 12, 13, 563675, 15, 16, 441211, 362, 363, 121, 364, 243, 365, 410181, 526376, 366, 367, 425305, 400, 445538, 368, 402, 369, 127, 403, 8, 9, 510315, 24, 25, 374564, 367070, 370, 374725, 371, 250, 372, 251, 373, 131, 374, 386148, 375, 376, 134, 377, 139, 564023, 564144, 564145, 563331, 561273, 564143, 32, 564148, 564146, 564147, 519437, 564029, 374792, 380, 374835, 381, 260, 382, 261, 141, 384, 385, 419973, 386, 388, 524699, 357442, 149, 420959, 305, 510336, 564150, 564155, 564156, 494009, 456443, 564154, 564157, 371993, 564158, 390, 393, 154, 397, 276, 399, 313, 159, 564162, 564163, 564161, 52, 564167, 564164, 374974, 374854, 564169, 563998, 374210, 160, 162, 466216, 163, 164, 165, 320, 321, 288, 169, 364386, 329, 60, 209, 62, 524790, 514113, 365133, 294, 173, 295, 333698, 296, 176, 331, 332, 214, 215, 344905, 337, 338, 381698, 363223, 394580, 374091, 77, 374634, 510387, 183, 340, 341, 342, 343, 102, 345, 346, 380752 )) ORDER BY CODE ASC

mysql解析器,查看一下扫描rows很少啊
select_typeSIMPLE表示简单查询,不包含子查询或UNION

1 find_in_set过滤的模式

基本上全表扫描了

2 exists替换in操作符

从实际效果验证,依旧不好。还不如in,固然chatgpt说的专家,也就是砖家。不要认为exist就一定性能好。

3 with方式
with as方式mysql5.7及以下版本不支持,而我们的生产环境就是mysql5.7,因此这条路是走不通的。

不过我还是想知道,这个效果怎么样,于是在本地的mariadb上运行,效果如下,嗯,貌似有进步。不过也让我研究一下explain的结果是啥意思。

虽然上面type出现了ALL,但那是临时表,也就是in里面的内容,所以没有影响。主表是eq_ref因为走了逐渐索引

select_typeMATERIALIZED说明采用的是物化视图,因为物化视图是预计算和存储的查询结果,用于提高查询性能,也就是说with as会创建物化视图,有助于性能优化
PRIMARY显示最外层的select语句是我的主表aaa

虽然mysql 5.7不支持with写法,可以通过下面的方式来实现

sql 复制代码
SELECT aaa.*
from acc_assisting_accounting aaa
inner join (
select 1 as id union all
		select 2 as id union all
		select 3 as id union all
		select 4 as id union all
		select 23 as id union all
		select 24 as id 
)	t on t.id = aaa.id
where as_id=112514

DERIVED表示派生表,通过子查询中派生的临时表

4 虚拟表

将in的内容,创建一个临时表,按照别人的示例,我为什么执行不通过呢?语句貌似没有错误.

查看mysql select 临时表, 应该是要先创建一张temp的临时表。

但是看了mysql临时表 表变量_SQL 使用 VALUES 生成带数据的临时表实例代码详解,好像有不对

相关推荐
Cloud云卷云舒10 小时前
云卷云舒:从Oracle/MySQL迁移到HaishanDB:迁移评估工具核心技术拆解
mysql·oracle·ai-native·haishandb·信创数据库替换
用户713335851562413 小时前
MySQL - 事务、redo/undo 日志与 MVCC
mysql
用户713335851562414 小时前
MySQL - InnoDB 的 Buffer Pool
mysql
欲速不达882015 小时前
Mysql并发DML锁等待的优化
数据库·mysql
L16247616 小时前
MySQL 全环境生产快速安装 + 完整配置手册(整合国产银河麒麟适配 + 主从补充版)
数据库·mysql
前端世界17 小时前
MySQL 基础入门(学习第4天)——约束与 DML 操作详解
数据库·学习·mysql
Vect__19 小时前
MySQL 数据类型和约束:从字段设计到表结构建模
数据库·mysql
Mico1821 小时前
MySQL 8.0.35 基于GTID 主从复制安装增强半同步复制
android·mysql·adb
CodexDave1 天前
MySQL事务隔离级别与MVCC机制解析
前端·数据库·mysql·nginx·性能优化·负载均衡
王琦03181 天前
生产环境中使用通用二进制包安装
mysql