2014-11-19 3 views
-2

Выполнение выражений Я ИМЕЮ ниже запрос, слишком долго ВЕРНУТЬ ЗАПИСИSQL Query принимает долго, чтобы

{SELECT /*+ PARALLEL(5) */ 
    EXTER.ACE_IT_REGION_ID , 
    EXTER.ACE_IT_LOCATION_CODE, 
    EXTER.ACE_IT_ORD_NUM, 
    EXTER.TOTAL_ITEM_PRICE_PER_ORDER, 
    EXTER.TOTAL_ACE_PAYD_AMOUNT, 
    EXTER.ACE_ORD_COMPLETION_TIME AS DATEOFDATA 
FROM 
(SELECT /*+ use_hash(TAB1,TAB2) +*/ 
     DISTINCT 
     TAB1.ACE_IT_REGION_ID , 
     TAB1.ACE_IT_LOCATION_CODE, 
     TAB1.ACE_IT_ORD_NUM, 
     TAB1.TOTAL_ITEM_PRICE_PER_ORDER, 
     TAB2.TOTAL_ACE_PAYD_AMOUNT, 
     TAB1.ACE_ORD_COMPLETION_TIME 
FROM 
(SELECT  AAA.ACE_IT_REGION_ID, 
      AAA.ACE_IT_LOCATION_CODE, 
      AAA.ACE_IT_ORD_NUM, 
      AAA.SUM_PRICE_PLUS_TAX, 
      AAA.TOTAL_DISCOUNT, 
      (AAA.SUM_PRICE_PLUS_TAX-AAA.TOTAL_DISCOUNT) AS TOTAL_ITEM_PRICE_PER_ORDER, 
      TRUNC(AAA.ACE_ORD_COMPLETION_TIME)     
    FROM (SELECT B.ACE_IT_REGION_ID AS ACE_IT_REGION_ID, 
        B.ACE_IT_LOCATION_CODE AS ACE_IT_LOCATION_CODE, 
        B.ACE_IT_ORD_NUM AS ACE_IT_ORD_NUM, 
        (SUM(B.ACE_IT_ITEM_PRICE + B.ACE_IT_TAX_AMT)*B.ACE_IT_QTY) AS  SUM_PRICE_PLUS_TAX,  
        SUM(B.ACE_IT_DISC_AMT+B.ACE_IT_AUTO_DISC_AMT) AS TOTAL_DISCOUNT, 
        TRUNC(A.ACE_ORD_COMPLETION_TIME) AS ACE_ORD_COMPLETION_TIME 
      FROM POSDB.ACE_ORDERS A, POSDB.ACE_ITEM_TRAN B 
      WHERE A.ACE_ORD_COMPLETION_TIME >= TRUNC(SYSDATE -1) 
      AND  A.ACE_ORD_COMPLETION_TIME < TRUNC(SYSDATE) 
      AND  A.ACE_ORD_REGION_ID = B.ACE_IT_REGION_ID 
      AND  A.ACE_ORD_LOCATION_CODE = B.ACE_IT_LOCATION_CODE 
      AND  A.ACE_ORD_NUM = B.ACE_IT_ORD_NUM 
      AND  A.ACE_ORD_TYPE = 'IS' 
      AND  (A.ACE_ORD_STATUS = 'CR' 
        OR A.ACE_ORD_STATUS IS NULL 
        OR A.ACE_ORD_STATUS LIKE ' %' 
        OR A.ACE_ORD_STATUS LIKE '% ') 
      AND  (B.ACE_IT_VOID_IND <> 'V' OR B.ACE_IT_VOID_IND IS NULL) 
      GROUP BY B.ACE_IT_REGION_ID, 
        B.ACE_IT_LOCATION_CODE, 
        B.ACE_IT_ORD_NUM, 
        A.ACE_ORD_COMPLETION_TIME) AAA 
    ORDER BY AAA.ACE_IT_REGION_ID, 
      AAA.ACE_IT_LOCATION_CODE, 
      AAA.ACE_IT_ORD_NUM, 
      AAA.ACE_ORD_COMPLETION_TIME) TAB1, 
    (SELECT ACE_PAYD_REGION_ID, 
      ACE_PAYD_LOCATION_CODE, 
      ACE_PAYD_ORD_NUM, 
      SUM(ACE_PAYD_AMOUNT) TOTAL_ACE_PAYD_AMOUNT 
    FROM POSDB.ACE_PAYMENT_DTL 
    WHERE ACE_PAYD_POSTING_TIMESTAMP BETWEEN TRUNC(SYSDATE-1) AND TRUNC(SYSDATE) 
    AND (ACE_PAYD_STATUS <> 'V' OR ACE_PAYD_STATUS IS NULL) 
    GROUP BY 
      ACE_PAYD_REGION_ID, 
      ACE_PAYD_LOCATION_CODE, 
      ACE_PAYD_ORD_NUM) TAB2    
WHERE TAB1.ACE_IT_REGION_ID = TAB2.ACE_PAYD_REGION_ID 
AND  TAB1.ACE_IT_LOCATION_CODE = TAB2.ACE_PAYD_LOCATION_CODE 
AND  TAB1.ACE_IT_ORD_NUM = TAB2.ACE_PAYD_ORD_NUM 
ORDER BY 
    TAB1.ACE_IT_REGION_ID , 
    TAB1.ACE_IT_LOCATION_CODE, 
    TAB1.ACE_IT_ORD_NUM  ) EXTER   
WHERE (EXTER.TOTAL_ITEM_PRICE_PER_ORDER = EXTER.TOTAL_ACE_PAYD_AMOUNT) 
AND  EXTER.ACE_ORD_COMPLETION_TIME IS NOT NULL;} 

Пожалуйста, дайте мне какие-либо предложения. Я использовал намеки, но все же не уверен, что это займет время. все столы огромны около 300 000 000 каждый.

перед тем, как присоединиться к таблице te в таблице таблиц tab3, это заняло 5 минут ... но теперь даже после 20-25 минут он не возвращает записи.

+1

Вы используете индексы? – peter

ответ

0

Вам необходимо переписать запрос с помощью JOINS и убедиться, что поля, к которым выполняется соединение, имеют индексы.

Ваш пересмотренный запрос должен быть такого формата:

SELECT tab1.fld1, tab.fld2 
FROM tab1 
JOIN tab2 ON (tab2.ID = tab1.ID AND tab2.fld3 = 'xxx') 
JOIN tab3 ON (tab3.ID2 = tab2.ID2) 
WHERE tab1.fld4 = 'aaa' 
and tab3.fld5 > 100 

Это позволит SQL оптимизатор делать свою работу.

+0

Хорошо, попробуй, что..thx – kanak

+0

Хотя использование соединений в стиле ANSI рекомендуется, все же отлично, чтобы указать критерии соединения в предложении WHERE, и оптимизатор вполне способен понять, что происходит. Я согласен с вашим предложением о том, что OP гарантирует наличие соответствующих индексов. –

+0

У меня есть еще один такой же запрос, что и ниже, который немного сложнее, чем верхний, поскольку для этого нужно искать много таблицы и проверять общую цену и платежи. без статуса V.It Incluses 5 differnt tables: – kanak

0

SELECT /*+ PARALLEL(5) */ 
 
    EXTER.ACE_IT_REGION_ID , 
 
    EXTER.ACE_IT_LOCATION_CODE, 
 
    EXTER.ACE_IT_ORD_NUM, 
 
    EXTER.TOTAL_ITEM_PRICE_PER_ORDER, 
 
    EXTER.TOTAL_ACE_PAYD_AMOUNT, 
 
    EXTER.ACE_ORD_COMPLETION_TIME AS DATEOFDATA 
 
FROM 
 
(SELECT /*+ use_hash(TAB1,TAB2) +*/ 
 
     DISTINCT 
 
     TAB1.ACE_IT_REGION_ID , 
 
     TAB1.ACE_IT_LOCATION_CODE, 
 
     TAB1.ACE_IT_ORD_NUM, 
 
     TAB1.TOTAL_ITEM_PRICE_PER_ORDER, 
 
     TAB2.TOTAL_ACE_PAYD_AMOUNT, 
 
     TAB1.ACE_ORD_COMPLETION_TIME 
 
FROM 
 
(SELECT  AAA.ACE_IT_REGION_ID, 
 
      AAA.ACE_IT_LOCATION_CODE, 
 
      AAA.ACE_IT_ORD_NUM, 
 
      AAA.SUM_PRICE_PLUS_TAX, 
 
      AAA.TOTAL_DISCOUNT, 
 
-- There is no necessary that you write another subquery to finish below sql, you can do it in AAA 
 
      (AAA.SUM_PRICE_PLUS_TAX-AAA.TOTAL_DISCOUNT) AS TOTAL_ITEM_PRICE_PER_ORDER, 
 
      TRUNC(AAA.ACE_ORD_COMPLETION_TIME) 
 
    FROM (SELECT B.ACE_IT_REGION_ID AS ACE_IT_REGION_ID, 
 
        B.ACE_IT_LOCATION_CODE AS ACE_IT_LOCATION_CODE, 
 
        B.ACE_IT_ORD_NUM AS ACE_IT_ORD_NUM, 
 
        (SUM(B.ACE_IT_ITEM_PRICE + B.ACE_IT_TAX_AMT)*B.ACE_IT_QTY) AS  SUM_PRICE_PLUS_TAX, 
 
        SUM(B.ACE_IT_DISC_AMT+B.ACE_IT_AUTO_DISC_AMT) AS TOTAL_DISCOUNT, 
 
        TRUNC(A.ACE_ORD_COMPLETION_TIME) AS ACE_ORD_COMPLETION_TIME 
 
      FROM POSDB.ACE_ORDERS A, POSDB.ACE_ITEM_TRAN B 
 
      WHERE 
 
      A.ACE_ORD_COMPLETION_TIME >= TRUNC(SYSDATE -1) 
 
      AND  A.ACE_ORD_COMPLETION_TIME < TRUNC(SYSDATE) 
 
-- you can remove it replace by trunc(A.ACE_ORD_COMPLETION_TIME) = TRUNC(SYSDATE -1) if there is no index on this column. 
 
--   A.ACE_ORD_COMPLETION_TIME >= TRUNC(SYSDATE -1) 
 
--   AND  A.ACE_ORD_COMPLETION_TIME < TRUNC(SYSDATE) 
 
      AND  A.ACE_ORD_REGION_ID = B.ACE_IT_REGION_ID 
 
      AND  A.ACE_ORD_LOCATION_CODE = B.ACE_IT_LOCATION_CODE 
 
      AND  A.ACE_ORD_NUM = B.ACE_IT_ORD_NUM 
 
      AND  A.ACE_ORD_TYPE = 'IS' 
 
      AND  (A.ACE_ORD_STATUS = 'CR' 
 
        OR A.ACE_ORD_STATUS IS NULL 
 
-- I think it better to replace blow by OR INSTR(ACE_ORD_STATUS,' ') > -1 
 
--     OR A.ACE_ORD_STATUS LIKE ' %' 
 
--     OR A.ACE_ORD_STATUS LIKE '% ' 
 
        ) 
 
      AND  (B.ACE_IT_VOID_IND <> 'V' OR B.ACE_IT_VOID_IND IS NULL) 
 
      GROUP BY B.ACE_IT_REGION_ID, 
 
        B.ACE_IT_LOCATION_CODE, 
 
        B.ACE_IT_ORD_NUM, 
 
        A.ACE_ORD_COMPLETION_TIME 
 
        ) AAA 
 
-- remove order by clause in subquery, it's useless. 
 
-- ORDER BY AAA.ACE_IT_REGION_ID, 
 
--   AAA.ACE_IT_LOCATION_CODE, 
 
--   AAA.ACE_IT_ORD_NUM, 
 
--   AAA.ACE_ORD_COMPLETION_TIME 
 
) TAB1, 
 
    (SELECT ACE_PAYD_REGION_ID, 
 
      ACE_PAYD_LOCATION_CODE, 
 
      ACE_PAYD_ORD_NUM, 
 
      SUM(ACE_PAYD_AMOUNT) TOTAL_ACE_PAYD_AMOUNT 
 
    FROM POSDB.ACE_PAYMENT_DTL 
 
    WHERE ACE_PAYD_POSTING_TIMESTAMP BETWEEN TRUNC(SYSDATE-1) AND TRUNC(SYSDATE) 
 
    AND (ACE_PAYD_STATUS <> 'V' OR ACE_PAYD_STATUS IS NULL) 
 
    GROUP BY 
 
      ACE_PAYD_REGION_ID, 
 
      ACE_PAYD_LOCATION_CODE, 
 
      ACE_PAYD_ORD_NUM) TAB2 
 
WHERE TAB1.ACE_IT_REGION_ID = TAB2.ACE_PAYD_REGION_ID 
 
AND  TAB1.ACE_IT_LOCATION_CODE = TAB2.ACE_PAYD_LOCATION_CODE 
 
AND  TAB1.ACE_IT_ORD_NUM = TAB2.ACE_PAYD_ORD_NUM 
 
-- remove order by clause in subquery, it's useless. 
 
--ORDER BY 
 
-- TAB1.ACE_IT_REGION_ID , 
 
-- TAB1.ACE_IT_LOCATION_CODE, 
 
-- TAB1.ACE_IT_ORD_NUM 
 
) EXTER 
 
WHERE (EXTER.TOTAL_ITEM_PRICE_PER_ORDER = EXTER.TOTAL_ACE_PAYD_AMOUNT) 
 
AND  EXTER.ACE_ORD_COMPLETION_TIME IS NOT NULL; 
 

 
-- Fix it like this for tempory, please supply explain plan for further. 
 
-- There are so many columns like "ACE_PAYD_STATUS is not null", as you know, index could not contain null value. 
 
-- But I think you can create an similarly index like "create index *** on ACE_PAYMENT_DTL(ACE_PAYD_STATUS,0)" to keep null values in your index.

+0

Ошибка выводится, если я отправляю этот ответ, кроме этого метода ... – VikiYang

+0

Для более того вы должны проверить последнее_анализируемое время этой таблицы с помощью «select table_name, last_analyzed from user_tables order by last_analyzed desc». Затем проанализируйте таблицу, если это необходимо. – VikiYang

1

немного очищено для читаемости каждого из которых подмножества следующего уровня вниз. Также удалили избыточный внешний запрос и просто добавили его предложение WHERE к одному внутри. Должно быть тем же результат

 SELECT DISTINCT * 
      FROM 
       (SELECT 
         AAA.ACE_IT_REGION_ID, 
         AAA.ACE_IT_LOCATION_CODE, 
         AAA.ACE_IT_ORD_NUM, 
         AAA.SUM_PRICE_PLUS_TAX, 
         AAA.TOTAL_DISCOUNT, 
         AAA.SUM_PRICE_PLUS_TAX - AAA.TOTAL_DISCOUNT AS TOTAL_ITEM_PRICE_PER_ORDER, 
         TRUNC(AAA.ACE_ORD_COMPLETION_TIME) AS DATEOFDATA 
        FROM 
         (SELECT 
           B.ACE_IT_REGION_ID, 
           B.ACE_IT_LOCATION_CODE, 
           B.ACE_IT_ORD_NUM, 
           (SUM(B.ACE_IT_ITEM_PRICE + B.ACE_IT_TAX_AMT) 
           * B.ACE_IT_QTY) AS SUM_PRICE_PLUS_TAX, 
           SUM(B.ACE_IT_DISC_AMT + B.ACE_IT_AUTO_DISC_AMT) AS TOTAL_DISCOUNT, 
           TRUNC(A.ACE_ORD_COMPLETION_TIME) AS ACE_ORD_COMPLETION_TIME 
          FROM 
           POSDB.ACE_ORDERS A, 
           POSDB.ACE_ITEM_TRAN B 
          WHERE 
            A.ACE_ORD_TYPE = 'IS' 
           AND A.ACE_ORD_REGION_ID = B.ACE_IT_REGION_ID 
           AND A.ACE_ORD_LOCATION_CODE = B.ACE_IT_LOCATION_CODE 
           AND A.ACE_ORD_NUM = B.ACE_IT_ORD_NUM 
           AND A.ACE_ORD_COMPLETION_TIME >= TRUNC(SYSDATE -1) 
           AND A.ACE_ORD_COMPLETION_TIME < TRUNC(SYSDATE) 
           AND ( A.ACE_ORD_STATUS = 'CR' 
            OR A.ACE_ORD_STATUS IS NULL 
            OR A.ACE_ORD_STATUS LIKE ' %' 
            OR A.ACE_ORD_STATUS LIKE '% ') 
           AND ( B.ACE_IT_VOID_IND <> 'V' 
            OR B.ACE_IT_VOID_IND IS NULL) 
          GROUP BY 
           B.ACE_IT_REGION_ID, 
           B.ACE_IT_LOCATION_CODE, 
           B.ACE_IT_ORD_NUM, 
           A.ACE_ORD_COMPLETION_TIME) AAA 
        ORDER BY 
         AAA.ACE_IT_REGION_ID, 
         AAA.ACE_IT_LOCATION_CODE, 
         AAA.ACE_IT_ORD_NUM, 
         AAA.ACE_ORD_COMPLETION_TIME) TAB1, 
       (SELECT 
         APD.ACE_PAYD_REGION_ID, 
         APD.ACE_PAYD_LOCATION_CODE, 
         APD.ACE_PAYD_ORD_NUM, 
         SUM(APD.ACE_PAYD_AMOUNT) TOTAL_ACE_PAYD_AMOUNT 
        FROM 
         POSDB.ACE_PAYMENT_DTL APD 
        WHERE 
          APD.ACE_PAYD_POSTING_TIMESTAMP 
          BETWEEN TRUNC(SYSDATE-1) AND TRUNC(SYSDATE) 
         AND ( APD.ACE_PAYD_STATUS <> 'V' 
          OR APD.ACE_PAYD_STATUS IS NULL) 
        GROUP BY 
         APD.ACE_PAYD_REGION_ID, 
         APD.ACE_PAYD_LOCATION_CODE, 
         APD.ACE_PAYD_ORD_NUM) TAB2 
      WHERE 
        TAB1.ACE_IT_REGION_ID = TAB2.ACE_PAYD_REGION_ID 
       AND TAB1.ACE_IT_LOCATION_CODE = TAB2.ACE_PAYD_LOCATION_CODE 
       AND TAB1.ACE_IT_ORD_NUM = TAB2.ACE_PAYD_ORD_NUM 
       AND TAB1.TOTAL_ITEM_PRICE_PER_ORDER = TAB2.TOTAL_ACE_PAYD_AMOUNT, 
       AND TAB1.ACE_ORD_COMPLETION_TIME IS NOT NULL 
      ORDER BY 
       TAB1.ACE_IT_REGION_ID, 
       TAB1.ACE_IT_LOCATION_CODE, 
       TAB1.ACE_IT_ORD_NUM) EX 

Для оптимизации, я могу предложить следующие показатели, как вы не имеете такой отображаться в вашей должности структуры/индексов ... Индекс Детали компенсации фактически индекс покрытия смысл имеет элементы для где, group by и сумма одно поле. Таким образом, для выполнения запроса не нужно переходить на страницы необработанных таблиц. Все это может быть выполнено непосредственно из индексированных полей, и каждый из них должен быть оптимизирован для соединения и где critreia.

table   index on.. 
ACE_ORDERS  (ACE_ORD_TYPE, ACE_ORD_COMPLETION_TIME, ACE_ORD_REGION_ID, ACE_ORD_LOCATION_CODE, ACE_ORD_NUM, ACE_ORD_STATUS) 
ACE_ITEM_TRAN (ACE_IT_REGION_ID, ACE_IT_LOCATION_CODE, ACE_IT_ORD_NUM, ACE_IT_VOID_IND) 

ACE_PAYMENT_DTL (ACE_PAYD_POSTING_TIMESTAMP, ACE_PAYD_REGION_ID, ACE_PAYD_LOCATION_CODE, ACE_PAYD_ORD_NUM, ACE_PAYD_STATUS, ACE_PAYD_AMOUNT) 
Смежные вопросы