2009-04-27 81 views
49

我已經在桌子上創建了複合索引(索引,對於你的數學民謠),並假設它們是如何工作的。我只是好奇,如果我的假設是正確的或沒有。組合索引如何工作?

我假設當你列出索引列的順序時,你也指定了索引如何分組。例如,如果您有a,bc列,並且您按相同順序指定索引a ASC,b ASCc ASC,則結果索引對於a中的每個「組」將基本上是許多索引。

這是正確的嗎?如果不是,那麼結果指數實際上會是什麼樣子?

+0

請參閱這裏:[SQL Server覆蓋索引](http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/sql-server-covering-indexes)一個很好的解釋 – SQLMenace 2009-04-27 20:03:17

+0

這看起來像一個複合索引給我CREATE NONCLUSTERED INDEX idx_PeopleTest_Name_Id_FavoriteColor ON PeopleTest(Name,Id,FavoriteColor) – SQLMenace 2009-04-27 20:08:33

回答

54

複合索引就像常規索引一樣工作,除了它們具有多值鍵。

如果您在字段(a,b,c)上定義了一個索引,則記錄首先在a,b和c上排序。

實施例:

| A | B | C | 
------------- 
| 1 | 2 | 3 | 
| 1 | 4 | 2 | 
| 1 | 4 | 4 | 
| 2 | 3 | 5 | 
| 2 | 4 | 4 | 
| 2 | 4 | 5 | 
+7

請注意,索引是作爲Btree存儲的,因此(a,b,c)索引將有助於在(a)和(a,b)上進行搜索,但在其他搜索(如(b)或(公元前)。 – aexl 2016-04-30 17:53:06

3

否。結果索引將是單索引但帶有複合鍵。

KeyX = A,B,C,D; KeyY = 1,2,3,4;

指數KeyX,KeyY會實際上是:A1,A2,A3,B1,B3,C3,C4,D2

這樣的情況下,你需要通過KeyX KeyY找到的東西 - 這將是快速並將使用單個索引。就像SELECT ... WHERE KeyX =「B」AND KeyY = 3.

但是理解這很重要:WHERE KeyX =?請求使用該索引,而WHERE KeyY =?將不是完全使用這樣的索引。

+0

最後一個斷言在Oracle上不是真的。請參閱http://stackoverflow.com/questions/57878/sql-oracle-when-indexes-on-multiple-columns-can-be-used(忽略 - 錯誤 - 接受的答案)。 – Hobo 2009-04-27 20:26:11

+0

@Hobo:1.在大多數RDBMS中,跳過掃描不可用。 2.在大多數情況下,速度非常慢,比簡單的表掃描速度快(有時甚至更慢)(在非常罕見的情況下,它確實會有所幫助)。甲骨文沒有魔力。只需記住一條好規則 - 如果您的標準不僅僅使用索引的頂級列(這是創建大型複合索引的常見錯誤),請不要依賴複合索引。 – Mash 2009-04-27 20:43:05

+0

@拍攝積分。絕對不會說跳過掃描是一個銀彈,只是有些情況下KeyY =? _將使用索引。想想最好儘可能地給出完整的圖片。至於速度,希望優化器會選擇合適的方法(儘管如往常一樣,如果有疑問將會測量而不是假設) – Hobo 2009-04-27 21:40:48

17

索引的最常見的實現使用B樹,以允許一定程度的快速查找,並且還相當快速範圍掃描。這裏解釋太多了,但這裏是關於B-trees的維基百科文章。你是對的,你在創建索引中聲明的第一列將是結果B-樹中的高階列。

對高階列的搜索相當於一個範圍掃描,而B樹索引對於這樣的搜索非常有用。最簡單的方法是通過類比舊庫卡中的尚未轉換爲在線目錄的舊卡目錄。

如果您正在尋找所有名字爲「Clemens」的作者名片,只需轉到作者目錄,並很快找到一個在前面寫上「CLE- CLI」的抽屜。這是正確的抽屜。現在你在抽屜裏做一種非正式的二進制搜索,快速找到所有名爲「Clemens,Roger」或者「Clemens,Samuel」的卡片。

但是,假設您想爲名爲「Samuel」的作者找到所有卡片。現在你上了小溪,因爲這些卡片不是聚集在作者目錄的一個地方。數據庫中的複合索引也會出現類似現象。

不同的DBMS在其優化器在檢測索引範圍掃描方面的聰明程度不同,並準確估計其成本。並不是所有的指數都是B樹。您必須閱讀您的特定DBMS的文檔才能獲得真實的信息。

+0

謝謝,我一直在想這個問題很難,沒有明確的答案。 「對高階列的搜索相當於範圍掃描」,但是如果索引覆蓋2列,並且在列範圍查詢中指定了兩列,如「ColumnA threshold 2 AND columnB threshold4「,那麼oracle似乎不得不在B樹上花費多次範圍掃描,對吧?那麼如果我們在複合索引中有很多列,我們必須做很多範圍掃描,並且索引的有效性會大大降低 – 2012-05-15 16:52:38

+0

在我的答案中,我的意思是說ColumnA = value相當於一個範圍掃描,因爲可能有很多條目都具有適合於ColumnA的值,但對於ColumnB具有不同的值。你概述的情況完全不同。它可能仍然是範圍掃描,但範圍可能涉及索引中大部分條目。範圍越大,索引節省的越少。如果使用索引的值降低,優化器可能會選擇不同的策略。 – 2013-02-09 02:00:44

28

綜合指數是像在字典中一個普通的字母索引,但覆蓋兩個或多個字母,這樣的:

AA - page 1 
AB - page 12 

錶行首先下令在第一列中的索引,然後由第二個等。

當您通過兩列或第一列進行搜索時它可用。如果你的指數是這樣的:

AA - page 1 
AB - page 12 
… 
AZ - page 245 
BA - page 246 
… 

,你可以用它(在表= 2列)搜索上2字母,或像一個字母一個普通的指數:

A - page 1 
B - page 246 
… 

注意,在字典的情況下,頁面自己按字母順序排列。這是CLUSTERED索引的一個例子。

在一個普通的,非CLUSTERED指數,在頁面引用是有序的,像一本歷史書:

Gaul, Alesia: pages 12, 56, 78 
Gaul, Augustodonum Aeduorum: page 145 
… 
Gaul, Vellaunodunum: page 24 
Egypt, Alexandria: pages 56, 194, 213, 234, 267 

複合索引也可能是你ORDER BY兩列或多列時使用。在這種情況下,DESC條款可能會派上用場。

看到這篇文章在我的博客關於複合索引使用DESC條款:

0

我的理解是,複合索引工作就像普通索引,除非他們有個值鍵。如果您在字段(a,b,c)上定義索引,由於複合索引將存儲在BinaryTree中,因此索引僅在搜索組合後才起作用。

ABC 
AB 
A 

例如創建用於複合索引,b和c場等價於創建用於A,AB和abc單獨的索引。