簡體   English   中英

oracle 在沒有索引的情況下提高查詢性能

[英]Improve oracle query performance without indexing

在不創建索引的情況下,我可以做些什么來提高 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 分半鍾的時間。 這是生產環境中的第三方數據庫,我不允許創建任何索引,因此必須對查詢本身進行任何性能改進。

謝謝!

要求第三方為其連接列建立索引,因為它們應該首先這樣做! 沒有索引,Oracle除了蠻力之外別無選擇。

首先,我將查詢重寫為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子句,然后在代碼中執行此操作。

您可能想要嘗試在任何這些表上創建實例化視圖。 然后,您可以在物化視圖上創建一個索引,這將有助於加快查詢速度(該索引隨后將查詢物化視圖而不是原始表)。

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

首先,查看執行計划。 它是否准確反映了查詢執行的每個階段要檢索的行數? 謂詞“ a.ItemType IN(112,115,189,241)”的選擇性如何? 執行計划是否顯示對連接或排序使用了任何臨時磁盤空間?

實際上,也許您可​​以修改問題以包括執行計划。

還要確保您沒有禁用哈希聯接,這在OLTP調整的系統中有時是這種情況,因為它們是在Oracle中等價聯接批量數據的最有效方法。 他們應該出現在執行計划中。

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

如果您在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 /或/ + ORDERED /以查看會發生什么……,特別是對於舊版本,有時會產生令人驚訝的結果。

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

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

然后,您可以使代價高昂的查詢“脫機”,並獲得更快/更好的交互式查詢結果。

這是您經常運行的查詢嗎? 創建數據庫以加快查詢速度似乎符合數據庫所有者的利益。 您花費3.5分鍾來運行查詢,這一定會對他們的生產環境產生一定的影響!

此外,他們是否在表上運行更新統計信息? 由於可以基於表的統計信息計算連接順序,因此可以提高性能。

順便說一句,你被允許做什么? 剛讀? 如果您可以創建臨時表並在其上放置索引,我可能會考慮制作該表的臨時副本,為這些索引建立索引,然后對臨時副本進行索引輔助的聯接。

我知道這個線程很舊,但是對於搜索引擎,我仍然想提供一個可以在oracle上運行的替代解決方案,並且取決於數據的速度可能要快得多。

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 */提示。

實際上,我發現oracle的舊連接語法比ansi sql ^^更易於閱讀

沒有索引,該查詢只會隨着表大小的增加而變得更糟。 話雖如此,請嘗試刪除order by子句並在客戶端進行排序。

是否在這些表上收集統計信息? 如果不是,收集統計信息可能會改變執行計划,盡管不一定會變得更好。

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

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

更新 :回應評論使我轉到了演示文稿,這可能會有所幫助或至少很有趣。

有時,您可以通過在where子句中添加看似多余的元素來增加優化器選擇的額外途徑,從而看到好處。

例如,您有A.ItemNum = B.ItemNum和B.ItemNum = C.ItemNum。 嘗試同時添加A.ItemNum = C.ItemNum。 但是,我非常確定,優化器足夠智能,可以自行解決這個問題-不過值得一試。

如果是varchar,則根據ItemType列的數據類型,使用以下命令可能會更快地執行,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

如果您說沒有索引,那么這是否還意味着沒有定義主鍵或外鍵? 顯然,分析表和收集統計信息很重要,但是如果不存在定義表應該如何連接的元數據,那么Oracle可能會選擇錯誤的執行路徑。

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

我想此評論的有用性取決於對索引的厭惡程度,以至於YMMV。

好吧,由於您無法創建索引,因此我將確保統計信息都是最新的,然后以這種方式重寫查詢:

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

注意,我在 Rockset 工作,但這是一個非常完美的用例,所以有一些信息。

Rockset 剛剛宣布了 Oracle / MS SQL 的早期訪問計划,該計划提供適合實時數據應用程序的查詢性能,無需任何手動索引。 使用 AWS 的 DMS,來自 Oracle 的數據被轉換為 stream 並通過 AWS Kinesis 發送到 Rockset。 Rockset 跟蹤 Kinesis stream,自動索引數據並在幾秒鍾內使其可用。 Rockset 是一個完全托管的 OLAP 數據庫,它通過自動構建聚合索引來實現毫秒級延遲搜索、聚合和連接任何數據,該索引結合了列、行和倒排索引的強大功能。 老實說,這是一些很酷的東西。

此處提供更多信息: https://rockset.com/blog/real-time-analytics-on-oracle-and-ms-sql-with-rockset/

首先在此查詢上創建一個視圖,然后從該視圖生成一個表。 還要在日期上創建索引,進行作業並將其安排在系統空閑時的午夜時間。

刪除訂單

將行拉回到應用程序后,執行排序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM