2014-11-17 97 views
0

嗨我有一個數據庫大量的記錄粗略,400K應該增長更多。Oracle查詢微調

我有一個查詢來從該表中獲取數據以向用戶顯示記錄。我的查詢如下。

SELECT "PC0".PYID AS "pyID" , 
    "PC0".NAME     AS "Name" , 
    "PC0".OPPORTUNITYSTAGE  AS "OpportunityStage" , 
    "PC0".PXCREATEOPNAME  AS "pxCreateOpName" , 
    "PC0".PZINSKEY    AS "pzInsKey" , 
    "PC0".OPPORTUNITYSHORTNAME AS "OpportunityShortName" , 
    "PC0".IDTYPE    AS "IDType" , 
    "PC0".IDNO     AS "IDNo" , 
    "Campaign".PROGRAMNAME  AS "ProgramName" , 
    "Campaign".ENDDATE   AS "EndDate" , 
    "PC0".PRODUCTNAME   AS "ProductName" , 
    "PC0".PRODUCTTYPE   AS "ProductType" , 
    "PC0".OPPORTUNITYSTAGE  AS "OpportunityStage" , 
    "PC0".PXCREATEOPNAME  AS "pxCreateOpName" , 
    "PC0".OPPORTUNITYSOURCE AS "OpportunitySource" , 
    "PC0".OPPORTUNITYOWNER  AS "OpportunityOwner" , 
    "PC0".IDTYPE 
    ||"PC0".IDNO               AS "pyTextValue(1)" , 
    "PC0".REMINDERDATE             AS "ReminderDate" , 
    "PC0".STAGELASTCHANGED            AS "StageLastChanged" , 
    ROUND((CAST(SYSDATE AS DATE) - CAST("PC0".STAGELASTCHANGED AS DATE))) AS "pyIntegerValue(1)" , 
    (
    CASE 
    WHEN ROUND((CAST(SYSDATE AS DATE) - CAST("PC0".REMINDERDATE AS DATE))) > 0 
    THEN 1 
    WHEN ROUND((CAST(SYSDATE AS DATE) - CAST("PC0".STAGELASTCHANGED AS DATE))) > 7 
    THEN 2 
    ELSE 3 
    END)                AS "pyIntegerValue(2)" , 
    "PC0".PXCREATEDATETIME           AS "pxCreateDateTime" , 
    "PC0".CAMPAIGNID             AS "CampaignID" , 
    ROUND((CAST(SYSDATE AS DATE) - CAST("PC0".REMINDERDATE AS DATE))) AS "pyIntegerValue(3)" 
FROM MYCO_OPPORTUNITY "PC0" 
LEFT OUTER JOIN MYCO_CAMPAIGN "Campaign" 
ON ("PC0".CAMPAIGNID = "Campaign".PYID) 
ORDER BY 21 ASC, 
    22 DESC 

這需要將近13秒才能獲取SQl開發人員中的前50條記錄。實時我將一次提取近5千條記錄。

在我爲REMINDERDATE和STAGELASTCHANGED列和位圖連接索引定義了CAST的函數索引之後,時間爲13秒。

你可以請建議我應該如何優化查詢。在大集合上排序可能是我必須面對的一個問題。 :(

+3

向我們解釋計劃並檢查是否使用索引。 –

+0

@SylvainLeroux我們需要獲取排序結果。就像首先通過提醒日期的記錄一樣,然後這些記錄不會超過7天,然後是其他記錄。 – user3210391

+0

讓我看看我是否瞭解它:當你禁用的功能。指數,你有體面的表演。當它啓用時,它太長了?如果是這樣,你能比較兩種執行計劃嗎?另外,有沒有辦法讓你在[最小示例](http://stackoverflow.com/help/mcve)上重現該行爲,以便我們能夠測試它? –

回答

0

請確保您有一個索引:「PC0」 .CAMPAIGNID和「運動」 .PYID

確保您的SGA設置足夠高,無需瞭解服務器和數據庫中的大量信息。除了確保SGA足夠大以外,很難提供指導

0

您正在計算列上使用「order by」,這意味着Oracle必須在對所有400k行計算此值之後才能對其進行排序並返回結果。要確定這是沒有使用order by的問題測試。

有多個pos sible解決方案,但這個例子似乎並不是你的實際用例,所以它幾乎沒有意義,建議優化它

沒有更多關於數據的知識,我建議將查詢拆分爲三部分,並聯合使用,並在reminderdate和stagelastchanged上實現索引。

select * from ([part 1] where reminderdate > sysdate order by pxCreateDateTime) 
union all 
select * from ([part 2] where reminderdate <= sysdate and stagelastchanged + 7 < sysdate order by pxCreateDateTime) 
union all 
select * from ([part 3] where reminderdate <= sysdate and stagelastchanged + 7 >= sysdate order by pxCreateDateTime) 

我則期望1和2.應滿足使用指數和3全表掃描,這可能會通過增加FIRST_ROWS提示的幫助。

+0

這是我的實際使用案例。我需要首先獲取已通過提醒日期的記錄,然後記錄7天后未記錄的記錄,然後記錄其餘記錄。 (CAST(SYSDATE AS DATE) - CAST(「PC0」.REMINDERDATE AS DATE)))> ROUND((CAST(SYSDATE AS DATE) - CAST(「PC0」.REMINDERDATE AS DATE) 。STAGELASTCHANGED AS AS DATE)))> 7 – user3210391

+1

因此,您不以任何其他方式限制選定的結果? – Thaylon

+0

截至目前爲止,但可以通過基於查詢的性能將最大不可恢復次數限制爲5000來進行。 – user3210391