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 ...
- python 优先队列
python 优先队列 from queue import PriorityQueue q = PriorityQueue() q.put((2, 'code')) q.put((1, 'eat')) ...
- RGB颜色值转化为long 型数字
通常我们表达颜色都是使用RGB值表示的,今天在VB中设置RGB值居然是一个整形数字,网上各种搜资料发现这个数字是怎么来的: 数值= 65536*Blue + 256* Green + Red
- 吴裕雄 python深度学习与实践(8)
import cv2 import numpy as np img = cv2.imread("G:\\MyLearning\\TensorFlow_deep_learn\\data\\le ...
- vue 未完待续
1. v-text:主要用来更新textContent,可以等同于JS的text属性. <span v-text="msg"></span> 这两者等价: ...
- vivo手机,自带世界之窗浏览器,sessionStorage设置的值为null
最近遇到一个小问题 用vivo手机自带浏览器,每次跳转到一个新页面都是重新打开一个webpage,导致sessionStorage设置的值都没了. 所以开发移动端网页时,谨慎使用sessionStor ...
- linux 大容量磁盘分区工具parted
1. Msdos和Gpt的区别 fdisk :只能分msdos分区parted :可以分msdos和gpt分区 2. MSDOS特点最大支持2TB卷大小.每个磁盘最多只能有4个主分区(或3个主分区, ...
- java中的throw、throws和try catch浅析
今天在公司和同事聊天的时候,突然发现自己对java中的throw.throws和try catch的作用理解不够准确,在网上查了查,在此大概梳理一下. throw用于抛出异常,例如 throw new ...
- matplotlib坐标轴的一些操作
- PHP安装linux
PHP 7.1.26 安装 1. 下载安装包 例php-7.1.26.tar.gz 下载地址:http://cn2.php.net/downloads.php 2. 放入/root 3. 切换目录 # ...