簡體   English   中英

Oracle 多列索引與單列索引

[英]Oracle multiple vs single column index

想象一下,我有一個包含以下列的表:

  1. 列:A(數字(10)) (PK)

  2. 列:B(數字(10))

  3. 列:C(數字(10))

     CREATE TABLE schema_name.table_name ( column_a number(10) primary_key, column_b number(10) , column_c number(10) );

A列是我的PK。

想象一下,我的應用程序現在有一個由 B 和 C 查詢的流。類似於:

SELECT * FROM SCHEMA.TABLE WHERE B=30 AND C=99

如果我只使用B列創建索引,這已經改善了我的查詢,對嗎?

此查詢背后的策略將受益於 B 列上的索引?

Q1 - 如果是這樣,為什么我應該用這兩列創建索引?

Q2 - 如果我決定用 B 和 C 創建一個索引,如果我查詢選擇B ,這個索引會影響嗎?

簡短回答:始終檢查實際性能,而不是理論性能。 這意味着,我的答案需要在真實數據庫中進行驗證。

在 SQL(Oracle、Postgre、MsSql 等)中,主鍵至少用於兩個目的:

  • 行的排序(例如,如果 PK 僅遞增,則將附加所有值)
  • 鏈接到行。 這意味着如果您有任何額外的索引,它將包含整個 PK,以便能夠從附加索引跳轉到其他行。

如果我只使用 B 列創建索引,這已經改善了我的查詢,對嗎? 此查詢背后的策略將受益於 B 列上的索引?

這取決於。 如果您的表太小,Oracle 可以對它進行完全掃描。 對於大表,Oracle 可以(並且在常見情況下會這樣做)對 B 列使用索引,然后進行范圍掃描 在這種情況下,Oracle 檢查 B=30 的所有值。 因此,如果您只能使用 B=30 的一行,那么您可以獲得良好的性能。 如果您有數百萬這樣的行,Oracle 將需要進行數百萬次讀取。 Oracle 可以通過 statistic獲取此信息。

Q1 - 如果是這樣,為什么我應該用這兩列創建索引?

需要直接訪問行。 在這種情況下,Oracle 只需要幾次跳轉即可找到您的行。 此外,您可以應用unique修飾符來幫助 Oracle。 然后它就會知道,不會返回多於單行。

但是,如果您的表有其他列,則真正的執行計划將包括對 PK 的訪問(以檢索其他行)。

如果我決定用B和C創建一個索引,如果我查詢只選擇B,這個索引會影響嗎?

是的。 請在此處查看詳細信息 如果索引有多個列,那么 Oracle 將根據列順序對它們進行排序。 例如,如果您使用B, C列創建索引B, C那么 Oracle 將能夠使用它來檢索諸如“B=30”之類的值,例如,當您僅限制 B 時。

您的問題的簡單答案。

對於此查詢:

SELECT *
FROM SCHEMA.TABLE
WHERE B = 30 AND C = 99;

最佳索引(B, C)(C, B) 順序確實很重要,因為兩個比較是=

可以使用任一列上的索引,但需要掃描所有匹配的值以與第二個值進行比較。

如果您在(B, C)上有一個索引,那么這可以用於對WHERE B = 30的查詢。 Oracle 還實現了跳過掃描優化,因此索引也可能用於WHERE C = 99 —— 但它可能不會。

我認為MySQL文檔對多列索引有很好的介紹。 它不包括跳過掃描,但在其他方面非常適用於 Oracle。

盡管已經回答了這個問題並且已經接受了一個答案,但我還是會提供更多信息:-)

索引是對 DBMS 的一種提議,它可以在某些情況下使用它來更快地訪問數據。 是否實際使用索引由 DBMS 決定。

Oracle 有一個內置優化器,它查看查詢並嘗試找到最佳執行計划以獲得您想要的結果。

假設所有行的 90% 有B = 30 AND C = 99 那么為什么 Oracle 會費力地遍歷索引,最后卻不得不訪問表中的幾乎每一行? 因此,即使在兩列上都有索引,Oracle 可能會決定根本不使用該索引,甚至由於針對索引的決定而更快地執行查詢。

現在回答問題:

如果我只使用 B 列創建索引,這已經改善了我的查詢,對嗎?

它可能。 如果 Oracle 認為B = 30減少了它必須從表中讀取的行數,它會這樣做。

如果是這樣,為什么要使用這兩列創建索引?

如果B = 30 AND C = 99的組合限制了要從表中進一步讀取的行,則最好改用此索引。

如果我決定用B和C創建一個索引,如果我查詢只選擇B,這個索引會影響嗎?

如果索引在(B, C) ,即 B 優先,那么 Oracle 可能會發現它很有用,是的。 在表中只有兩列的極端情況下,這甚至是覆蓋索引(即包含查詢中訪問的所有列)並且 DBMS 不必讀取任何表行,因為所有信息都是已經在索引本身中。 如果索引是(C, B) ,即 C 優先,則不太可能使用該索引。 不過,在某些極端情況下,Oracle 可能會這樣做。

好吧,這一切都取決於

如果該表很小,無論您可能創建任何索引,您都不會看到任何好處——它太小了,Oracle 會立即返回數據。

如果表很大,則取決於列的選擇性。 不能保證 Oracle 將永遠使用該索引。 如果優化器決定(根據它所擁有的信息 - 不要忘記定期收集統計信息!)不應該使用索引,那么你創建它是徒勞的(雖然,你可以選擇使用提示,但是 - 除非你知道什么你在做,不要做)。

你怎么知道發生了什么? 請參閱說明計划。

但是,一般來說,是的 - 索引有幫助。


Q1 - 如果是這樣,為什么我應該用這兩列創建索引?

哪個“兩列”? A 如果是主鍵列,Oracle 會自動創建索引,您不必這樣做。


Q2 - 如果我決定用 B 和 C 創建一個索引,如果我查詢只選擇 B,這個會受到索引的影響嗎?

如果您在談論復合索引(分別包含 B 和 C 列),並且如果查詢使用 B 列,那么是 - 索引將(好吧,可能會使用)。 但是,如果查詢僅使用 C 列,那么該索引將完全無用。

暫無
暫無

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

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