Javi Pedrera
Javi Pedrera

Reputation: 2095

SQL. Recursive Query. How do I optimise this query?

Are there any way to optimize the recursive query?

Tables:

TREE_TABLE: 
      Parent   varchar2 
      Child    varchar2
TABLEXXX:   
      FieldXXX varchar2       

I need to get all the roots which have any child that have a reference in TABLEXXX(FieldXXX). The result of the query is right, however the response time is too high. It is possible reduce the number of accesses to the subquery? Or another hint...

TREE_TABLE (Tree format)

a - b - c
d
f - g

TABLEXXX

c
f

Result:

a
b
c
f


-- Cost: 7. Bytes: 33.210  Cardinality: 1.230 
WITH subquery AS
(SELECT FIELD FROM TABLEXXX WHERE ...)
SELECT CONNECT_BY_ROOT t1.CHILD "ROOT"
   FROM TREE_TABLE t1
    WHERE EXISTS
      (SELECT subquery.FIELD 
        FROM subquery
        WHERE t1.CHILD = subquery.FIELD)
    START WITH t1.CHILD IN
                  (SELECT FIELD FROM TABLEYYYY WHERE ...)
    CONNECT BY PRIOR t1.CHILD = t1.PARENT

The Execution plan

 <ExplainPlan>
   <PlanElement id="0" operation="SELECT STATEMENT" optimizer="ALL_ROWS" cost="7" cardinality="1.230" bytes="33.210" cpu_cost="3.583.764" io_cost="6">
     <PlanElements>
       <PlanElement id="1" operation="FILTER" filter_predicates=" EXISTS (SELECT 0 FROM &quot;TS_SO_ENG_VALUATIONS_INFO&quot; &quot;V&quot; WHERE &quot;V&quot;.&quot;VAL_DATE&quot;=TO_DATE('2012-10-31 00:00:00', 'yyyy-mm-dd hh24:mi:ss') AND &quot;V&quot;.&quot;CLIENT_CP_CODE&quot;=:B1 GROUP BY &quot;CLIENT_CP_CODE&quot;)">
         <PlanElements>
           <PlanElement id="2" operation="CONNECT BY" option="WITH FILTERING" filter_predicates=" EXISTS (SELECT 0 FROM &quot;TS_BPU_EMAIL_EXTRA_INFO&quot; &quot;TS_BPU_EMAIL_EXTRA_INFO&quot; WHERE &quot;COUNTERPARTY&quot;=:B1)">
       <PlanElements>
         <PlanElement id="3" operation="FILTER" filter_predicates=" EXISTS (SELECT 0 FROM &quot;TS_BPU_EMAIL_EXTRA_INFO&quot; &quot;TS_BPU_EMAIL_EXTRA_INFO&quot; WHERE &quot;COUNTERPARTY&quot;=:B1)">
           <PlanElements>
             <PlanElement id="4" operation="COUNT">
         <PlanElements>
           <PlanElement id="5" operation="HASH JOIN" option="RIGHT OUTER" cost="7" cardinality="1.230" bytes="33.210" cpu_cost="3.583.764" io_cost="6" access_predicates="&quot;T2&quot;.&quot;COUNTERPARTY&quot;(+)=&quot;T1&quot;.&quot;FATHER&quot;">
             <PlanElements>
               <PlanElement object_ID="0" id="6" operation="INDEX" option="FAST FULL SCAN" optimizer="ANALYZED" object_owner="COMPANY_TREASURY" object_name="IDX_TS_BPU_EMAIL_FAMILY_CNT" object_type="INDEX" cost="3" cardinality="1.230" bytes="12.300" cpu_cost="176.086" io_cost="3"/>
               <PlanElement object_ID="1" id="7" operation="INDEX" option="FAST FULL SCAN" optimizer="ANALYZED" object_owner="COMPANY_TREASURY" object_name="TS_BPU_EMAIL_FAMILY_PK" object_type="INDEX (UNIQUE)" cost="3" cardinality="1.230" bytes="20.910" cpu_cost="190.329" io_cost="3"/>
             </PlanElements>
           </PlanElement>
         </PlanElements>
             </PlanElement>
             <PlanElement object_ID="2" id="8" operation="INDEX" option="UNIQUE SCAN" optimizer="ANALYZED" object_owner="COMPANY_TREASURY" object_name="TS_BPU_EMAIL_EXTRA_INFO_PK" object_type="INDEX (UNIQUE)" search_columns="1" cost="1" cardinality="1" bytes="10" cpu_cost="14.443" io_cost="1" access_predicates="&quot;COUNTERPARTY&quot;=:B1"/>
           </PlanElements>
         </PlanElement>
         <PlanElement id="9" operation="HASH JOIN" access_predicates="&quot;T1&quot;.&quot;FATHER&quot;=NULL">
           <PlanElements>
             <PlanElement id="10" operation="CONNECT BY PUMP"/>
             <PlanElement id="11" operation="COUNT">
         <PlanElements>
           <PlanElement id="12" operation="HASH JOIN" option="RIGHT OUTER" cost="7" cardinality="1.230" bytes="33.210" cpu_cost="3.583.764" io_cost="6" access_predicates="&quot;T2&quot;.&quot;COUNTERPARTY&quot;(+)=&quot;T1&quot;.&quot;FATHER&quot;">
             <PlanElements>
               <PlanElement object_ID="0" id="13" operation="INDEX" option="FAST FULL SCAN" optimizer="ANALYZED" object_owner="COMPANY_TREASURY" object_name="IDX_TS_BPU_EMAIL_FAMILY_CNT" object_type="INDEX" cost="3" cardinality="1.230" bytes="12.300" cpu_cost="176.086" io_cost="3"/>
               <PlanElement object_ID="1" id="14" operation="INDEX" option="FAST FULL SCAN" optimizer="ANALYZED" object_owner="COMPANY_TREASURY" object_name="TS_BPU_EMAIL_FAMILY_PK" object_type="INDEX (UNIQUE)" cost="3" cardinality="1.230" bytes="20.910" cpu_cost="190.329" io_cost="3"/>
             </PlanElements>
           </PlanElement>
         </PlanElements>
             </PlanElement>
           </PlanElements>
         </PlanElement>
         <PlanElement id="15" operation="COUNT">
           <PlanElements>
             <PlanElement id="16" operation="HASH JOIN" option="RIGHT OUTER" cost="7" cardinality="1.230" bytes="33.210" cpu_cost="3.583.764" io_cost="6" access_predicates="&quot;T2&quot;.&quot;COUNTERPARTY&quot;(+)=&quot;T1&quot;.&quot;FATHER&quot;">
         <PlanElements>
           <PlanElement object_ID="0" id="17" operation="INDEX" option="FAST FULL SCAN" optimizer="ANALYZED" object_owner="COMPANY_TREASURY" object_name="IDX_TS_BPU_EMAIL_FAMILY_CNT" object_type="INDEX" cost="3" cardinality="1.230" bytes="12.300" cpu_cost="176.086" io_cost="3"/>
           <PlanElement object_ID="1" id="18" operation="INDEX" option="FAST FULL SCAN" optimizer="ANALYZED" object_owner="COMPANY_TREASURY" object_name="TS_BPU_EMAIL_FAMILY_PK" object_type="INDEX (UNIQUE)" cost="3" cardinality="1.230" bytes="20.910" cpu_cost="190.329" io_cost="3"/>
         </PlanElements>
             </PlanElement>
           </PlanElements>
         </PlanElement>
         <PlanElement object_ID="2" id="19" operation="INDEX" option="UNIQUE SCAN" optimizer="ANALYZED" object_owner="COMPANY_TREASURY" object_name="TS_BPU_EMAIL_EXTRA_INFO_PK" object_type="INDEX (UNIQUE)" search_columns="1" cost="1" cardinality="1" bytes="10" cpu_cost="14.443" io_cost="1" access_predicates="&quot;COUNTERPARTY&quot;=:B1"/>
       </PlanElements>
           </PlanElement>
           <PlanElement id="20" operation="SORT" option="GROUP BY NOSORT" cost="4" cardinality="1" bytes="18" cpu_cost="29.741" io_cost="4">
       <PlanElements>
         <PlanElement object_ID="3" id="21" operation="TABLE ACCESS" option="BY INDEX ROWID" optimizer="ANALYZED" object_owner="COMPANY_TREASURY" object_name="TS_SO_ENG_VALUATIONS_INFO" object_type="TABLE" object_instance="1" cost="4" cardinality="1" bytes="18" cpu_cost="29.741" io_cost="4" filter_predicates="&quot;V&quot;.&quot;CLIENT_CP_CODE&quot;=:B1">
           <PlanElements>
             <PlanElement object_ID="4" id="22" operation="INDEX" option="RANGE SCAN" optimizer="ANALYZED" object_owner="COMPANY_TREASURY" object_name="ENG_VAL_INFO_VAL_DATE_IDX" object_type="INDEX" search_columns="1" cost="3" cardinality="1" cpu_cost="21.564" io_cost="3" access_predicates="&quot;V&quot;.&quot;VAL_DATE&quot;=TO_DATE('2012-10-31 00:00:00', 'yyyy-mm-dd hh24:mi:ss')"/>
           </PlanElements>
         </PlanElement>
       </PlanElements>
           </PlanElement>
         </PlanElements>
       </PlanElement>
     </PlanElements>
   </PlanElement>
</ExplainPlan>

Upvotes: 0

Views: 657

Answers (1)

Lord Peter
Lord Peter

Reputation: 3501

I'm guessing a little at your tree table structure here (assume that null parent means a root node):-

CREATE TABLE TREE_TABLE (PARENT VARCHAR2(1), CHILD VARCHAR2(1));
CREATE TABLE TABLEXXX (CHILD_REF VARCHAR2(1) NOT NULL); 
insert into tree_table values (null, 'a');
insert into tree_table values ('a','b');
insert into tree_table values ('b', 'c');
insert into tree_table values (null, 'd');
insert into tree_table values (null, 'f');
insert into tree_table values ('f','g');
insert into tablexxx values ('c');
insert into tablexxx values ('f');
commit;

Then we can pick all the nodes that have your selected TABLEXXX values as a descendant like this (your output suggests that you want all the ancestor nodes and not just the root nodes):-

select child from tree_table 
connect by child = prior parent start with child in (select child_ref from tablexxx)

This gives us:-

c
b
a
f

And this shows how we are walking the tree. We are starting at your selected nodes (c and f) and working upwards (so the level is upside down):-

select sys_connect_by_path(child ||'(' || level || ')', '->'), child from tree_table 
connect by child = prior parent start with child in (select child_ref from tablexxx) 

->c(1)                c
->c(1)->b(2)          b
->c(1)->b(2)->a(3)    a
->f(1)                f

Upvotes: 1

Related Questions