POSTGRESQL SQL 执行用 IN 还是 EXISTS 还是 ANY

dbda15f4b34e39a9d59e60643a84cd65.png

开头还是介绍一下群,如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系 liuaustin3 ,在新加的朋友会分到3群(共950人左右 1 + 2 + 3)

POSTGRESQL SQL 查询中经常用到的一些查询使用的查询符号,如 in , exists ,any ,这些查询符号在使用中有什么性能方面的差距,以及在什么场景下适合使用,这应该是一个有意思的话题。

IN  EXISTS ANY ,三个条件操作符,分别带有不同的目的

虽然IN 和 EXISTS 本身都是从一个结果集合匹配另一个结果集合中包含相关的数据的问题,但是两个操作符号,对应的操作方法是不同的。

IN 是将外表当做一个结果集,将内表和外表进行一个笛卡尔积,所以如果内表比较小的话,则对于计算的速度是有利的。

c4123d56e7addd3cea60c93bf9b48e68.png

EXISTS 本身是循环外表,简则内表的行是否在外表中存在

我们下面先入为主的用三查询来说明

select sum(pay.amount),sta.staff_id

from payment as pay

left join staff as sta on pay.staff_id = sta.staff_id

left join (select rental_date,rental_id from rental where rental_date > '2000-09-08') as ren on pay.rental_id = ren.rental_id

group by sta.staff_id;

select sum(pay.amount),sta.staff_id

from staff as sta 

left join (

select pay_z.amount,pay_z.staff_id

from payment as pay_z where exists (select * from rental as ren where pay_z.rental_id = ren.rental_id and rental_date > '2000-09-08')) as 

pay on pay.staff_id = sta.staff_id

group by sta.staff_id;

select sum(pay.amount),pay.staff_id from 

(select pay.amount,pay.staff_id,pay.rental_id

from payment as pay where pay.staff_id in (select staff_id from staff)) as pay

left join rental as ren on ren.rental_id = pay.rental_id 

where ren.rental_date > '2000-09-08'

group by pay.staff_id;

相关查询已经有预热了查询,所以不存在第一次查询的时间的差异

3c4015bbd8be7137b3cf7cb0ce1e26e6.png

三个查询的方式 一样的查询结果,这里第一个查询时间最快,但查看执行计划,发现一个问题,虽然查询里面的rental 表并用时间进行了控制,但是在查询计划中并未有相关的表出现。经过分析在rental 表中的最早有时间的rental_date 是在 2005年5月24日所以这个条件相对于整体的SQL 是一个完全包含的结果,通过统计信息的分析,在这条SQL 里面并未涉及  rental 表与整体数据的关联。

left join (select rental_date,rental_id from rental where rental_date > '2005-09-08') as ren on pay.rental_id = ren.rental_id

af112b3961b5bf57e2c659d5e5613bcc.png

ae378f16c58d0716f9d4ea65a1071bdd.png

第二种方式,在查询中使用了exists 的方式,这里由于操作方式的变化,根据语句的逻辑整体还是先根据rental_date时间的条件进行过滤然后通过merge 的方式将 payment 表和 rental表进行条件的匹配,并且对于payment 的staff_id进行了排序,然后在和排序的 staff表进行了merge 最后产出的结果。

05c69f43a04fce7982d3464a6cd3a01c.png

第三种 查询将 EXISTS 替换成 IN 操作,这里的操作明显复杂于 EXISTS ,在rental 和payments 两个表进行merge后,在进行排序然后在对STAFF 表进行排序在对 STAFF 和结果集进行MERGE

17c2a4fe93c85e0420ae66b93cd80a2a.png

三个语句最终,还是不通过exists 和in 采用单纯的JOIN的方式的语句速度要快,因为他抛弃了rental 表的操作, 而无论采用EXISTS 或 IN 两个执行的过程是类似的,COST的值也是一样的,但是后者有极小的差异,EXISTS 占优。

在POSTGRESQL 还有一个运算操作 ANY ,通过ANY 也可以进行类似 EXISTS 或 IN 通过类似的方式进行,但不同的是 ANY 的操作余地比其他的方案要多,非等值的计算也可以通过ANY来进行。

0b64922f0eed7e9c500303705555b2ee.png

其中查询时间类似EXISTS 的查询时间。

那么下面我们变换一下查询的逻辑将等值的运算变为非等值的运算,看看这样三种方式还是否在查询时间上类似。

a7f3cf157bda3c0a69878c409580d507.png

在我们变换了查询的逻辑,将staff_id 等于1的排除在外后,查询的效率里面排名  not in 为速度最快, not exists 排名第二  , any的速度与 not exists 类似。

select sum(pay.amount),sta.staff_id

from staff as sta 

inner join (

select pay_z.amount,pay_z.staff_id

from payment as pay_z where not exists (select * from rental as ren where pay_z.rental_id = ren.rental_id and rental_date > '2000-09-08' and pay_z.staff_id = 1)) as 

pay on pay.staff_id = sta.staff_id 

group by sta.staff_id;

select sum(pay.amount),pay.staff_id from 

(select pay.amount,pay.staff_id,pay.rental_id

from payment as pay where pay.staff_id not in (select staff_id from staff where staff_id = 1)) as pay

left join rental as ren on ren.rental_id = pay.rental_id 

where ren.rental_date > '2000-09-08'

group by pay.staff_id;

select sum(pay.amount),pay.staff_id from 

(select pay.amount,pay.staff_id,pay.rental_id

from payment as pay where pay.staff_id > any (select staff_id from staff where staff_id = 1)) as pay

left join rental as ren on ren.rental_id = pay.rental_id 

where ren.rental_date > '2000-09-08'

group by pay.staff_id;

但是这里要说明,not exists 的语句变动最大,从原来的LEFT JOIN 变为了 INNER JOIN 而从人操作的逻辑来看 any 是从思维的角度最容易理解的语句的撰写的方式。

当然这里数据量不一样的情况下,可能NOT IN 就不会占据优势。

总结:

如果你想要排除一组值,NOT IN 通常是一个简单和直观的选择。

如果你想要比较一个值与子查询的结果集中的任何值,ANY 是一种常用的方法。

如果你只是想确定子查询是否返回结果,并且不关心具体的匹配记录,NOT EXISTS 是一个适当的选择。

三种数据的处理方式中,根据数据量和表前后的关系,可以在性能差的时候进行一些语句查询方式的变更,看看是否可以提高相关的语句查询的效率。但根据上面的案例,如果可以直接使用 JOIN ,那么还是直接使用JOIN 的方式在部分情况下,更快。

acf8505045c50342ba86bfd2cd2b4db0.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/34515.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【youcans动手学模型】MobileNet 模型-CIFAR10图像分类

欢迎关注『youcans动手学模型』系列 本专栏内容和资源同步到 GitHub/youcans 【youcans动手学模型】MobileNet 模型-CIFAR10图像分类 1. MobileNet 卷积神经网络模型1.1 模型简介1.2 论文介绍 2. 在 PyTorch 中定义 MobileNet V1 模型类2.1 深度可分离卷积(DSC&…

转换流~~

乱码如何解决: 使用字符输入转换流可以提取文件(GBK)的原始字节流,原始字节不会存在问题然后把字节流以指定编码转换成字符输入流,这样字符输入流中的字符就不乱码了 1:字符输入转换流 字符转换输入流&a…

uni-App踩坑记录

​ 1、uni自己封装的axios在真机中失效,发不出请求 uniapp中使用axios 需要配置适配器 (添加适配器有点费劲,直接封装uni自带请求也可以) axios-adapter-uniapp传送门 axios.defaults.adapter function(config) { //自己定义个适配器,用来…

2023年生猪行业研究报告

第一章 行业概况 生猪是指猪类动物中未经加工的、原始的、活体的猪,通常是指用于肉类生产的猪。生猪在全球范围内都是主要的肉类来源之一。它们的肉质丰富,营养价值高,同时还能用来制作各种加工肉类产品,如火腿、香肠等。 生猪养…

AR试穿试戴相关SDK或平台

1.火山引擎 链接 咨询过平台收费比较高几十万一年而且还是起步价 2.Geenee 链接 geenee在衣服、裤子、头饰以及鞋子方面可以实现试穿。 3.Wanna 链接 Wanna 试衣、试包、试鞋及手表都可以,我试过鞋子的试穿效果还不错 4.DeepAR …

nginx进行反向代理

Nginx是一个开源的高性能Web服务器和反向代理服务器。它最初是由Igor Sysoev在2004年开发的,现在由一个全球性的社区维护和支持。 Nginx的主要特点包括: 高性能:Nginx使用事件驱动模型,可以处理高并发请求,具有出色的…

信息服务上线渗透检测网络安全检查报告和解决方案4(网站风险等级评定标准、漏洞危害分级标准、漏洞安全建议)

系列文章目录 信息服务上线渗透检测网络安全检查报告和解决方案3(系统漏洞扫描、相对路径覆盖RPO漏洞、nginx漏洞修复)信息服务上线渗透检测网络安全检查报告和解决方案2(安装文件信息泄漏、管理路径泄漏、XSS漏洞、弱口令、逻辑漏洞、终极上传漏洞升级)信息服务上线渗透检测网…

常微分方程(ODE)求解方法总结(续)

常微分方程(ODE)求解方法总结(续) 1 隐式方法2 多步法2.1 二阶方法2.1.1 非自启动修恩方法2.2 开型和闭型积分公式2.3 高阶多步法 1 隐式方法 常微分方程(ODE)求解方法总结 里面介绍了我称为“正常思路”的…

C/C++的发展历程和未来趋势

文章目录 C/C的起源C/C的应用C/C开发的工具C/C未来趋势 C/C的起源 C语言 C语言是一种通用的高级编程语言,由美国计算机科学家Dennis Ritchie在20世纪70年代初期开发出来。起初,C语言是作为操作系统UNIX的开发语言而创建的。C语言的设计目标是提供一种功…

Transformer时间序列:PatchTST引领时间序列预测进

Transformer时间序列:PatchTST引领时间序列预测进 引言为什么transformer框架可以应用到时间序列呢统计学模型深度学习模型 PatchTSTPatchTST模型架构原理。通道独立性Patchingpatching的优点Transformer编码器 利用表示学习改进PatchTST使用PatchTST模型进行预测初…

【RabbitMQ】

一、概念 MQ(消息队列):是指在消息传送过程中保存消息的容器,用于分布式系统之间的通信 生产者:是发送消息的用户应用程序。 队列:是存储消息的缓冲区。 消费者:是接收消息的用户应用程序。 1…

(嵌入式)STM32G061C8T6、STM32G061C6T6、STM32G061C8U6 64MHz 64KB/32KB 闪存(MCU)

STM32G0 32位微控制器 (MCU) 适合用于消费、工业和家电领域的应用,并可随时用于物联网 (IoT) 解决方案。这些微控制器具有很高的集成度,基于高性能ARM Cortex-M0 32位RISC内核,工作频率高达64MHz。该器件包含内存保护单元 (MPU)、高速嵌入式内…

mysql 视图

视图,是虚拟存在的表,视图中的数据在数据库中实际不存在,视图只保存查询SQL的逻辑,不保存查询结果 建表sql DROP TABLE IF EXISTS w_dict; CREATE TABLE w_dict (id int(0) NOT NULL AUTO_INCREMENT,label varchar(255) CHARACT…

go开源项目slgserver源码分析

个人博客地址: https://cxx001.gitee.io 前言 项目开源地址:https://github.com/llr104/slgserver 比较适合作为go语言入门学习项目或轻量级游戏项目,整体的项目结构和编码质量还是可以的。不过距离商业项目还是差点意思,如服务负载、容灾这…

弗迪科技携手纷享销客共建CRM系统,数智化升级加速“灯塔工厂”征程

当前,全球新一轮科技革命正和产业升级融合发展,数字化技术成为各行各业升级发展的重要推动力。 自2018年起,世界经济论坛与麦肯锡咨询公司发起“灯塔工厂”项目,全球严选制造业数字化转型典范作为“数字化制造”和“全球化4.0”的…

360测试开发技术面试题目

目录 一、java方面 二、Linux方面 三、数据库方面 四、性能测试方面 五、HTTP协议方面 六、其他 总结: 最近面试了360测试开发的职位,将面试题整理出来分享~ 一、java方面 1、java重载和重写的区别 重载overloading 多个方法、相同的名字&#x…

Nginx负载均衡、虚拟主机

目录 常用的6种负载均衡算法 轮询算法(round robin)默认 权重(weight) 响应时间(fair) 连接数(least_conn) IP_hash url_hash(第三方) 开发优选:一致性哈希 安装步骤: 虚拟主机 常用的6种负载均衡算法 轮询算法(round robin)默认 轮询方式&a…

C#扩展——Visual Studio 代码提示/智能提示字体大小更改方法.

声明:本文为个人笔记,用于学习研究使用非商用,内容为个人研究及综合整理所得,若有违规,请联系,违规必改。 C#扩展——Visual Studio 代码提示/智能提示字体大小更改方法. 文章目录 C#扩展——Visual Studio…

stm32或gd32移植libcanard实现UAVCAN协议

一、源码下载 1、git下载 点击我下载 2、csdn下载 自己上传的点击下载 二、源码移植 我自己是使用rt-thread操作系统移植的。但是不局限与操作系统,裸机也可以。 1、首先将源码加入到工程 2、分别实现一个内存的分配与释放函数,他是一个指针函数&…

基于预测帧的视频异常检测经典论文

16年上海科技的论文,上海科技做这个方向的系大佬多多的。 摘要 受基于稀疏编码的异常检测能力的激励,我们提出了一种时间相干稀疏编码(TSC),其中我们强制用相似的重构系数对相似的相邻帧进行编码。然后,我们用一种特殊类型的层叠…
最新文章