ToprowDB Dynamic Server 查询优化技术---子查询优化--03-1

ToprowDB Dynamic Server 查询优化技术

华胜信泰架构师  李海翔

(五)ToprowDB Dynamic Server 查询优化技术之子查询

本篇是《ToprowDB Dynamic Server 查询优化技术》系列的第五篇,继续 探讨ToprowDB逻辑查询优化技术中的子查询优化技术。

1 还有什么样的子查询,可以被优化?

参见上篇《ToprowDB Dynamic Server 查询优化技术之子查询 - 2》。

2子查询/视图被优化的技术本质?

SQL语句的形式上看,子查询和视图相似,都会嵌入在宿主SQL中,这将导致宿主SQL产生嵌套层次。

而子查询作为一个相对独立的query,其与宿主SQL之间发生引用(reference)使得SQL的语义进一步复杂化。这样的子查询被称为相关子查询。而与宿主SQL之间不存在引用关系的则较为简单,被称为非相关子查询。

SQL语句的执行效率看,存在子查询的SQL语句,通常情况下,父查询每执行一次(如获取一条元组),整个子查询都被执行(子查询作为一个整体被全部执行一次),这样导致IO很高(子查询对应的数据被反复调入调出内存),如果能够减少子查询的数据被反复调入调出,则SQL整体的执行效率就会得到提高。实践也证明,子查询的优化很有效果。

子查询的优化,就是消除嵌套层次,把子查询与父查询放在同一个层次去执行。这就是子查询优化的基本思路。

子查询优化的技术,常规的方式,称为“pull up”或“flatten”,即把子查询“上拉”或称为“扁平化”。这种技术常规的实现步骤有两条:

把子查询的FROM子句中的表对象,与上层的父FROM子句中的表对象做JOIN

把子查询的WHERE子句中的条件表达式,与上层的父WHERE子句中的条件表达式用“AND”操作符连接

这样,就能实现子查询的上拉优化。

 

但是,不是所有的子查询都能被优化的,我们在视图的优化中提到过,SPJ类型的视图可以被优化,子查询与此相似,通常情况下:SPJ类型的子查询不能被优化,SPJ类型的子查询能被优化

采用上述技术对子查询进行优化,则能把子查询的带来的嵌套层次消除从而减少IO花费

 

但是,上述方式不代表“囊括了所有的子查询优化技术”,子查询优化技术还有更多的内容,例如:

postgres=# explain select * from test1 where id not in (select idx from test2);

                           QUERY PLAN

----------------------------------------------------------------

 Seq Scan on test1  (cost=18.50..37.00 rows=340 width=92)

   Filter: (NOT (hashed SubPlan 1))

   SubPlan 1

     ->  Seq Scan on test2  (cost=0.00..16.80 rows=680 width=4)

PostgreSQL为例,一个NOT IN子查询,没有被上拉,但是,子查询仅在执行器初始化阶段执行一次,然后把结果缓存到内存供后续多次使用,这样的方式,也是一种优化,称为“物化”。许多数据库使用了这种方式,如PGMySQLToprowDBInformix等。

 

再但是,前述的方式,表示了所有的子查询优化技术了吗?

答案是:没有。

还有很多的子查询优化技术,如子查询合并等等,可以参见《数据库查询优化器的艺术》一书获得更多知识。

 

再次但是,前述的方式,表示出了子查询优化技术得深度了吗?

答案是:没有。

如果子查询在SQL被优化的阶段执行,然后获得结果,是不是结果能被用于后续其他项目的优化呢?

举个例子:

select * from t1, t3 where t1.id in (select t2.idx from test2 where t2.idx<5) AND t1.id=t3.id;

假设id列是主键列,子查询的执行结果是(12),如果子查询能够在优化阶段即被执行,那么上述的SQL语句就等价于:

select * from t1, t3 where t1.id in (12) AND t1.id=t3.id;

又等价于:

select * from t1, t3 where (t1.id=1 OR t1.id=2) AND t1.id=t3.id;

据此即可推导出:t1.id=t3.id=1 OR t1.id=t3.id=2。有这个结论,是不是原始的SQL的执行会被极大地简化呢?!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值