SQL的性能调优

时间:2016-01-19 02:27:52

标签: sql oracle

问题陈述: -

我有一张表格,用于存储客户,相关客户和相关客户的数量。相关客户可以再次拥有更多相关客户,就像递归关系一样。

例如,客户1是客户2的父母,客户2也可以是客户3的父母,...

我想找到一些像下面的东西

CUSTOMER1 - CUSTOMER2
CUSTOMER1 - CUSTOMER3 

我想找出一位客户的所有相关客户(直到最后一位相关客户)。 表统计: -

目前的音量是2,00,000条记录。

创建表

CREATE TABLE RELATED_TABLE 
( CUS_ID            VARCHAR2(09) ,
  REL_CUS_ID        VARCHAR2(09) ,
  COUNT_OF_REL_CUST NUMBER(12)) ;

样本数据: -

 INSERT INTO RELATED_TABLE VALUES ('402758970','898196448',3);
 INSERT INTO RELATED_TABLE VALUES ('402758970','855115206',3);
 INSERT INTO RELATED_TABLE VALUES ('402758970','850353774',3);
 INSERT INTO RELATED_TABLE VALUES ('898196448','691094946',3);
 INSERT INTO RELATED_TABLE VALUES ('898196448','404636299',3);
 INSERT INTO RELATED_TABLE VALUES ('898196448','402758970',3);
 INSERT INTO RELATED_TABLE VALUES ('855115206','870397045',3);
 INSERT INTO RELATED_TABLE VALUES ('855115206','855115206',3);
 INSERT INTO RELATED_TABLE VALUES ('855115206','402758970',3);


CUS_ID     REL_CUS_ID    COUNT_OF_REL_CUST   
402758970  898196448       3                                                          
402758970  855115206       3                                                          
402758970  850353774       3                                     
898196448  691094946       3                                     
898196448  404636299       3                                     
898196448  402758970       3                                            
855115206  870397045       3                                            
855115206  855115206       3                                            
855115206  402758970       3

输出: -

402758970  898196448
402758970  855115206
402758970  850353774
402758970  691094946
402758970  404636299
402758970  870397045
402758970  855115206

如果我指定了一个特定的客户,我已经为上述问题声明尝试了两个SQL,这些SQL正在快速运行 但是当我针对一个拥有20万条记录的表尝试这些SQL时,SQL会运行30分钟而不提供 任何输出你可以建议如何提高这个SQL的性能。

方法1: -

SQL> SELECT  DISTINCT '402758970' CUS_ID,
  2                   REL_CUS_ID
  3    FROM  RELATED_TABLE
  4    START WITH CUS_ID = '402758970'
  5    CONNECT BY NOCYCLE PRIOR REL_CUS_ID = CUS_ID
  6  /

CUS_ID    REL_CUS_ID
--------- ---------
402758970 898196448
402758970 691094946
402758970 870397045
402758970 402758970
402758970 404636299
402758970 850353774
402758970 855115206

方法2: -

with tree ( cust_id, child_id, path) as
 (select cus_id ,
         rel_cus_id ,
         cus_id || ',' || rel_cus_id
   from  RELATED_TABLE 
  where cus_id = '402758970'
  union all
   select t.cust_id,
          rt.rel_cus_id,
          t.path || ',' || rt.rel_cus_id
   from tree t
   join related_table rt
    on t.child_id = rt.cus_id and
          instr(t.path, rt.rel_cus_id) = 0 )
    select distinct cust_id, child_id from tree

数据库上使用的实际SQL并解释PLAN

实际SQL: -

WITH relation_tree(cust_id,
                   child_id,
                   rel_desc,
                   rel_cus_id_count,
                   reqr_id,
                   path)
AS
(SELECT  cus_id,
         REL_cus_id,
         REL_DESC,
         REL_cus_id_COUNT,
         REQR_ID,
         cus_id || ',' || REL_cus_id
    FROM RELATED_CUS_DATA
   WHERE rel_cus_id_count >=
                 (SELECT val_1
                    FROM EXCLUSION_RELATION_NUMBER
                   WHERE attr = 'SEED_LIST_FAT_CUSTOMERS')
  union all
  SELECT rt.cust_id,
         ssr.rel_cus_id,
         ssr.REL_DESC,
         ssr.REL_cus_id_COUNT,
         ssr.REQR_ID,
         rt.path || ',' || ssr.rel_cus_id
    FROM relation_tree rt ,
         RELATED_CUS_DATA ssr 
   WHERE rt.child_id = ssr.cus_id
     and instr(rt.path, ssr.rel_cus_id) = 0)
select distinct cust_id,
                child_id,
                rel_desc,
                rel_cus_id_count,
                reqr_id 
  from relation_tree
ORDER BY cust_id

Explain Plan
-----------------
DESCRIPTION                                              OBJECT OWNER  OBJECT NAME                     COST CARDINALITY  BYTES
--------------------------------------------------------------------------------------------------------------------------------------
- SELECT STATEMENT , GOAL = ALL_ROWS                                                                   3917 20022        11332452
 - SORT UNIQUE                                                                                         2985 20022        11332452
   - VIEW                                                USER_NAME                                     1999 20022        11332452 
     - UNION ALL (RECURSIVE WITH) BREADTH FIRST
       -TABLE ACCESS STORAGE FULL                        USER_NAME     RELATED_CUS_DATA                34   15058        8522828
           TABLE ACCESS STORAGE FULL FIRST ROWS          USER_NAME     EXCLUSION_RELATION_NUMBER       2    1            65
       - HASH JOIN                                                                                     1953 1963         12916328
            RECURSIVE WITH PUMP                                                         
            TABLE ACCESS STORAGE FULL                    USER_NAME     RELATED_CUS_DATA                34   301168       170461088      

0 个答案:

没有答案