MYSQL之not in优化方法:left join

MYSQL之not in优化方法:left join

Author:飘易 Source:飘易

正 文:

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

项目简介:

会议应该签到表 signshould :15万条数据

会议实际签到表 sign :10万条数据

请假表 leaves :1000条数据

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

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

select uid from signshould where mid=897 
and uid not in(select uid from sign where mid=897 and thetype=0) 
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 的方法优化

select a.* from signshould as a 
LEFT JOIN (select * from sign where mid=897 and thetype=0) as b ON a.uid=b.uid 
LEFT JOIN (select * from leaves where mid=897) as c ON a.uid=c.uid  
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:

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

时间: 39.208s

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

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

select a.* from sign as a 
LEFT JOIN (select * from sign where mid=674 and thetype=1) as b ON a.uid=b.uid 
LEFT JOIN (select * from leaves where mid=674) as c ON a.uid=c.uid  
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 要点:

select t1.id,t2.id from t1
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后面也是会返回不同的结果;

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

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

本文完。

作者:飘易
来源:飘易
版权所有。转载时必须以链接形式注明作者和原始出处及本声明。

摘自飘易博客,原文链接:http://www.piaoyi.org/database/MYSQL-not-in-left-join.html#comment-5118

原文地址:https://www.cnblogs.com/zran/p/10206913.html

时间: 2024-10-29 19:08:42

MYSQL之not in优化方法:left join的相关文章

【Mysql】大数据处理优化方法

1.应尽量避免在 where 子句中使用 != 或  <>  操作符,否则将引擎放弃使用索引而进行全表扫描. 2.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by  涉及的列上建立索引. 3.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select i

mysql性能的检查和优化方法

这个命令可以看到当前正在执行的sql语句,它会告知执行的sql.数据库名.执行的状态.来自的客户端ip.所使用的帐号.运行时间等信息 mysql在遇到严重性能问题时,一般都有这么几种可能:1.索引没有建好;2.sql写法过于复杂;3.配置错误;4.机器实在负荷不了;1.索引没有建好如果看到mysql消耗的cpu很大,可以用mysql的client工具来检查.在linux下执行/usr/local/mysql/bin/mysql -hlocalhost -uroot -p输入密码,如果没有密码,则

centos linux服务器apache+mysql环境访问慢优化方法

一.优化apache配置增加MaxClients的值 默认情况下,2.0及以上apache版本MaxClients的值为256,对于中大型应用访问是远远不够的. 在Apache2.0中,可以通过在httpd.conf配置的perfork代码段内修改ServerLimit和MaxClients参数来突破256的限制,此时必须MaxClients ≤ ServerLimit ≤ 20000设置完之后大致是这样的: ServerLimit 1000StartServers 30MinSpareServ

mysql模糊查询的优化方法--亲自实践

数据有4W多条,不多,但是模糊查询 起来特别慢. 1,尝试过用 select * from (select * from a union all select * from b...很多表union) as tempTable where name like "%a%" and person_id like "%1%",发现太慢了.. 2,尝试使用具体的字段,而不是*,即 select id,name,person_id from (select id,name,p

redmine在linux上的mysql性能优化方法与问题排查方案

iredmine的linux服务器mysql性能优化方法与问题排查方案 问题定位: 客户端工具: 1. 浏览器inspect-tool的network timing工具分析 2. 浏览器查看 response header, 分析http server 与 web server.       服务器工具:   0. nmon 查看各类系统负载, rrdtool 查看网络状况.   1. uptime看cpu负载;    free看内存;  mem ; cat /proc/meminfo以及  i

最全 MySQL 优化方法,从此优化不再难

说起MySQL的查询优化,相信大家收藏了一堆奇技淫巧:不能使用SELECT *.不使用NULL字段.合理创建索引.为字段选择合适的数据类型..... 你是否真的理解这些优化技巧?是否理解其背后的工作原理?在实际场景下性能真有提升吗?我想未必.因而理解这些优化建议背后的原理就尤为重要,希望本文能让你重新审视这些优化建议,并在实际业务场景下合理的运用. MySQL逻辑架构 如果能在头脑中构建一幅MySQL各组件之间如何协同工作的架构图,有助于深入理解MySQL服务器.下图展示了MySQL的逻辑架构图

30多条mysql数据库优化方法,千万级数据库记录查询轻松解决【转】

转自:http://www.ihref.com/read-16422.html 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描, Sql 代码 : select id from t where num is null; 可以在 num 上设置默认值 0,确保表中 num 列没有 null 值,然后这样查询: Sql 代码 : s

数据库调优教程(十三) MySQL数据库其他优化方法

六.           MySQL数据库其他优化方法 最后一章,谈谈前面没有涉及的一些优化方法. 1.      My.ini配置文件 这里只介绍两个最重要的,其他的不过多介绍. 1)    配置 最大连接数 默认为100,建议设为1000 2)   配置 缓存 在my.ini的[mysqld]节点开启查询缓存,配置如下 query_cache_size = 268435456 query_cache_type = 1 query_cache_limit = 1048576 2.      使

mysql limit分页优化方法分享

MySQL的优化是非常重要的.其他最常用也最需要优化的就是limit.MySQL的limit给分页带来了极大的方便,但数据量一大的时候,limit的性能就急剧下降. 同样是取10条数据 select * from yanxue8_visit limit 10000,10 和 select * from yanxue8_visit limit 0,10 就不是一个数量级别的. 网上也很多关于limit的五条优化准则,都是翻译自MySQL手册,虽然正确但不实用.今天发现一篇文章写了些关于limit优