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执行计划. 下面来个简单 ...
随机推荐
- java中Class.getMethod方法
Method Class.getMethod(String name, Class<?>... parameterTypes)的作用是获得对象所声明的公开方法 该方法的第一个参数name是 ...
- tp5文件上传展示
//接收文件 $file = request()->file('image'); //将文件移动到框架应用根目录/public/uploads/ 目录下 $info = $file->mo ...
- JAVA结合testng断言verify(断言失败不中断继续执行)
原理: 1.自已构造一个断言类,把Assert.assertEquals给try catch住. 2.利用testng的监听类在测试方法运行结束后进行分析. 代码: 断言类: package com. ...
- Win7上安装scapy
1.环境 操作环境:win7 python版本:python3.5 依赖模块:Npcap(推荐)或WinPcap 下载scapy 2.安装步骤 操作环境,python及依赖模块安装省略(一直点击下一步 ...
- django mysql 数据库配置
在settings.py中保存了数据库的连接配置信息,Django默认初始配置使用sqlite数据库. DATABASES = { 'default': { 'ENGINE': 'django.db. ...
- GPL_LGPL
LGPL 与GPL的区别 GPL(GNU General Public License) 我们很熟悉的Linux就是采用了GPL.GPL协议和BSD, Apache Licence等鼓励代码重用的 ...
- Pay attention to "Changing"
data l_ct_imseg type vsep_t_imseg. refresh l_ct_imseg. append lines of ct_imseg to l_ct_imseg. call ...
- face_recognition 模块安装
https://blog.csdn.net/qq_15192373/article/details/78623741 https://blog.csdn.net/roguesir/article/de ...
- Windows7 VS2015 下编译 PythonQt3.2
本文在使用vs2015编译python3.6.7源代码后,编译的PythonQt3.2.如果使用python二进制文件进行安装,注意python的路径即可 本机环境: 1.win7 64 旗舰版 2. ...
- 探索未知种族之osg类生物---呼吸分解之渲染遍历二
那么今天我们就正式进入osg整个呼吸动作之中最复杂的一个动作,ViewerBase::renderingTraversals(),我们先介绍renderingTraversals的开头的简单的几步操作 ...