ITPub博客

首页 > 数据库 > 国内数据库 > lightdb -- Oracle兼容 -- 支持Oracle多表层级查询的下推优化

lightdb -- Oracle兼容 -- 支持Oracle多表层级查询的下推优化

原创 国内数据库 作者:Hanson69 时间:2024-02-22 13:42:37 0 删除 编辑

在Oracle数据库中,层级查询可以很方便地查询含义等级关系的数据,例如工资表与部门表之间的下属关系。

而在实际应用中,多数情况下这些关系数据分布在多个表中,需要跨表进行层级查询。


对于两种方式连接多表:隐式连接和显示连接。隐式连接指没有明确指定JOIN子句;

显示连接指明确使用JOIN关键字指定连接方式。

这两种连接方式在WHERE子句中的连接条件下推上具有区别:


  • 对于隐式连接,Oracle会试图将WHERE子句中的连接条件下推到实际的连接操作中。

  • 而对于显示连接,由于用户已经明确指定了连接逻辑,Oracle不会再修改用户定义的连接条件下推位置。


下推连接条件的影响很明显:


  • 对于隐式连接,连接条件下推后可以利用索引更快地连接表,通常性能更优。

  • 但是如果条件下推错误,可能导致结果错误。


所以,在实际开发中需要灵活选择:

比如下面的 sql ,隐式的多表关联查询(没有显示的写 join )。

SELECT s1.staff_id, s1.name, s1.manager_id
 FROM staff_table s1, staff_table_2 s2
 WHERE s1.staff_id = s2.staff_id AND s1.staff_id > 1001
 START WITH s1.staff_id = '1001'
 CONNECT BY PRIOR s1.staff_id = s1.manager_id;

Oracle 执行计划如下,可以看到 WHERE 子句中的 s1.staff_id = s2.staff_id 被下推到了连接节点,而 s1.staff_id > 1001 还是保留在原来的位置。

------------------------------------------------------------------
| Id  | Operation                                | Name          |
------------------------------------------------------------------
|   0 | SELECT STATEMENT                         |               |
|*  1 |  FILTER                                  |               |
|*  2 |   CONNECT BY NO FILTERING WITH START-WITH|               |
|   3 |    NESTED LOOPS                          |               |
|   4 |     TABLE ACCESS FULL                    | STAFF_TABLE   |
|*  5 |     INDEX UNIQUE SCAN                    | SYS_C00109736 |
------------------------------------------------------------------
                                                                 
Predicate Information (identified by operation id):              
---------------------------------------------------              
                                                                 
   1 - filter("S1"."STAFF_ID">1001)                              
   2 - access("S1"."MANAGER_ID"=PRIOR "S1"."STAFF_ID")           
       filter("S1"."STAFF_ID"=1001)                              
   5 - access("S1"."STAFF_ID"="S2"."STAFF_ID")

如果显示的指定了 join ,那么 where 条件中的连接条件就不能再进行下推,否则结果错误。

SELECT s1.staff_id, s1.name, s1.manager_id
 FROM staff_table s1 join staff_table_2 s2
 ON s1.manager_id = s2.manager_id
 WHERE s1.staff_id = s2.staff_id AND s1.staff_id > 1001
 START WITH s1.staff_id = '1001'
 CONNECT BY PRIOR s1.staff_id = s1.manager_id;
------------------------------------------------------------------
| Id  | Operation                                | Name          |
------------------------------------------------------------------
|   0 | SELECT STATEMENT                         |               |
|*  1 |  FILTER                                  |               |
|*  2 |   CONNECT BY NO FILTERING WITH START-WITH|               |
|*  3 |    HASH JOIN                             |               |
|   4 |     TABLE ACCESS FULL                    | STAFF_TABLE   |
|   5 |     TABLE ACCESS FULL                    | STAFF_TABLE_2 |
------------------------------------------------------------------
Predicate Information (identified by operation id):                
---------------------------------------------------                                            
   1 - filter("S1"."STAFF_ID"="S2"."STAFF_ID" AND "S1"."STAFF_ID">1001) 
   2 - access("S1"."MANAGER_ID"=PRIOR "S1"."STAFF_ID")                   
       filter("S1"."STAFF_ID"=1001)                                     
   3 - access("S1"."MANAGER_ID"="S2"."MANAGER_ID")


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69982913/viewspace-3007059/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
专注于PostgreSQL数据库的研究

注册时间:2020-08-30

  • 博文量
    16
  • 访问量
    11392