MySQL优化--NOT EXISTS和LEFT JOIN方式差异
在MySQL中,我们可以将NOT EXISTS语句转换为LEFT JOIN语句来进行优化,哪为什么会有性能提升呢?
使用NOT EXISTS方式SQL为:
SELECT count(1)
FROM t_monitor m
WHERE NOT exists
(SELECT 1
FROM t_alarm_realtime AS a
WHERE a.resource_id=m.resource_id
AND a.resource_type=m.resource_type
AND a.monitor_name=m.monitor_name)
而使用LEFT JOIN方式SQL为:
SELECT count(1)
FROM t_monitor m
LEFT JOIN t_alarm_realtime AS a
ON a.resource_id=m.resource_id
AND a.resource_type=m.resource_type
AND a.monitor_name=m.monitor_name
WHERE a.resource_id is NULL
从查询效果来看,NOT EXISTS 方式耗时29.38秒,而LEFT JOIN方式耗时1.20秒,性能提升25倍左右。
查看NOT EXISTS方式的执行计划:
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: m
partitions: NULL
type: index
possible_keys: NULL
key: idx_id_name_type
key_len: 119
ref: NULL
rows: 578436
filtered: 100.00
Extra: Using where; Using index
*************************** 2. row ***************************
id: 2
select_type: DEPENDENT SUBQUERY
table: a
partitions: NULL
type: eq_ref
possible_keys: idx_id_name_type
key: idx_id_name_type
key_len: 119
ref: cmdb.m.resource_id,cmdb.m.monitor_name,cmdb.m.resource_type
rows: 1
filtered: 100.00
Extra: Using index
查看LEFT JOIN方式的执行计划:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: m
partitions: NULL
type: index
possible_keys: NULL
key: idx_id_name_type
key_len: 119
ref: NULL
rows: 578436
filtered: 100.00
Extra: Using index
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: a
partitions: NULL
type: eq_ref
possible_keys: idx_id_name_type
key: idx_id_name_type
key_len: 119
ref: cmdb.m.resource_id,cmdb.m.monitor_name,cmdb.m.resource_type
rows: 1
filtered: 100.00
Extra: Using where; Not exists; Using index
使用SQL PROFILE查看NOT EXISTS 执行过程:
+--------------------+----------+----------+------------+-------------------+---------------------+--------------+---------------+
| Status | Duration | CPU_user | CPU_system | Context_voluntary | Context_involuntary | Block_ops_in | Block_ops_out |
+--------------------+----------+----------+------------+-------------------+---------------------+--------------+---------------+
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000022 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000028 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000022 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000029 | 0.001000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000022 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000027 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000028 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000026 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000025 | 0.000000 | 0.000999 | 0 | 0 | 0 | 0 |
| Sending data | 0.000031 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000028 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000027 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000027 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000027 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000027 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000027 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000027 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000027 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000028 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000027 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000027 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000022 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000027 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000027 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000023 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 0.000033 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| end | 0.000024 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| query end | 0.000028 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| closing tables | 0.000027 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| freeing items | 0.000039 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| logging slow query | 0.000059 | 0.000000 | 0.000000 | 0 | 0 | 0 | 16 |
| cleaning up | 0.000033 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
+--------------------+----------+----------+------------+-------------------+---------------------+--------------+---------------+
使用SQL PROFILE查看LEFT JOIN 执行过程:
+----------------------+----------+----------+------------+-------------------+---------------------+--------------+---------------+
| Status | Duration | CPU_user | CPU_system | Context_voluntary | Context_involuntary | Block_ops_in | Block_ops_out |
+----------------------+----------+----------+------------+-------------------+---------------------+--------------+---------------+
| starting | 0.000162 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| checking permissions | 0.000025 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| checking permissions | 0.000025 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Opening tables | 0.000033 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| init | 0.000049 | 0.001000 | 0.000000 | 0 | 0 | 0 | 0 |
| System lock | 0.000030 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| optimizing | 0.000033 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| statistics | 0.000050 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| preparing | 0.000037 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| executing | 0.000025 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| Sending data | 1.200899 | 1.547764 | 0.124981 | 7460 | 116 | 0 | 8608 |
| end | 0.000103 | 0.000000 | 0.000000 | 2 | 0 | 0 | 0 |
| query end | 0.000028 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| closing tables | 0.000028 | 0.000000 | 0.000000 | 0 | 0 | 0 | 0 |
| freeing items | 0.000039 | 0.000000 | 0.000000 | 2 | 0 | 0 | 8 |
| logging slow query | 0.000052 | 0.000000 | 0.000000 | 0 | 0 | 0 | 24 |
| cleaning up | 0.000030 | 0.000000 | 0.000000 | 1 | 0 | 0 | 0 |
+----------------------+----------+----------+------------+-------------------+---------------------+--------------+---------------+
两种执行方式对比:
1、从执行计划来看,两个表都使用了索引,区别在于NOT EXISTS使用“DEPENDENT SUBQUERY”方式,而LEFT JOIN使用普通表关联的方式
2、从执行过程来看,LEFT JOIN方式主要消耗Sending data的上,在NOT EXISTS方式主要消耗在"executing"和“Sending data”两项上,受限于PROFILE只能记录100行结果,因此超过57万个"executing"和“Sending data”的组合项没有显示,虽然每次"executing"和“Sending data”的组合项消耗时间较少(约50毫秒),但由于执行次数较高,导致最终执行时间较长(50μs*578436=28921800us=28.92s)
如何在NOT EXISTS和LEFT JOIN中选择:
1、当外层数据较少时,子查询循环次数较少,使用NOT EXISTS并不会导致严重的性能问题,推荐使用NOT EXISTS方式。
2、当外层数据较大时,子查询消耗随外层数据量递增,查询性能较差,推荐使用LEFT JOIN方式
总结:
按照存在即合理是客观唯心主义的理论,NOT EXISTS以更直观地方式实现业务需求,在SQL复杂度上要远低于LEFT JOIN,且在生产执行计划时,NOT EXISTS方式相对更稳定些,LEFT JOIN可能会随统计信息变化而生产不同的执行计划。
MySQL优化--NOT EXISTS和LEFT JOIN方式差异的更多相关文章
- 0104探究MySQL优化器对索引和JOIN顺序的选择
转自http://www.jb51.net/article/67007.htm,感谢博主 本文通过一个案例来看看MySQL优化器如何选择索引和JOIN顺序.表结构和数据准备参考本文最后部分" ...
- 性能优化之mysql优化——慢查日志的开启方式和存储
-- MySQL优化 -- mysql 慢查日志的开启方式和存储 -- 1) 查看mysql是否开启慢查询日志 SHOW VARIABLES LIKE 'slow_query_log'; -- 2) ...
- sql优化 表连接join方式
sql优化核心 是数据库中 解析器+优化器的工作,我觉得主要有以下几个大方面:1>扫表的方法(索引非索引.主键非主键.书签查.索引下推)2>关联表的方法(三种),关键是内存如何利用 ...
- 如何干涉MySQL优化器使用hash join
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. GreatSQL是MySQL的国产分支版本,使用上与MySQL一致. 前言 实验 总结 前言 数据库的优化器相当于人类的大 ...
- SQL优化--使用 EXISTS 代替 IN 和 inner join来选择正确的执行计划
在使用Exists时,如果能正确使用,有时会提高查询速度: 1,使用Exists代替inner join 2,使用Exists代替 in 1,使用Exists代替inner join例子: 在一般写s ...
- MySQL优化—工欲善其事,必先利其器之EXPLAIN(转)
最近慢慢接触MySQL,了解如何优化它也迫在眉睫了,话说工欲善其事,必先利其器.最近我就打算了解下几个优化MySQL中经常用到的工具.今天就简单介绍下EXPLAIN. 内容导航 id select_t ...
- MySQL优化—工欲善其事,必先利其器之EXPLAIN
最近慢慢接触MySQL,了解如何优化它也迫在眉睫了,话说工欲善其事,必先利其器.最近我就打算了解下几个优化MySQL中经常用到的工具.今天就简单介绍下EXPLAIN. 内容导航 id select_t ...
- mysql优化sql语句的方法
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索 ...
- 项目中常用的19条MySQL优化
声明一下:下面的优化方案都是基于 " Mysql-索引-BTree类型 " 的 一.EXPLAIN 做MySQL优化,我们要善用 EXPLAIN 查看SQL执行计划. 下面来个简单 ...
随机推荐
- ARCore中根据屏幕坐标计算射线的算法
ARCore中提供了根据屏幕坐标.视口大小及view. project矩阵计算从屏幕坐标发射一条射线的方法,此方法用于3D拾取. class Ray { public final Vector3f o ...
- kudu导入文件(基于impala)
kudu是cloudera开源的运行在hadoop平台上的列式存储系统,拥有Hadoop生态系统应用的常见技术特性,运行在一般的商用硬件上,支持水平扩展,高可用,集成impala后,支持标准sql语句 ...
- __iter__ 和 __next__
class F: def __init__(self,x): self.x = x def __iter__(self): #把对象 变成可迭代对象 return self def __next__( ...
- JavaScript倒计时实现
/** * 倒计时函数 * @param {String}} endTime 终止时间戳 */ const countDown = (endTime, callback) => { const ...
- python+appium-desktop:安卓(android)7.0以上使用appium无法定位元素(无法refresh)且 无法运行脚本
--解决方法: 启动appium时配置中添加: "automationName":"uiautomator2" --扩展: 想支持安卓7.0及以上版本需要满足一 ...
- laravel不能读取session
Laravel用redis存储session,论坛有讨论说关于session无法保存的问题:https://laravel-china.org/topics/13510/points-to-be-pa ...
- RTTI和反射小结
Java有两种方式让我们在运行时识别对象和类的信息:1.“传统的”RTTI,假定所有的类型编译时已知:2.“反射”机制,允许在运行时发现和使用类的信息. 一.RTTI RTTI(Run-Time Ty ...
- Android Studio2.0 教程从入门到精通Windows版 - 提高篇
第二篇我们开发了一个Hello World应用,并介绍Android Sutdio的界面和如何调试应用,接下来将介绍一些常用的快捷键和必备插件. 常用快捷键 代码跳转 描述:跳转是为了方便代码位置的定 ...
- WordConut
一.代码地址:https://gitee.com/cainiaoY/WordCount 二.代码: import java.io.*; import java.util.regex.*; public ...
- springboot寻找property的顺序
Spring Boot uses a very particular PropertySource order that is designed to allow sensible overridin ...