首页 > 数据库 >mysql的not in 优化

mysql的not in 优化

时间:2022-10-24 20:00:44浏览次数:78  
标签:uid 优化 mid 索引 mysql where id select

有一个项目,mysql 语句采用了not in,结果某些页面打开需要40多秒,排查sql语句后,发现是采用了 not in 语法导致全表扫描,消耗了大量的时间,飘易记录下优化的过程:

项目简介:
会议应该签到表 signshould :15万条数据
会议实际签到表 sign :10万条数据
请假表 leaves :1000条数据

其中字段:mid:会议id,uid:用户id

【例一】:原先的 not in 语句:

 

  1.   select uid from signshould where mid=897 
  2.   and uid not in(select uid from sign where mid=897 and thetype=0) 
  3.   and uid not in(select uid from leaves where mid=897)

时间: 18.898s

 

 

查看状态,可以看到 Handler_read_rnd_next 值很大,达到了 1073万次请求,该参数的含义:在数据文件中读下一行的请求数。如果你正进行大量的表扫描,该值较高。通常说明你的表索引不正确或写入的查询没有利用索引。

说明上诉sql语句引起了全表扫描。

explain SQL语句:

此时,我们在 mid  和 uid 上并未建立索引。

优化思路1:在 mid  和 uid 上建立索引后再 explain:

时间下降到: 0.039s。

 

 

优化思路2:采用left join 和 右表.id is null 的方法优化:

  1.   select a.* from signshould as a 
  2.   LEFT JOIN (select * from sign where mid=897 and thetype=0) as b ON a.uid=b.uid 
  3.   LEFT JOIN (select * from leaves where mid=897) as c ON a.uid=c.uid  
  4.   where a.mid=897 and b.uid is null and c.uid is null

没有建立索引时间: 0.031s

建立索引时间: 0.016s

飘易发现采用 left join 方法执行sql语句的时候:

没有索引的前提下,执行时间仅为not in方法的 1.6/千分 【0.031/18.898】;

建立了索引后消耗时间仅为not in(也建立索引)方法的 40% 【0.016/0.039】。

索引 not in 执行时间 left join 执行时间 优化后时间占比
无索引 18.898 0.031 1.6‰
有索引 0.039 0.016 40%

 

可以看到优化后的 Handler_read_rnd_next 值下降到了22万。

注:LEFT JOIN 关键字会从左表那里返回所有的行,即使在右表中没有匹配的行。

EXPLAIN sql:

 

 

【例二】:原先的not in的sql语句2:

  1.   select uid from sign where mid=674 and thetype=0 
  2.   and uid not in(select uid from sign where mid=674 and thetype=1) 
  3.   and uid not in(select uid from leaves where mid=674)

时间: 39.208s

 

可以看到 Handler_read_rnd_next 值很大,达到了 2500万,也是全表扫描导致的。

 

 

采用left join 和 右表.id is null 方法优化:

  1.   select a.* from sign as a 
  2.   LEFT JOIN (select * from sign where mid=674 and thetype=1) as b ON a.uid=b.uid 
  3.   LEFT JOIN (select * from leaves where mid=674) as c ON a.uid=c.uid  
  4.   where a.mid=674 and a.thetype=0 and b.uid is null and c.uid is null

时间: 0.048s

 

优化后 Handler_read_rnd_next 的值下降到了 18万。

 

 

LEFT JOIN 要点:

  1.   select t1.id,t2.id from t1
  2.   left join t2 on t1.id = t2.id and t1.id>1 and t2.id<>3

在mysql的 left join 中条件放在on后面和在where后面是不同的;

1. on后面只针对于t2表进行过滤,所以上面的 t1.id>1 将不起作用,切记,切记;

2. where后面会对最终结果产生影响,所以如果t2.id<>3放到on后面和where后面也是会返回不同的结果;

  例如下面脚本一会比脚本二多返回一些数据。

  1.   select * from test2 left join test1 on test2.id = test1.id and test1.id<>3  where test2.id <>6;
  2.   --
  3.   select * from test2 left join test1 on test2.id = test1.id  where test2.id <>6 and test1.id<>3;

 

 

标签:uid,优化,mid,索引,mysql,where,id,select
From: https://www.cnblogs.com/matengfei123/p/16822595.html

相关文章

  • mysql 联表更新某个字段
    想把i表中的数据通过关联关系,更新到m表中updateT_MuasmLEFTJOINT_Infoasionm.F_InfoId=i.F_Idsetm.F_InfoUuid=i.F_Uuid这里的join可以使用常见的......
  • 具名返回值优化(NRV)
    具名返回值优化(NRV)最近在看《深度探索C++对象模型》,在第2.3节中提到了具名返回值优化(NamedReturnValueoptimization,NRV),如下:#include<iostream>classTest{publi......
  • MySQL中数据类型宽度
    一、数据类型的取值范围和宽度字段类型对应的取值范围:类型字节有符号取值范围无符号取值范围TINYINT1-128~1270~255SMALLINT2-32768~327670......
  • springboot整合elasticsearch实现MySQL模糊查询
    es关联mysql实现模糊查询的数据流:   1、使用logstash同步mysql数据到eslogstash简介及基本操作:https://blog.csdn.net/yurun_house/article/details/109025588win......
  • mysql事务和隔离级别学习--笔记
    一、MySQL事务1、什么事事务事务(transaction)就是一个最小的单独任务单元由一个或多个SQL语句组成,在这个任务单元中,每个SQL语句都是相互依赖,整个任务单元是作为一个不可分......
  • KYLIN(麒麟系统)下安装MySQL5.0
    1groupaddmysql2useradd-gmysqlmysql3#修改密码4passwdmysql5cd/usr/local6#解压文件7tar-zxvfmysql-standard-5.0.15-linux-i686.tar.gz8......
  • mysql InnoDB建表时设定初始大小的方法
    InnoDB在写密集的压力时,由于B-Tree扩展,因而也会带来数据文件的扩展,然而,InnoDB数据文件扩展需要使用mutex保护数据文件,这就会导致波动。丁奇的博客说明了这个问题:WhenInno......
  • MySQL 中 不等于 会过滤掉 Null 的问题
    1.原因: 在写SQL条件语句时经常用到不等于!=的筛选条件。  此时要注意此条件会将字段为Null的数据也当做满足不等于的条件而将数据筛选掉。 2.实例:表A ......
  • Mac下安装MySQL详细图文步骤
    1.安装包下载下载链接:https://downloads.mysql.com/archives/community/为了安装更方便,建议下载和mac电脑版本匹配的mysql的dmg安装包,我的电脑Mac版本是12.5的,所以下载......
  • WGCLOUD无法连接到mysql数据库的原因
    WGCLOUD有时候连不上mysql数据库,我们按照以下几点来排查下:1.我们首先检查server/config/application.yml中mysql连接配置是否正确,比如用户名密码这些2.再检查mysql是否已......