PostgreSQL查询优化器--逻辑查询优化--子查询优化(二)

 

PostgreSQL支持的子查询优化技术

在第2章,探讨了子查询的优化技术,包括子查询合并、子查询反嵌套、聚集子查询消除三项技术。PostgreSQL只支持子查询反嵌套,其他两种不支持。参看如下示例。

首先我们先做一些前期的准备工作。

创建表结构和索引如下:

CREATE TABLE t1 (a1 INT, b1 INT);

CREATE TABLE t2 (a2 INT, b2 INT);

CREATE TABLE t3 (a3 INT, b3 INT);

CREATE INDEX t_idx_t1 ON t1(a1);

CREATE INDEX t_idx_t2 ON t2(a2);

CREATE INDEX t_idx_t3 ON t3(a3);

插入数据如下:

INSERT INTO t1 values(generate_series(1,10000), generate_series(1,10000));

INSERT INTO t2 values(generate_series(1,10000), generate_series(1,20000,2));

INSERT INTO t3 values(generate_series(1,10000), generate_series(1,30000,3));


示例1 子查询合并技术,PostgreSQL不支持。

两个相似子链接作为条件子句的一部分,查询执行计划如下:

test=# explain SELECT * FROM t1 WHERE a1<10 AND (
EXISTS (SELECT a2 FROM t2 WHERE t2.a2<5 AND t2.b2=1) OR
EXISTS (SELECT a2 FROM t2 WHERE t2.a2<5 AND t2.b2=2) );
                                 QUERY PLAN
----------------------------------------------------------------------------
 Result  (cost=16.66..25.07 rows=9 width=8)
   One-Time Filter: ($0 OR $1)
   InitPlan 1 (returns $0)
     ->  Index Scan using t2_a2_key on t2  (cost=0.00..8.33 rows=1 width=0)
           Index Cond: (a2 < 5)
           Filter: (b2 = 1) //没有和条件“b2=2”合并在一起判断,而是一个独立结点
   InitPlan 2 (returns $1)
     ->  Index Scan using t2_a2_key on t2  (cost=0.00..8.33 rows=1 width=0)
           Index Cond: (a2 < 5)
           Filter: (b2 = 2) //没有和条件“b2=1”合并在一起判断,而是一个独立结点
   ->  Index Scan using t1_a1_key on t1  (cost=0.00..8.41 rows=9 width=8)
         Index Cond: (a1 < 10)
(12 行记录)

 
从查询执行计划看,表t2上执行了两次独立的索引扫描,且过滤条件不同,这表明两条子链接是独立执行的,所以PostgreSQL没有进行子查询的合并。
SQL语句的语义等价于上一条SQL,查询执行计划如下:

test=# explain SELECT * FROM t1 WHERE a1<10 AND EXISTS (SELECT a2 FROM t2 WHERE t2.a2<5 AND (t2.b2=1 OR t2.b2=2));
                                 QUERY PLAN
----------------------------------------------------------------------------
 Result  (cost=8.34..16.75 rows=9 width=8)
   One-Time Filter: $0
   InitPlan 1 (returns $0)
     ->  Index Scan using t2_a2_key on t2  (cost=0.00..8.34 rows=1 width=0)
           Index Cond: (a2 < 5)
           Filter: ((b2 = 1) OR (b2 = 2))
   ->  Index Scan using t1_a1_key on t1  (cost=0.00..8.41 rows=9 width=8)
         Index Cond: (a1 < 10)
(8 行记录)

 

查看查询执行计划,在表t2上只执行了一次索引扫描,过滤条件是“(b2 = 1) OR (b2 = 2)”,查询优化器没有把子链接拆分为两个子链接执行而是完全有能力在一个索引扫描中完成子链接的查询工作。对比前一条SQL语句,可知PostgreSQL不支持子查询合并技术。

本文节选自《数据库查询优化器的艺术--原理解析与SQL性能优化》2014年1-2月出版
  
  
PostgreSQL查询优化器--逻辑查询优化--子查询优化(二) - 那海蓝蓝 - 那海蓝蓝的博客
 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值