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 生成带数据的临时表实例代码详解,好像有不对

相关推荐
White_Mountain8 分钟前
在Ubuntu中配置mysql,并允许外部访问数据库
数据库·mysql·ubuntu
老王笔记13 分钟前
GTID下复制问题和解决
mysql
Lojarro2 小时前
【Spring】Spring框架之-AOP
java·mysql·spring
TianyaOAO2 小时前
mysql的事务控制和数据库的备份和恢复
数据库·mysql
Ewen Seong2 小时前
mysql系列5—Innodb的缓存
数据库·mysql·缓存
W21554 小时前
Liunx下MySQL:表的约束
数据库·mysql
nbsaas-boot5 小时前
探索 JSON 数据在关系型数据库中的应用:MySQL 与 SQL Server 的对比
数据库·mysql·json
奥顺5 小时前
PHPUnit使用指南:编写高效的单元测试
大数据·mysql·开源·php
苹果醋37 小时前
SpringBoot快速入门
java·运维·spring boot·mysql·nginx
ROCKY_8177 小时前
Mysql复习(一)
数据库·mysql