如果您有索引first name + last name + age + state
,則不需要first name + last name + age
和first name + last name
和first name
。如果您的索引爲first name + last name + age + state
,並且用戶僅在「名字」和「姓氏」上進行搜索,則數據庫將能夠使用該索引。只要用戶以相同的從左到右的順序指定列作爲索引,即使沒有指定每列,數據庫也可以使用該索引。例如,如果您有索引first name + last name + age + state
並且用戶指定了「名字」和「姓氏」,那麼數據庫將能夠使用該索引跳轉到匹配的行。但是,如果用戶指定「名字」和「年齡」,或「名字」和「狀態」,那麼數據庫將只部分使用索引跳轉到具有匹配名字的行,但是它必須掃描匹配「年齡」或「狀態」的行。如果你想了解背後的技術細節,請閱讀數據庫索引和B +樹。 This是一個很好的解釋。
運行單個查詢時,數據庫也可以使用多個索引。如果你有索引
`last name`
`state`
`age`
而對於「姓氏」,「狀態」,「年齡」的用戶搜索,該數據庫將能夠使用所有三個索引快速找到匹配的行的每個字段,然後將結果結合起來,並且不匹配所有三個索引的行將不會被選中。如果你看一個執行計劃,你就可以看到它這樣做。當然,這將比單個索引具有每個必需字段慢一點,但它會阻止你有很多索引。
另請注意,即使索引存在,數據庫可能不一定使用該索引,因爲執行行掃描可能會更快。例如,用上面的三個不同索引的例子,假設用戶搜索「姓氏」,「名字」和「狀態」。由於「姓氏」和「名字」的組合具有如此高的選擇性(意味着該索引中的大多數值是唯一的),因此使用索引獲取與第一個匹配的所有行可能更快名稱和姓氏,然後僅對這些行執行簡單的迭代掃描,以查找也具有匹配狀態的行,然後再使用state
索引,然後加入兩個索引返回的行。
當您設計索引時,如果索引的選擇性非常低,那麼索引不會提高性能(實際上可能比進行全表掃描更糟糕)。舉例來說,性別並不是一個好的領域,因爲你只有兩個可能的價值。如果用戶僅搜索性別,則無論索引還是沒有索引,都不會獲得良好的性能,因爲您將返回一半行。
行對行,全表掃描實際上比使用索引更快。原因是當數據庫執行表掃描時,它可以直接跳到磁盤上的數據頁面。當它使用一個索引時,它必須經過幾箇中間索引頁面才能真正到達數據存儲在磁盤上的位置。對於像「性別」這樣的將要選擇一半行的字段,跟隨索引鏈接對錶中一半行的額外開銷可能超過僅使用索引掃描整個表的成本。
我會建議指標
`first name, last name`
`birthdate`
`state`
如果你有搜索的頻繁領域的特定組合,那麼你可以讓該指數也加快速度。但是,不要爲每個字段組合建立索引。
如果您使用「生日」而不是「生日」,那麼您不需要「年齡」,因爲您可以根據「生日」計算出來,然後對「生日」進行between
查詢。如果你不得不爲「生日」和「年齡」分開列,那麼你也可以索引「年齡」。但是,像其他用戶在下面評論的那樣,您必須不斷更新您的年齡。我強烈建議不要這種設計。
要考慮的最後一件事是是否試圖使覆蓋索引。覆蓋索引是用戶搜索的每個字段都是索引的一部分。例如,假設您的表格中有100個字段,但用戶通常只會根據姓名查找某人的狀態和年齡。所以,你的查詢有很大比例是這個樣子
SELECT STATE, AGE FROM PEOPLE WHERE FIRSTNAME = 'Homer' AND LASTNAME = 'Simpson'
如果你的指數是LASTNAME, FIRSTNAME
,則數據庫將查找「荷馬史詩」和「辛普森」的索引(這將涉及讀取從幾個索引頁磁盤)中,使用索引指針轉到存儲數據記錄的磁盤頁面,讀取整個數據頁面,將其解析爲字段,然後返回狀態和年齡。
現在,假設您運行相同的查詢,但您的索引爲LASTNAME, FIRSTNAME, STATE, AGE
。數據庫引擎仍會使用您的索引查找「Homer」和「Simpson」,但一旦找到合適的索引記錄(與上面的工作方式完全相同),該索引記錄已經有STATE
和AGE
。因此,數據庫可以直接從索引中獲得查詢結果,而不必從磁盤讀取數據頁面。
在表掃描的情況下,覆蓋指數可以顯着提高性能的情況。假設你的表中有100個字段(所以一行的大小是幾百字節或更多)。現在,用戶運行查詢
SELECT FIRSTNAME, LASTNAME, AGE FROM PEOPLE
數據庫必須讀取整個表(包括所有100個字段這是沒有必要爲此查詢)來獲得結果。如果您有索引LASTNAME, FIRSTNAME, AGE
,那麼數據庫可以通過掃描整個索引而不是掃描整個表來獲取結果。由於在這種情況下,單個索引元素比單個數據行在字節方面小得多,所以查詢將快得多。
在您的表中有這麼幾個字段的特定情況下,由於索引中的字段與表中的字段相同,所以覆蓋索引可能不會非常有用,從而破壞了整個目的。但是,對於包含數十個字段的表(其中只有少數幾個字段通常被查詢),覆蓋索引可能是加快查詢速度的好方法。
哪種RDBMS適用於?請添加一個標籤來指定您是使用'mysql','postgresql','sql-server','oracle'還是'db2' - 或者其他的東西。 –
mysql/sql server – mtkachenko
(1)使用標籤而不是註釋來指定供應商的細節;那就是標籤的用途,評論(假定是)是臨時的。 (2)它是什麼:MySQL或SQL Server?這些是兩個**非常不同的**引擎,在某些情況下具有顯着不同的功能。 (3)永遠不會(幾乎不會*;但實際上從不***)將*年齡*放在索引中 - 因爲它每天改變0.3%的行數,需要不斷索引重建。存儲BirthDate並根據BIrthDate和CurrentDate計算* age *查詢。 –