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.hqwc.cn/news/8816.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL频率低但笔试会遇到: 触发器、索引、外键约束

一. 前言 在SQL面笔试中,对于表的连接方式,过滤条件,窗口函数等肯定是考察的重中之重,但是有一些偶尔会出现,频率比较低但是至少几乎会遇见一两次的题目,就比如触发器,索引和外键约束&#xff0…

Spring源码解析(二):bean容器的创建、默认后置处理器、扫描包路径bean

Spring源码系列文章 Spring源码解析(一):环境搭建 Spring源码解析(二): 目录 一、Spring源码基础组件1、bean定义接口体系2、bean工厂接口体系3、ApplicationContext上下文体系 二、AnnotationConfigApplicationContext注解容器1、创建bean工厂-beanFa…

【Nginx05】Nginx学习:HTTP核心模块(二)Server

Nginx学习:HTTP核心模块(二)Server 第一个重要的子模块就是这个 Server 相关的模块。Server 代表服务的意思,其实就是这个 Nginx 的 HTTP 服务端所能提供的服务。或者更直白点说,就是虚拟主机的配置。通过 Server &…

iview切换Select时选项丢失,重置Seletc时选项丢失

分析原因 在旧版本的iview中如果和filterable一起使用时,当值清空选项或者使用重置按钮清空时选项会丢失。 解决方式一 把去掉filterable 解决方式二 使用ref,调用clearSingleSelect()方法清空 ref"perfSelect" this.$refs.perfSelect.c…

Java链式编程

一、链式编程 1.1.释义 链式编程,也叫级联式编程,调用对象的函数时返回一个this对象指向对象本身,达到链式效果,可以级联调用。 1.2.特点 可以通过一个方法调用多个方法,将多个方法调用链接起来,形成一…

UE4中创建的瞄准偏移或者混合空间无法拖入动画

UE4系列文章目录 文章目录 UE4系列文章目录前言一、解决办法 前言 UE4 AimOffset(瞄准偏移)动画融合时,AimOffse动画拖入不了融合框的解决办法,你会发现动画无法拖入到融合框,ue4编辑器提示“Invalid Additive animation Type”,…

C#核心知识回顾——10.List、Dictionary、数据结构

1.List List<int> list new List<int>(); List<String> strings new List<String>();//增list.Add(0);list.Add(1);List<int> ints new List<int>();ints.Add(0);list.AddRange(ints);//插入list.Insert(0, 1);// 位置0插入1//删//1.移…

使用GPIO来模拟UART

前言 最近在看一些秋招的笔试和面试题&#xff0c;刚好看到一个老哥的经验贴&#xff0c;他面试的时候被问到了如果芯片串口资源不够了该怎么办&#xff1f;其实可以用IO口来模拟串口&#xff0c;但我之前也没有具体用代码实现过&#xff0c;借此机会用32开发板上的两个IO口来…

从0开始,手写MySQL数据管理器DM

说在前面 从0开始&#xff0c;手写一个MySQL的学习价值在于&#xff1a; 可以深入地理解MySQL的内部机制和原理&#xff0c;MySQL可谓是面试的绝对重点和难点&#xff0c; 尼恩曾经指导过的一个7年经验小伙&#xff0c;凭借精通MySQL 搞定月薪40K。 从而更好地掌握MySQL的使…

前端实现pdf,图片,word文件预览

前端实现文件预览功能 需求&#xff1a;实现一个在线预览pdf、excel、word、图片等文件的功能。 介绍&#xff1a;支持pdf、xlsx、docx、jpg、png、jpeg。 以下使用Vue3代码实现所有功能&#xff0c;建议以下的预览文件标签可以在外层包裹一层弹窗。 图片预览 iframe标签能够将…

Vue3 JSX 插槽、v-model 的用法以及 React JSX 的区别

前言 写这篇文章的初衷是&#xff0c;Vue3 JSX 部分与 React JSX 容易混淆&#xff0c;比如如本文所说的 slot & v-model&#xff0c; 如果你是第一次接触 JSX&#xff0c;可先阅读前面写过的 React & JSX 日常用法与基本原则 来对 JSX 有一个整体的认知以及比较两者间…

架构重构|性能和扩展性大幅提升的Share Creators智能数字资产管理软件3.0

作为数字资产管理行业的领军者&#xff0c;Share Creators智能数字资产管理软件持续致力于帮助企业和团队智能化管理数字资产&#xff0c;提升工业化管线制作效率。经过本次重构&#xff0c;Share Creators 3.0版本重装上阵&#xff0c;全面更新的服务架构标志着软件整体性能的…