2014-04-01 49 views
1

我在這個表單中有一個查詢,平均需要約100個子句元素,並且在某些罕見時間超過1000個元素。如果超過1000個元素,我們會將in子句分塊到1000(Oracle最大值)。沒有聯接的Oracle IN子句的性能影響是什麼?

的SQL是在

SELECT * FROM tab WHERE PrimaryKeyID IN (1,2,3,4,5,...) 

我從選擇的表是巨大的,將包含數百萬更多的行比什麼是我的條款的形式。我的擔憂是,優化器可能會選擇做表掃描(我們的數據庫沒有最新的統計信息 - 是的 - 我知道...)

有沒有一個提示,我可以通過強制使用主鍵 - 無需知道主鍵的索引名稱,可能類似.../* + DO_NOT_TABLE_SCAN * /?

是否有創造性的方法來拉回數據,使得

  1. 我們進行
  2. 我們,我們讀取的塊數最少的往返次數最少(在邏輯IO級別?)
  3. 這會不會是快..
SELECT * FROM tab WHERE PrimaryKeyID = 1 
    UNION 
SELECT * FROM tab WHERE PrimaryKeyID = 2 
    UNION 
SELECT * FROM tab WHERE PrimaryKeyID = 2 
    UNION .... 
+0

['+ INDEX(tab)'](http://docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements006.htm#SQLRF50405)?因人而異。儘管可能只是確保適當的統計信息和信任查詢計劃者(當計劃者認爲它在IO成本方面「更好」時,通常會選擇FTS,因此強制索引使用可能會顛覆這一點)。另一種方法是通過OPTIMIZER_INDEX_COST_ADJ降低索引使用成本。再次,YMMV。 – user2864740

回答

5

如果表中的統計信息是準確的,那麼當WHERE子句中只有1000個硬編碼元素時,優化器應該不太可能選擇執行表掃描,而不是使用主鍵索引。最好的方法是收集(或設置)對象的準確統計數據,因爲這會導致好的事情自動發生,而不是嘗試做大量的體操操作來處理不正確的統計數據。

如果我們假設統計信息不準確,優化器會導致相信表掃描會比使用主鍵索引更有效,那麼您可能會添加一個DYNAMIC_SAMPLING提示,該提示將強制優化器在優化語句或提示覆蓋優化器的默認基數估計之前收集更準確的統計信息。這些都不需要知道任何關於可用索引的信息,它只需要知道表別名(或者如果沒有別名,則是名稱)。 DYNAMIC_SAMPLING將是更安全,更可靠的方法,但它會增加解析步驟的時間。

如果要在IN子句中構建一個包含可變硬編碼參數數量的SQL語句,那麼您可能會通過使用不可共享的SQL強制共享池並強制爲自己創建性能問題並強制數據庫花費大量時間分別解析每個變體。如果您創建了可以解析一次的單個可共享的SQL語句,效率會更高。根據您的IN子句值是從哪裏來的,可能看起來像

SELECT * 
    FROM table_name 
WHERE primary_key IN (SELECT primary_key 
         FROM global_temporary_table); 

SELECT * 
    FROM table_name 
WHERE primary_key IN (SELECT primary_key 
         FROM TABLE(nested_table)); 

SELECT * 
    FROM table_name 
WHERE primary_key IN (SELECT primary_key 
         FROM some_other_source); 

如果你讓自己到一個單一的共享SQL語句,那麼除了避免不斷重新解析語句的代價之外,您還有許多選項可用於強制執行不涉及修改的特定計劃e SQL語句。不同版本的Oracle對於計劃穩定性有不同的選擇 - 根據您的版本,有stored outlines,SQL plan managementSQL profiles等技術。您可以使用這些強制特定的SQL語句的特定計劃。但是,如果持續生成必須重新解析的新SQL語句,則使用這些技術將變得非常困難。

+0

本主題對不同查詢設計和模式的成本進行了一些反思。有時候,經驗法則僅僅是一個指導原則,但並不是執法的嚴格規定。 –

相關問題