2010-03-26 40 views
1

假設我有以下查詢:如何在查詢提示中爲單個表的不同連接選擇不同的提示?

select * from A, B, C, D 
where A.x = B.x 
and B.y = C.y 
and A.z = D.z 

我有A.x和B.x和B.y和C.y和D.z

指標

上有A.Z.沒有索引

如何提示此查詢在A.x上使用INDEX提示,但在A.z上使用USE_HASH提示?看起來好像只有表名,而不是特定的聯接,所以當使用一個包含多個聯接的表時,我只能爲它們指定一個策略。

另外,假設我在上面的查詢中使用了LEADING或ORDERED提示。這兩個提示都只有一個表名,所以如何確保A.x = B.x join在A.z = D.z之前發生?我意識到在這種情況下,我可以先列出D,但想象D隨後加入到E中,並且D-E加入是我在整個查詢中想要的最後一個。

第三個配置 - 假設我希望A.x join成爲整個查詢的第一個,並且我希望A.z join成爲最後一個。我如何使用提示從A發起單個連接,然後是B-C連接,最後是A-D連接?

+0

否 - 'ORDERED'不包含表名。它告訴優化器使用FROM子句中的表的順序。另外,在Oracle 10g +中,LEADING提示接受任意數量的表 - 例如, '/ * + LEADING(A B C D)* /' – 2010-03-29 03:44:49

回答

3

首先,使用這種提示應該是最後的手段,而不是編寫查詢的正常方式。大多數情況下,您應該確保優化器的統計數據是最新的,並讓社區組織爲自己制定最佳路徑 - 這是它的工作!

索引提示可以指定要使用這樣的索引的名稱:

SELECT /*+ INDEX (A, A_X_IDX) */ * 
... 

(假設A.X指數被稱爲A_X_IDX)。

你不能告訴Oracle使用A.X 上的索引使用哈希連接到表A在同一語句中,這是沒有意義的。但是,您可以(如果必須)指定的訪問路徑爲每個表是這樣的:

SELECT /*+ INDEX (A, A_X_IDX) INDEX(B, B_Y_IDX) USE_HASH(C) */ * 

但重申一下,它應該是罕見需要做到這一點。甲骨文已經投入了數百萬美元和工時來開發CBO,那麼爲什麼要有效地關閉它呢?

+0

我一直很滿意默認優化的行爲,但是對於這個特定的查詢(跨越數據庫鏈接並使用多個視圖),當我運行沒有任何提示的解釋計劃時,它顯示約700的估計成本。當我運行沒有提示的查詢時,大約需要30秒才能返回。當我指定LEADING提示時,它顯示約950的費用,但返回約3.5秒。必須達到這個特定水平是相當令人沮喪的,但我沒有看到任何其他選擇。 – 2010-03-26 16:56:39

+1

數據庫鏈接可能是一個很大的表現。 DRIVING_SITE提示在這裏很有用 - 請參閱http://download.oracle.com/docs/cd/B28359_01/server.111/b28310/ds_appdev004.htm – 2010-03-26 20:17:19

0

在SQL Server中,你會做一個哈希聯合提示這樣

SELECT * FROM table1 t1 
INNER hash join table2 t2 ON t1.id = t2.id 

,你也可以提供一個索引提示

select * from table1 t1 
inner join table2 t2 with (index(bla)) on t1.id = t2.id 

不知道語法看起來像在甲骨文,順便說一句,你爲什麼使用舊式連接?你還在8i嗎?

+0

我們使用10g。我發現「舊」風格加入比新語法更具可讀性。我已經對ANSI加入語法做了一些嘗試,但我並不覺得自己獲得了很多。我還有點不確定如何在ON子句中指定非連接條件,並且我花費了更多的時間在各個地方跳躍,而不是在所有連接都在一個塊中時。 – 2010-03-26 17:00:25

+2

作爲一個在不太遙遠的過去中彈指一揮並轉向ANSI連接語法的人,起初我也沒有看到這一點。看起來很尷尬。現在我是一個大粉絲。首先,如果您必須使用不同的DBMS(例如SQL Server),您不會爲語法而煩惱。一旦你改變了你的想法,它實際上更直觀。你沒有人問你「+」符號的含義。它更具可讀性。不知道「一個塊中的所有連接」是什麼意思,你可以在一個選擇中確定有多個連接。儘管最初的阻力,我很高興我做出了改變。 – DCookie 2010-03-26 18:50:09

相關問題