postgresql对EXISTS类型查询优化

关系准备:

CREATE TABLE t_1(
	t_1_id INT UNIQUE,
	t_1_col_1 INT,
	t_1_col_2 VARCHAR(10));

CREATE TABLE t_2(
	t_2_id INT UNIQUE,
	t_2_col_1 INT,
	t_2_col_2 VARCHAR(10));

数据准备:

INSERT INTO t_1 VALUES(1,11,'t_1_1');
INSERT INTO t_1 VALUES(2,12,NULL);
INSERT INTO t_1 VALUES(3,NULL,'t_1_3');
INSERT INTO t_1 VALUES(4,14,'t_1_4');
INSERT INTO t_1 VALUES(5,15,NULL);
INSERT INTO t_1 VALUES(7,NULL,NULL);
INSERT INTO t_2 VALUES(1,11,'t_2_1');
INSERT INTO t_2 VALUES(2,NULL,'t_2_2');
INSERT INTO t_2 VALUES(3,13,NULL);
INSERT INTO t_2 VALUES(4,14,'t_2_4');
INSERT INTO t_2 VALUES(6,16,'t_2_6');
INSERT INTO t_2 VALUES(7,NULL,NULL);
SQL准备:

//EXISTS类型的普通相关子查询,子查询条件和父查询相关联:
(4).SELECT t_1.* FROM t_1 WHERE EXISTS(SELECT t_2_id FROM t_2 WHERE t_1_id=t_2_id);
//EXISTS类型的普通子相关子查询,子查询条件和子查询没有关系:
(5).SELECT t_1.* FROM t_1 WHERE EXISTS(SELECT t_2_id FROM t_2 WHERE t_1_id=10);
//EXISTS类型的普通非相关子查询
(6).SELECT t_1.* FROM t_1 WHERE EXISTS(SELECT t_2_id FROM t_2 WHERE t_2_id=10);
//EXISTS类型的普通非相关子查询,子查询简单没有表存在;
(7).SELECT t_1.* FROM t_1 WHERE EXISTS(SELECT 10);

测试1:

uu=# EXPLAIN SELECT t_1.* FROM t_1 WHERE EXISTS(SELECT t_2_id FROM t_2 WHERE t_1_id=t_2_id);
                            QUERY PLAN                             
-------------------------------------------------------------------
 Hash Semi Join  (cost=34.08..69.49 rows=1070 width=46)
   Hash Cond: (t_1.t_1_id = t_2.t_2_id)
   ->  Seq Scan on t_1  (cost=0.00..20.70 rows=1070 width=46)
   ->  Hash  (cost=20.70..20.70 rows=1070 width=4)
         ->  Seq Scan on t_2  (cost=0.00..20.70 rows=1070 width=4)
(5 rows)

        查询优化器对查询进行了查询重写,通过子查询上拉技术,把子查询转换为使用t_1.t_1_id = t_2.t_2_id作为连接条件实现hash半连接(hash semi join)操作。如果不做优化,则t_1表有多少条记录,都需要扫描t_2表多少次,每次都对t_2做全表扫描,这样的操作是非常昂贵的操作;优化后,只需对t_2进行一次全表扫描,这样大大节省了成本值,然后采用 Hash Semi Join 连接算法。


测试2:

uu=# EXPLAIN SELECT t_1.* FROM t_1 WHERE EXISTS(SELECT t_2_id FROM t_2 WHERE t_1_id=10);
                                   QUERY PLAN                                    
---------------------------------------------------------------------------------
 Nested Loop Semi Join  (cost=0.00..28.99 rows=1 width=46)
   ->  Index Scan using t_1_t_1_id_key on t_1  (cost=0.00..8.27 rows=1 width=46)
         Index Cond: (t_1_id = 10)
   ->  Seq Scan on t_2  (cost=0.00..20.70 rows=1070 width=0)
(4 rows)
        优化器对查询SQL语句进行了优化。通过子查询上拉技术,对子查询t_2做一个顺序扫描,然后通过索引方式访问t_1的索引,最后将t_1结果集与t_2结果集做嵌套循环半连接。


测试3:

uu=# EXPLAIN SELECT t_1.* FROM t_1 WHERE EXISTS(SELECT t_2_id FROM t_2 WHERE t_2_id=10);
                                      QUERY PLAN                                       
---------------------------------------------------------------------------------------
 Result  (cost=8.27..28.97 rows=1070 width=46)
   One-Time Filter: $0
   InitPlan 1 (returns $0)
     ->  Index Only Scan using t_2_t_2_id_key on t_2  (cost=0.00..8.27 rows=1 width=0)
           Index Cond: (t_2_id = 10)
   ->  Seq Scan on t_1  (cost=0.00..20.70 rows=1070 width=46)
(6 rows)
        由于该查询是非相关子查询,我们只需对表t_2做一次扫描,验证子查询结果是TRUE还是FALSE,所以不会执行多次,没有必要优化,按照SQL语句意思走即可。


测试4:

uu=# EXPLAIN SELECT t_1.* FROM t_1 WHERE EXISTS(SELECT 10);
                          QUERY PLAN                          
--------------------------------------------------------------
 Result  (cost=0.01..20.71 rows=1070 width=46)
   One-Time Filter: $0
   InitPlan 1 (returns $0)
     ->  Result  (cost=0.00..0.01 rows=1 width=0)
   ->  Seq Scan on t_1  (cost=0.00..20.70 rows=1070 width=46)
(5 rows)
      只需对子查询求解 TRUE还是FALSE即可。


PostgreSQL是以加州大学伯克利分校计算机系开发的POSTGRES,现在已经更名为PostgreSQL. PostgreSQL支持大部分SQL标准并且提供了许多其它现代特性:复杂查询、外键、触发器、视图、事务完整性等。 PostgreSQL 是一个免费的对象-关系数据库服务器(数据库管理系统),它在灵活的 BSD-风格许可证下发行。它提供了相对其他开放源代码数据库系统(比如 MySQL 和 Firebird),和专有系统(比如 Oracle、Sybase、IBM 的 DB2 和 Microsoft SQL Server)之外的另一种选择。 事实上, PostgreSQL 的特性覆盖了 SQL-2/SQL-92 和 SQL-3/SQL-99,首先,它包括了可以说是目前世界上最丰富的数据类型的支持,其中有些数据类型可以说连商业数据库都不具备, 比如 IP 类型和几何类型等;其次,PostgreSQL 是全功能的自由软件数据库,很长时间以来,PostgreSQL 是唯一支持事务、子查询、多版本并行控制系统(MVCC)、数据完整性检查等特性的唯一的一种自由软件的数据库管理系统。 Inprise 的 InterBase 以及SAP等厂商将其原先专有软件开放为自由软件之后才打破了这个唯一。最后,PostgreSQL拥有一支非常活跃的开发队伍,而且在许多黑客的努力下,PostgreSQL 的质量日益提高。从技术角度来讲,PostgreSQL 采用的是比较经典的C/S(client/server)结构,也就是一个客户端对应一个服务器端守护进程的模式,这个守护进程分析客户端来的查询请求,生成规划树,进行数据检索并最终把结果格式化输出后返回给客户端。为了便于客户端的程序的编写,由数据库服务器提供了统一的客户端 C 接口。而不同的客户端接口都是源自这个 C 接口,比如ODBC,JDBC,Python,Perl,Tcl,C/C++,ESQL等, 同时也要指出的是,PostgreSQL 对接口的支持也是非常丰富的,几乎支持所有类型数据库客户端接口。这一点也可以说是 PostgreSQL 一大优点。 本课程作为PostgreSQL数据库管理二,主要讲解以下内容:1.     PostgreSQL中的子查询2.     PostgreSQL公共表表达式3.     PostgreSQL数据的修改4.     PostgreSQL中的事务5.     PostgreSQL数据导入和导出6.     PostgreSQL数据库的管理7.     PostgreSQL表的管理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值