ToprowDB Dynamic Server 查询优化技术---子查询优化--03-1
ToprowDB Dynamic Server 查询优化技术
华胜信泰架构师 李海翔
1 还有什么样的子查询,可以被优化?
参见上篇《ToprowDB Dynamic Server 查询优化技术之子查询 - 2》。
2子查询/视图被优化的技术本质?
从SQL语句的形式上看,子查询和视图相似,都会嵌入在宿主SQL中,这将导致宿主SQL产生嵌套层次。
而子查询作为一个相对独立的query,其与宿主SQL之间发生引用(reference)使得SQL的语义进一步复杂化。这样的子查询被称为相关子查询。而与宿主SQL之间不存在引用关系的则较为简单,被称为非相关子查询。
从SQL语句的执行效率看,存在子查询的SQL语句,通常情况下,父查询每执行一次(如获取一条元组),整个子查询都被执行(子查询作为一个整体被全部执行一次),这样导致IO很高(子查询对应的数据被反复调入调出内存),如果能够减少子查询的数据被反复调入调出,则SQL整体的执行效率就会得到提高。实践也证明,子查询的优化很有效果。
子查询的优化,就是消除嵌套层次,把子查询与父查询放在同一个层次去执行。这就是子查询优化的基本思路。
子查询优化的技术,常规的方式,称为“pull up”或“flatten”,即把子查询“上拉”或称为“扁平化”。这种技术常规的实现步骤有两条:
l 把子查询的FROM子句中的表对象,与上层的父FROM子句中的表对象做JOIN
l 把子查询的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子查询,没有被上拉,但是,子查询仅在执行器初始化阶段执行一次,然后把结果缓存到内存供后续多次使用,这样的方式,也是一种优化,称为“物化”。许多数据库使用了这种方式,如PG、MySQL、ToprowDB、Informix等。
再但是,前述的方式,表示了所有的子查询优化技术了吗?
答案是:没有。
还有很多的子查询优化技术,如子查询合并等等,可以参见《数据库查询优化器的艺术》一书获得更多知识。
再次但是,前述的方式,表示出了子查询优化技术得深度了吗?
答案是:没有。
如果子查询在SQL被优化的阶段执行,然后获得结果,是不是结果能被用于后续其他项目的优化呢?
举个例子:
select * from t1, t3 where t1.id in (select t2.idx from test2 where t2.idx<5) AND t1.id=t3.id;
假设id列是主键列,子查询的执行结果是(1,2),如果子查询能够在优化阶段即被执行,那么上述的SQL语句就等价于:
select * from t1, t3 where t1.id in (1,2) 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的执行会被极大地简化呢?!
————————————————
版权声明:本文为CSDN博主「那海蓝蓝」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/fly2nn/article/details/61924797
相关文章