2008-10-28 22 views
4

我可以做些什麼來提高oracle查詢的查詢性能而不創建索引?在不編制索引的情況下提高oracle查詢性能

這裏是我想要跑得更快的查詢:

SELECT c.ClaimNumber, a.ItemDate, c.DTN, b.FilePath 
FROM items a, 
itempages b, 
keygroupdata c 
WHERE a.ItemType IN (112,115,189,241) 
AND a.ItemNum = b.ItemNum 
AND b.ItemNum = c.ItemNum 
ORDER BY a.DateStored DESC 

這些列沒有被索引,並且每個表中包含數百萬條記錄。不用說,查詢執行需要花費3分半鐘以上的時間。這是生產環境中的第三方數據庫,我不允許創建任何索引,因此必須對查詢本身進行任何性能改進。

謝謝!

+0

哪些列中的數據類型?特別是ItemType? – 2008-10-28 19:45:23

+0

計劃是什麼。每個表中有多少行? 如果您無法創建任何索引,那麼您可能無法完成任何操作。 – 2008-10-28 22:05:20

回答

6

首先我重寫查詢是ANSI標準:

SELECT c.ClaimNumber, a.ItemDate, c.DTN, b.FilePath 
FROM items a 
INNER JOIN itempages b ON b.ItemNum = a.ItemNum 
INNER JOIN keygroupdata c ON c.ItemNum = b.ItemNum 
WHERE a.ItemType IN (112,115,189,241) 
ORDER BY a.DateStored DESC 

這使得它更容易閱讀和理解正在發生的事情。它也可以幫助你不犯錯誤(即交叉連接),這可能會導致真正的大問題。然後,我會得到Explain計劃,以查看DBMS正在使用該查詢處理的內容。它試圖使用一些索引?它是否正確加入表格?

然後,我會檢查我正在使用的表格,看看是否有任何已存在的索引可用於更快地進行查詢。最後,正如其他人所建議的,我會刪除Order By子句,然後在代碼中執行此操作。

-1

刪除ORDER BY

進行排序,你拉的行迴應用程序之後。

+1

數據庫內核開發人員花費大量時間優化通用組件(如分類技術)是不是很明顯?我覺得這不值得做這件事。 – 2008-10-28 18:14:38

+0

爲什麼是這樣。 如果數據庫淹沒了,就像我認爲的那樣,那麼可能是將數據拉回來然後對其進行排序將會有好處。 這將需要一些實驗,看看這是否是一個有效的方法,但他是在尋求想法。這是一個想法。 – EvilTeach 2008-10-28 19:55:39

+0

好吧,通過一切手段更新你的迴應,說:「如果數據庫被淹沒......」。然後,我們可以談論什麼「淹沒」的意思,而無論是在這種情況下,除去ORDER BY也優化切換到FIRST_ROWS模式的執行計劃等。 – 2008-10-29 12:22:03

0

沒有索引,該查詢只會隨着表大小的增加而變差。 就這樣說,嘗試刪除order by子句並在客戶端執行此類操作。

+0

數據庫內核開發人員花費大量時間優化通用組件(如分類技術)是不是很明顯?我覺得這不值得做這件事。 – 2008-10-28 18:16:24

+1

我確定數據庫排序是優化的,這不是問題。他問他如何提高查詢性能,最明顯的做法是刪除這種排序。 我已經拉到客戶端的一些重負載數據庫的一些真正的改進。 – 2008-10-28 18:47:04

7

要求第三方索引它的連接列,因爲它們應該在第一位完成!沒有索引,甲骨文除了暴力之外別無他法。

6

你可能想嘗試在任何這些表上創建一個物化視圖。然後,您可以在物化視圖上創建一個索引,以幫助加快查詢速度(然後查詢物化視圖而不是原始表)。

當然,如果您的基礎表已更新,您的視圖和索引將需要刷新。

1

如果查詢輸入是恆定的或可預測的(itemType IN (...)),則另一種方法是每天運行一次或兩次查詢,並將結果存儲在本地表中,並在適當的位置存儲索引。

然後,您可以進行昂貴的查詢'離線',併爲交互式查詢獲得更快/更好的結果。

3

首先看執行計劃。它是否準確地反映了在查詢執行的每個階段中要檢索的行數?謂詞「a.ItemType IN(112,115,189,241)」的選擇性有多大?執行計劃是否顯示使用臨時磁盤空間進行連接或排序?

其實,也許你可以修改問題來包含執行計劃。

此外,請確保您沒有禁用散列連接,這在OLTP調整的系統中有時就是這種情況,因爲它們是在Oracle中平等批量數據的最有效方式。他們應該出現在執行計劃中。

3

在加入表格之前,您可以嘗試過濾項目類型,如下所示。

如果您在9i之前運行Oracle,這有時會帶來令人驚喜的好處。

select 
    c.claimnumber, 
    a.itemdate, 
    c.dtn, 
    b.filepath 
from 
    (
    select itemdate 
    from items it 
    where it.itemtype in(112,115,189,241) 
) a 
    itempages b, 
    keygroupdata c 
where a.itemnum = b.itemnum 
    and b.itemnum = c.itemnum 

您也可以嘗試添加提示/ + RULE /或/ +有序 /看個究竟......再次,特別是與舊版本,這有時會得到意想不到的結果。

SELECT /*+RULE*/ 
    c.ClaimNumber, a.ItemDate, c.DTN, b.FilePath 
FROM 
    items a, 
    itempages b, 
    keygroupdata c 
WHERE a.ItemType IN (112,115,189,241) 
    AND a.ItemNum = b.ItemNum 
    AND b.ItemNum = c.ItemNum 
ORDER BY a.DateStored DESC 
0

統計數據是收集在這些表上嗎?如果不是,收集統計數據可能會改變執行計劃,但不一定會更好。

除此之外,請看執行計劃。您可能會發現它以非最優順序連接表(例如,在連接具有過濾條件的a之前,它可能會連接b和c)。

您可以使用提示嘗試影響訪問路徑,連接順序或連接方法。

更新:應對評論使我this介紹,這可能是有益的,或者至少有趣。

1

這是您經常運行的查詢嗎?看起來數據庫所有者有興趣創建索引來加快查詢的速度。您花費3.5分鐘運行查詢必須對其生產環境產生一些影響!

此外,他們是否已經在表上運行更新統計信息?這可能會提高性能,因爲連接順序是根據表的統計信息計算出來的。

順便說一句,你允許做什麼?剛剛閱讀?如果您可以創建臨時表並將索引放在這些表上,那麼我可能會考慮製作表的臨時副本,將它們編入索引,然後使用臨時副本執行索引輔助連接。

0

有時,您可以通過爲優化程序添加額外路徑來選擇它,通過在where子句中添加看起來像冗餘元素的東西來獲益。

例如,你有A.ItemNum = B.ItemNum AND B.ItemNum = C.ItemNum。嘗試添加A.ItemNum = C.ItemNum。然而,我非常確定,優化器足夠聰明,可以自行解決這個問題 - 儘管值得一試。

0

根據ItemType列的數據類型,如果它是varchar,使用以下命令可能會遇到更快的執行情況,Oracle將執行implict轉換。

SELECT c.ClaimNumber, a.ItemDate, c.DTN, b.FilePath 
FROM items a, 
itempages b, 
keygroupdata c 
WHERE ((a.ItemType IN ('112','115','189','241')) 
AND (a.ItemNum = b.ItemNum) 
AND (b.ItemNum = c.ItemNum)) 
ORDER BY a.DateStored DESC 
0

如果你說沒有索引,那麼這是否也意味着沒有定義主鍵或外鍵?顯然,分析表格和收集統計數據非常重要,但是如果元數據(如定義應該如何連接表格)不存在,那麼Oracle可能會選擇一個糟糕的執行路徑。

在這種情況下使用提示,如/ * + *有序/很可能使優化可靠地選擇一個好的執行路徑是唯一的選擇。它可能也值得添加外鍵和主鍵,但將它們定義爲DISABLE和VALIDATE。

我猜此評論的有效性依賴於厭惡指標走多遠等等因人而異。

0

首先創建關於該查詢的圖,然後生成從該視圖的表格。還可以在日期上創建索引,創建作業並在系統空閒時的午夜時間安排它。

1

我知道這個線程是很老,但對於搜索引擎我還是想提供一個替代的解決方案,將在甲骨文工作,並根據數據可能會快得多。

with a as (
    select 
    * 
    from 
    items 
    where 
    ItemType IN (112,115,189,241) 
) 
SELECT 
    c.ClaimNumber 
    , a.ItemDate 
    , c.DTN, b.FilePath 
FROM 
    a, 
    itempages b, 
    keygroupdata c 
WHERE 
    a.ItemNum = b.ItemNum 
    AND b.ItemNum = c.ItemNum 
ORDER BY 
    a.DateStored DESC 

您也可以嘗試WITH子句中的/*+ MATERIALIZE */提示。

其實我發現甲骨文的老聯接語法更容易比ANSI SQL ^^

0

好讀,因爲你不能創建索引,我會確保統計數據均達到最新那麼,我已經重寫了查詢是這樣的:

with a as (select /*+ MATERIALIZE */ ItemType, ItemNum, DateStored, ItemDate from items where ItemType in (112,115,189,241)) SELECT c.ClaimNumber, a.ItemDate, c.DTN, b.FilePath FROM a, itempages b, keygroupdata c WHERE a.ItemNum = b.ItemNum AND b.ItemNum = c.ItemNum ORDER BY a.DateStored DESC