我的查询太慢了。如何执行和加快它们?

时间:2014-12-09 16:44:21

标签: sql oracle database-performance

我对有数百万行的表有两个查询..有可能加快它们的速度吗?

首先是:

WITH DATI AS
(
    SELECT 
        a.target_ou_id  FK_CLIENTE, count(*) QTA_NUM_TENT_VEND_3M
    FROM
        STG.T_STG_NBA_DT_S_EVT_ACT_G A 
    LEFT JOIN  
        STG.T_STG_NBA_DT_S_EVT_ACT_X_G ax ON A.ROW_ID = AX.ROW_ID
    WHERE
        INITCAP (ax.attrib_03) = 'Tentativo Di Vendita'
        AND to_number(to_char(todo_plan_start_dt,'YYYYMMDD')) >= to_number(to_char(add_months(sysdate,-3),'YYYYMMDD'))
    GROUP BY 
        a.target_ou_id
), IND_NBA AS 
(
    SELECT 
        CDC_QUERY, PK_ID_IND_NBA, SDS_NOME_ORA 
    FROM 
        ODS.T_ODS_ALL_DIM_IND_NBA 
    WHERE 
        CDC_QUERY = 'CRM038' AND SDS_STATO = 'ATT'
)
, PIVOT AS 
(
   SELECT
       FK_CLIENTE,
       IND_NBA.CDC_QUERY  CDC_QUERY,
       IND_NBA.SDS_NOME_ORA  CD_IND_NBA,
       IND_NBA.PK_ID_IND_NBA,
       DECODE(IND_NBA.SDS_NOME_ORA,
                    'QTA_NUM_TENT_VEND_3M ', QTA_NUM_TENT_VEND_3M,
                     NULL) AS CDN_VALORE,
       NULL AS SDS_TESTO 
   FROM 
       DATI
   CROSS JOIN 
       IND_NBA
)
SELECT * 
FROM PIVOT
WHERE CDN_VALORE IS NOT NULL or SDS_TESTO IS NOT NULL

第二个是:

WITH DATI AS
(
    SELECT 
        CLI_UNICO.FK_CLIENTE FK_CLIENTE,
        MAX(CASE WHEN COM.LDS_DESCRIZIONE_COMUNE IS NOT NULL THEN 'SI' ELSE 'NO' END) FLC_COMUNE_TERR
    FROM    
        STG.T_STG_NBA_DT_S_ASSET_G A, 
        ODS.V_ODS_NBA_DT_ASS_CLI_CLIUNICO CLI_UNICO,
        STG.T_STG_NBA_DT_S_ORG_EXT_G CFORN,
        STG.T_STG_NBA_DT_S_ADDR_PER_G IND_FOR,
        STG.T_STG_PSP_DT_LISTA_COMUNI_TERR COM
    WHERE 
        A.OWNER_ACCNT_ID = CLI_UNICO.FK_CLIENTE
        AND A.SERV_ACCT_ID = CFORN.ROW_ID(+)
        AND CFORN.PR_ADDR_ID = IND_FOR.ROW_ID(+)
        AND IND_FOR.CITY = COM. LDS_DESCRIZIONE_COMUNE (+)
    GROUP BY 
        CLI_UNICO.FK_CLIENTE
)
, IND_NBA AS
(
   SELECT 
       CDC_QUERY, PK_ID_IND_NBA, SDS_NOME_ORA 
   FROM 
       ODS.T_ODS_ALL_DIM_IND_NBA 
   WHERE 
       CDC_QUERY = 'CRM036' AND SDS_STATO = 'ATT'
)
, PIVOT AS (
    SELECT
       FK_CLIENTE,
       IND_NBA.CDC_QUERY  CDC_QUERY,
       IND_NBA.SDS_NOME_ORA  CD_IND_NBA,
       IND_NBA.PK_ID_IND_NBA,
       NULL AS CDN_VALORE,
       DECODE(IND_NBA.SDS_NOME_ORA,
                    'FLC_COMUNE_TERR', FLC_COMUNE_TERR,
                     NULL) AS SDS_TESTO 
   FROM 
       DATI
   CROSS JOIN 
       IND_NBA
)
SELECT * 
FROM PIVOT
WHERE CDN_VALORE IS NOT NULL or SDS_TESTO IS NOT NULL

我在连接列上放置了索引

offerte.target_ou_id,
CLI_UNICO.FK_CLIENTE,
A.OWNER_ACCNT_ID,CLI_UNICO.FK_CLIENTE,
A.SERV_ACCT_ID,CFORN.ROW_ID,
CFORN.PR_ADDR_ID, IND_FOR.ROW_ID,
IND_FOR.CITY,COM.LDS_DESCRIZIONE_COMUNE

表格包含以下行数:

  • STG.T_STG_NBA_DT_S_EVT_ACT_G A-> 314mil
  • STG.T_STG_NBA_DT_S_EVT_ACT_X_G-> 321mil
  • STG.T_STG_NBA_DT_S_ASSET_G A - > 25 mil。
  • ODS.V_ODS_NBA_DT_ASS_CLI_CLIUNICO CLI_UNICO-> 12,3 mil
  • STG.T_STG_NBA_DT_S_ORG_EXT_G CFORN-> 74,6mil
  • STG.T_STG_NBA_DT_S_ADDR_PER_G IND_FOR-> 56 mil
  • STG.T_STG_PSP_DT_LISTA_COMUNI_TERR COM-> 161
  • ind_nba-> 463

由于

1 个答案:

答案 0 :(得分:2)

一种考虑方式: 学习使用tkprof

在代码开头添加

alter session set sql_trace true;

在代码末尾添加

alter session set sql_trace false;

运行代码(我假设它实际运行时没有错误)。完全记住它完成时的一天。

接下来得到一些DBA帮助。在$ORACLE_HOME/admin/[name of database]中,通常(对于开发db)有一个名为udump的目录。在那里会有一个文件名

[ some numbers].trc

文件时间恰好是代码停止运行的时间。

针对文件

运行tkprof可执行文件
tkprof 123456789.trc some_output_filename

输出文件显示执行时间,磁盘查找和信息的信息。 i / o,以及每个游标使用的解释计划。