在我们平时写SQL时,如果遇到需要排除某些数据时,往往使用id <> xxx and id <> xxx,进而改进为id not in (xxx, xxx);

这样写没有问题,而且简化了SQL,但是往往有些极端情况,使用not in就会造成极大的性能损耗,例如:

select * from test where id not in (select id from test_back) and info like '%test%';

这样的话select id from test_back将成为一个子查询,而且不会走索引,每次走一遍全表扫描。

每一条满足info like '%test%'的记录都会去调用这个方法去判断id是否不在子查询中,具体的执行计划见下面的例子。

改进方法:

1)使用test和test_back进行联合查询,id <> id明显是不行的,这样只会判断同一关联条件下的一行中的id是否相同,无法做到排除某些id。

2)正确的方式应该使用not exists,将条件下推到里面,就不会出现子查询了:

select * from test  t1 where info like '%test%' and not exits (select 1 from test_back t2 where t2.id = t1.id);

apple=# \d test
Table "public.test"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
id | integer | | not null |
info | text | | |
Indexes:
"test_pkey" PRIMARY KEY, btree (id) apple=# truncate test;
TRUNCATE TABLE
apple=# insert into test select generate_series(1, 100), 'test'||round(random()*10000)::text;
INSERT 0 100
apple=# select * from test limit 1;
id | info
----+----------
1 | test9526
(1 row) apple=# insert into test select generate_series(101, 200), 'tes'||round(random()*10000)::text;
INSERT 0 100
apple=# create table test_back as select * from test where id between 50 and 70;
SELECT 21
apple=# explain select * from test where id not in (select id from test_back) and info like '%test%';
QUERY PLAN
---------------------------------------------------------------------
Seq Scan on test (cost=25.88..30.88 rows=49 width=12)
Filter: ((NOT (hashed SubPlan 1)) AND (info ~~ '%test%'::text))
SubPlan 1
-> Seq Scan on test_back (cost=0.00..22.70 rows=1270 width=4)
(4 rows)
apple=# explain select * from test t1 where info like '%test%' and not exists (select 1 from test_back t2 where t2.id = t1.id);
QUERY PLAN
-------------------------------------------------------------------------
Hash Anti Join (cost=1.47..7.13 rows=89 width=12)
Hash Cond: (t1.id = t2.id)
-> Seq Scan on test t1 (cost=0.00..4.50 rows=99 width=12)
Filter: (info ~~ '%test%'::text)
-> Hash (cost=1.21..1.21 rows=21 width=4)
-> Seq Scan on test_back t2 (cost=0.00..1.21 rows=21 width=4)
(6 rows)

例子里面没有建索引,建索引后,这种优化方式效果更好。

那么进一步扩展来说:

1)!= 不是标准的SQL,<>才是,这两个在PostgreSQL中是等效的。

2)exits和not exits的意思是逐条将条件下放到判断条件,而jion方式是先对表进行笛卡尔积,然后判断同行之间的各列值是否满足关系。

PostgreSQL SQL优化之NOT IN问题的更多相关文章

  1. SQL优化技巧

    我们开发的大部分软件,其基本业务流程都是:采集数据→将数据存储到数据库中→根据业务需求查询相应数据→对数据进行处理→传给前台展示.对整个流程进行分析,可以发现软件大部分的操作时间消耗都花在了数据库相关 ...

  2. 《高性能SQL调优精要与案例解析》一书谈主流关系库SQL调优(SQL TUNING或SQL优化)核心机制之——索引(index)

    继<高性能SQL调优精要与案例解析>一书谈SQL调优(SQL TUNING或SQL优化),我们今天就谈谈各主流关系库中,占据SQL调优技术和工作半壁江山的.最重要的核心机制之一——索引(i ...

  3. SQL优化案例—— RowNumber分页

    将业务语句翻译成SQL语句不仅是一门技术,还是一门艺术. 下面拿我们程序开发工程师最常用的ROW_NUMBER()分页作为一个典型案例来说明. 先来看看我们最常见的分页的样子: WITH CTE AS ...

  4. sql 优化

    1.选择最有效率的表名顺序(只在基于规则的优化器中有效): oracle的解析器按照从右到左的顺序处理 from 子句中的表名,from子句中写在最后的表(基础表driving table)将被最先处 ...

  5. SQL 优化总结

    SQL 优化总结 (一)SQL Server 关键的内置表.视图 1. sysobjects         SELECT name as '函数名称',xtype as XType  FROM  s ...

  6. (转)SQL 优化原则

    一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用 系统提交实际应用后,随着数据库中数据的增加,系 ...

  7. sql优化阶段性总结以及反思

    Sql优化思路阶段性心得: 这段时间的优化做了好几个案例,其实有很多的类似点,都是好几张大表的相互连接,然后执行长达好几个小时,甚至都跑不出来. 自己差不多的思路就是Parallel full tab ...

  8. mysql sql优化实例

    mysql sql优化实例 优化前: pt-query-degist分析结果: # Query 3: 0.00 QPS, 0.00x concurrency, ID 0xDC6E62FA021C85B ...

  9. ORACLE常用SQL优化hint语句

    在SQL语句优化过程中,我们经常会用到hint,现总结一下在SQL优化过程中常见Oracle HINT的用法: 1. /*+ALL_ROWS*/ 表明对语句块选择基于开销的优化方法,并获得最佳吞吐量, ...

随机推荐

  1. 2018第九届蓝桥杯C/C++ A组试题答案参考

    题目1 标题:分数 1/1 + 1/2 + 1/4 + 1/8 + 1/16 + .... 每项是前一项的一半,如果一共有20项,求这个和是多少,结果用分数表示出来.类似:3/2当然,这只是加了前2项 ...

  2. TTTTTTTTTTTTTT hdu 5763 Another Meaning 哈希+dp

    Another Meaning Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  3. BZOJ 3531 [Sdoi2014]旅行 树链剖分+动态开点线段树

    题意 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我们用 ...

  4. 基于node、webpack、搭建一个koa服务器

    1.首先需要node(去官网下载) 2.见一个文件夹  比如koa          cmd——r       cd  koa文件 3.npm init 4.安装webpack       (本地安装 ...

  5. Spring——代理工厂实现增强

    借助Spring IOC的机制,为ProxyFactory代理工厂的属性实现依赖注入,这样做的优点是可配置型高,易用性好. 1.创建抽象主题 public interface ProService { ...

  6. Charles中文破解版下载安装及使用教程

    下载地址:https://pan.baidu.com/s/1praYZAw23psZLi59hKJjqw 一. 简介及安装 Charles 是在 PC 端常用的网络封包截取工具,但它不仅仅能在pc端使 ...

  7. Java Jsch SFTP 递归下载文件夹

    Java Program For Downloading Folder Content recursively from SFTP Server How to download folder from ...

  8. linux读xml文件问题

    由于从配置文件中读取到的路径名的最后多了个0x0A,害我折腾了半天. 提示也很奇葩: I/O warning : failed to load external entity 关键是从这个提示看不出是 ...

  9. LC 672. Bulb Switcher II

    There is a room with n lights which are turned on initially and 4 buttons on the wall. After perform ...

  10. YJango的卷积神经网络——介绍

    原文地址:https://zhuanlan.zhihu.com/p/27642620 如果要提出一个新的神经网络结构,首先就需要引入像循环神经网络中“时间共享”这样的先验知识,降低学习所需要的训练数据 ...