关于left join优化not in 导致的长时间查询无数据问题 Using where; Using join buffer (Block Nested Loop)

一、背景

  1. 线上存在业务,需要每天定时整理某个表A未处理的数据,并写入另外一张表B;
  2. 每天查询出不存在B表中且未处理过的A表数据;
  3. A表中的数据主键放入B表中,未设定B表对应索引;
  4. 数据量初始值大概在几千条;
  5. 根据网上书籍介绍及多数网友介绍,left join 优于 not exists 优于 not in,not in不走索引,所以最终选择left join完成该业务;
  6. 数据量大约在10万条数据时,已经无法查询出任何数据;
    在这里插入图片描述

二、测试环境

  1. mysql版本 5.7.30
  2. 数据库建表sql
    	create table test_a(
    		id int(11) primary key,
    		user_name varchar(11)
    	)
    	create table test_b(
    		id int(11),
    		user_name varchar(11)
    	)
    
  3. test_a存在主键索引,test_b表无索引
  4. 插入数据存储过程sql
    	CREATE DEFINER=`root`@`%` PROCEDURE `NewProc`()
    	BEGIN
    	#Routine body goes here...
    	declare id int(11);
    	DECLARE i int(11) DEFAULT 0;
    	DECLARE user_name varchar(11);
    	while i <= 1000000 do
    	 set i = i + 1;
    	 set id = i;
    	 set user_name = CONCAT('test',i);
    	 insert into test_a VALUES (id, user_name);
    	 set i = i + 1;
    	 set id = i;
    	 set user_name = CONCAT('test',i);
    	 insert into test_b VALUES (id, user_name);
    	 end while;
    	 END
    
  5. 保证test_a和test_b各存在id互不相等500001条数据

三、测试结果

left join

  1. 测试sql

    select count(0) from test_a a left join test_b b on a.id = b.id where b.id is null
    

    1.1 测试sql分析
    在这里插入图片描述
    1.2 测试结果
    无结果,数据查询时间过长无响应
    在这里插入图片描述

not exists

  1. 测试sql
    EXPLAIN select count(0) from test_a where not exists (select * from test_b where test_b.id = test_a.id)
    
    2.1 测试sql分析
    在这里插入图片描述
    2.2 测试结果
    无结果,数据查询时间过长无响应
    在这里插入图片描述

not in

  1. 测试sql
    EXPLAIN select count(0) from test_a where id not in (select id from test_b)
    
    3.1 测试sql分析
    在这里插入图片描述
    3.2 测试结果
    唯一一个出数据的,1.190s
    在这里插入图片描述

四、优化处理

  1. 增加test_b 的id索引
    在这里插入图片描述
  2. 查看对应结果
    2.1 left join , 0.596s
    在这里插入图片描述
    在这里插入图片描述
    2.2 not exists , 1.998s
    在这里插入图片描述
    在这里插入图片描述
    2.3 not in , 1.172s
    在这里插入图片描述
    在这里插入图片描述

五、结果分析

  1. 使用left join, not exists优化not in 语句时,必须在存在索引的情况下使用,否则有可能长时间查询无结果;
  2. left join在有索引的情况下对于此类情况优化最明显;
  3. not exists不一定速度快过not in,exists的原理是先查询exists前面表返回的数据,根据数据结果,作为条件与exists后面的查询进行对比(查询一条,对比一条),如果满足后面的条件,则返回真,然后返回数据,否则返回假,无数据,not exists则与之相反。所以not exists快过not in的前提是exists前面的语句对应的表查询返回的数据量必须小于后面的表查询返回的数据量;
  4. not in还是会走索引,至于是否与mysql版本有关,暂时不做论证;
  5. 使用Left join,exists优化 in语句时,必须要小心是否能触发索引,否则得不偿失。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值