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

相关推荐
momo小菜pa3 小时前
【MySQL 06】表的增删查改
数据库·mysql
程序员大金6 小时前
基于SpringBoot+Vue+MySQL的装修公司管理系统
vue.js·spring boot·mysql
gorgor在码农6 小时前
Mysql 索引底层数据结构和算法
数据结构·数据库·mysql
-seventy-6 小时前
SQL语句 (MySQL)
sql·mysql
一般路过糸.6 小时前
MySQL数据库——索引
数据库·mysql
无敌少年小旋风8 小时前
MySQL 内部优化特性:索引下推
数据库·mysql
翔云1234568 小时前
MVCC(多版本并发控制)
数据库·mysql
静听山水9 小时前
mysql语句执行过程
数据库·mysql
Q_w774210 小时前
一个真实可用的登录界面!
javascript·mysql·php·html5·网站登录
容器( ु⁎ᴗ_ᴗ⁎)ु.。oO11 小时前
MySQL事务
数据库·mysql