2012-11-14 25 views
1

約5分鐘,我需要產生,採用預付費的用戶細節報告。的Oracle 11g查詢花了將近30分鐘來完成,但在SQL Server

基本上我有2個表。 TBL_USER以及TBL_PREPAID_DETAILS

tbl_user僅列出用戶,而tbl_prepaid_details將具有所有預付信息,例如借方,貸方,餘額,總額充值。

報告將產生這樣的事情: -

FULLNAME USER_ID NEW_BALANCE CREATED DEPOSIT DEBIT TOTAL_DEPOSIT 
USER1 1 250 21/05/2011 500 250 1000 
USER2 2 250 21/05/2011 500 250 1000 
USER3 3 250 21/05/2011 500 250 1000 
USER4 4 250 21/05/2011 500 250 1000 

這個我使用SQL服務器數據庫之前,但全年2012/2013我們需要從SQL服務器到Oracle 11g遷移。

從前面的SQL查詢(SQL Server)的,我拿出下面的查詢(的Oracle 11g)。我可以得到結果,但花了近30分鐘完成,而在SQL服務器只需要5分鐘左右。 其唯一500+用戶

難道我失去了一些東西?有沒有簡化的版本來加快這個過程?

SELECT DISTINCT A.FULLNAME AS NAME, 
       A.USER_ID AS ID, 
       B.NAME, 

    (SELECT T.NEW_BAL 
    FROM 
    (SELECT NEW_BAL, 
      USER_ID 
     FROM TBL_PREPAID_DETAILS 
     WHERE DATE_INSERT BETWEEN '01/01/2010' AND '14/11/2012' 
     ORDER BY PREPAID_DETAIL_ID DESC) T 
    WHERE T.USER_ID = A.USER_ID 
    AND ROWNUM = 1) AS NEW_BALANCE, 

    (SELECT T2.DATE_INSERT 
    FROM 
    (SELECT DATE_INSERT, 
      USER_ID 
     FROM TBL_PREPAID_DETAILS 
     WHERE DATE_INSERT BETWEEN '01/01/2010' AND '14/11/2012' 
     ORDER BY DATE_INSERT DESC)T2 
    WHERE T2.USER_ID = A.USER_ID 
    AND ROWNUM = 1) AS DATE_INSERT, 

    (SELECT T3.PREV_BAL 
    FROM 
    (SELECT PREV_BAL, 
      USER_ID 
     FROM TBL_PREPAID_DETAILS 
     WHERE DATE_INSERT BETWEEN '01/01/2010' AND '14/11/2012' 
     ORDER BY PREPAID_DETAIL_ID ASC)T3 
    WHERE T3.USER_ID = A.USER_ID 
    AND ROWNUM = 1) AS DEPOSIT, 

    (SELECT SUM(T4.CREDIT) 
    FROM 
    (SELECT CREDIT, 
      USER_ID 
     FROM TBL_PREPAID_DETAILS 
     WHERE DATE_INSERT BETWEEN '01/01/2010' AND '14/11/2012' 
     ORDER BY PREPAID_DETAIL_ID ASC)T4 
    WHERE T4.USER_ID = A.USER_ID 
    AND ROWNUM = 1) AS DEBIT, 

    (SELECT SUM(T5.DEBIT + T5.PREV_BAL) 
    FROM 
    (SELECT DEBIT, 
      PREV_BAL, 
      USER_ID 
     FROM TBL_PREPAID_DETAILS 
     WHERE DATE_INSERT BETWEEN '01/01/2010' AND '14/11/2012' 
     ORDER BY PREPAID_DETAIL_ID ASC)T5 
    WHERE T5.USER_ID = A.USER_ID 
    AND ROWNUM = 1) AS TOTAL_DEPOSIT 
FROM TBL_USER A 
LEFT JOIN TBL_PREPAID_DETAILS C ON A.USER_ID = C.USER_ID 
LEFT JOIN TBL_ORGANIZATION_INFO B ON A.ORGANIZATION_ID = B.ORGANIZATION_ID 
WHERE C.DATE_INSERT BETWEEN '01/01/2010' AND '14/11/2012' 
    AND (A.USER_ID NOT IN ('xxx', 
         'xxx', 
         'xxx')) 
GROUP BY A.FULLNAME, 
     A.USER_ID, 
     C.DATE_INSERT, 
     B.NAME 
ORDER BY A.FULLNAME; 
+3

什麼指數(ES)存在嗎?兩個數據庫中的查詢計劃是什麼?各種物體的統計數據是否準確? DATE_INSERT是日期還是字符串?如果它是一個日期,爲什麼你將它與一個字符串進行比較? –

+1

其他說明:切勿在日期/時間/時間戳中使用'BETWEEN',也許在SQL Server上使用_especially_(是的,我看到你正在移動...);總是使用獨佔的上限(''<'')。不要在對象(或列)名稱前添加它們的類型,這是噪聲,稍後可能會使某些類型的重構變得尷尬;在列的情況下,總是命名它們,因此類型是「明顯的」(例如,「插入的」或類似的)。我們能否獲得您的表格定義,以及這些預期結果的樣本數據?另外,你並沒有通過一個一致的屬性來排序,這讓我感到很沮喪...... –

+1

如果你使用'OVER'子句,這將在兩個系統上運行得更快 - 那麼你將不需要'GROUP BY'語句。如果你需要一個例子,如果你發佈完整的表格定義,我可以給你寫一個例子。 – Hogan

回答

2

查看此頁面,瞭解Oracle調整的一般概述幫助。 Overall Oracle Tuning Page

Oracle提供的工具,大量的調整性能,包括可以添加哪些索引來提高特定查詢。這是我遇到慢速查詢時首先要做的事情之一。在你的情況下,我會考慮在你的查詢上運行一個解釋計劃,看看Oracle推薦什麼。這裏是運行解釋計劃的文檔。 Oracle Explain Plan

+0

感謝您的信息。我會嘗試運行oracle解釋計劃 – skycrew