Schema的優化和索引 - 索引的基礎

  索引是數據結構。它能幫助MySQL更有效率的獲取數據。它對於好的性能是決定性的因素,但是人們常常忘記使用它們或者沒有正確的理解它們,因此在現實的例子中,索引總是引起性能問題。這就是我們把索引放在這本書的較早部分的原因。甚至把索引這章放在語句優化之前。

  索引(在MySQL中也叫做鍵(keys))在數據越來越大的時候,變的格外重要。數據量小,沒有高的負載的情況下,在沒有索引的情況下,數據庫也可以表現的很好,但是隨着數據量的增大,性能下降還是非常厲害的。

  最簡單的理解MySQL索引的工作方式就是思考下這本書的索引。你可以通過此書的索引,很容易找到你需要的內容。並且可以知道內容的頁碼。

  MySQL使用索引的方式也是相類似的。它查找了值的索引數據結構。當它找到一個匹配,它就能找到包含這個匹配的行。假如你運行一下的語句:

  mysql> SELECT first_name FROM sakila.actor WHERE actor_id = 5;

  在actor_id上會有一個索引,所以MySQL使用索引來查找actor_id爲5的行。換句話說,它通過索引來查找值,並且返回包含這些指定值的任意的行。

  一個索引包含的值是來自於一個表中指定的列或者一些列。如果你索引超過1列的話,列的順序就尤爲重要了。因爲MySQL只高效的搜索最左邊前綴的索引。你將會看到,在兩個列上創建一個索引和爲兩個列分別創建單獨的索引是不同的。

  索引的類型

  索引有許多類型,它們都是針對不同的用途而被設計的。索引是在存儲引擎中實現的,而不是服務器。因此它們並沒有標準化:在每個引擎中,索引工作的方式都有所不同,並且並不是所有的存儲引擎支持所有種類的索引。即使這些存儲引擎支持索引的類型相同,在底層的實現也是有所不同。

  讓我們來看看MySQL所支持的索引類型,它們的優勢和缺點。

  B-Tree索引

  當人們討論索引而沒有說明它的類型的時候,往往指的是B-Tree索引。它用B-Tree數據結構存儲了數據。大部分MySQL存儲引擎都支持這種類型。Archive引擎是個例外:MySQL5.1之前還不支持索引,現在可以支持對AUTO_INCREMENT列添加一個索引了。

  對於這些索引,我們使用術語B-TREE,那是因爲在CREATE TABLE和其他語句中MySQL都是這麼使用它們的。然而,存儲引擎內部可能使用不同的存儲結構。比如,NDB集羣存儲引擎使用T-TREE的結構來實現這些索引的。

  存儲引擎在硬盤上存儲B-TREE索引的方式也各不相同。這些方式會影響性能。舉個實例,MyISAM使用前綴壓縮技術使索引變得更小。然而InnoDB並沒有壓縮索引,因爲它的一些優化功能不能使用壓縮的索引。MyISAM還通過行所存儲的物理位置來引用這個已索引的行,但是InnoDB是通過主鍵值來引用它們的。每種方式都有各自的優點和缺點。

  B-Tree的普通思路是,有序的存儲所有的值,並且每個葉的頁面(leaf page)和根節點都是相同的距離。下面的圖是抽象的B-Tree索引的展現。這和InnoDB索引的工作方式有點相吻合。(InnoDB使用的是B+TREE結構)。MyISAM使用不同的結構,但是概念上是相似的。

Schema的優化和索引 - 索引的基礎 - 索引的類型 - B-Tree索引

  Hash索引

  Hash索引是建立在Hash table至上的,並且它只對準確查找有效,也就是說,必須查找索引上的每一個列。對於每個行,存儲引擎計算了索引列的Hash code。這個hash code是非常小,並且對於其他行不同的數值,這些Hash code也是不相同的。在索引中存儲了hash code並且在hash table中存儲了一個指針指向每一行。

  在MySQL中,只有Memory存儲引擎支持顯式的Hash索引。雖然Memory表也可以使用B-Tree索引,但是它們是默認的索引類型是Hash索引。Memory引擎支持非唯一的Hash索引,這在數據庫領域中是不尋常的。如果多個值有相同的Hash code,那麼索引就會在在相同的hash table的實體中,使用一個linked list保存這些值所屬行的指針。

  說一個例子吧,假設表結構如下

CREATE TABLE testhash (
fname VARCHAR(50) NOT NULL,
lname VARCHAR(50) NOT NULL,
KEY USING HASH(fname)
) ENGINE=MEMORY;

  包含的數據如下:

mysql> SELECT * FROM testhash;
+--------+-----------+
| fname | lname |
+--------+-----------+
| Arjen | Lentz |
| Baron | Schwartz |
| Peter | Zaitsev |
| Vadim | Tkachenko |
+--------+-----------+

  假設我們有一個hash的函數叫f(),它會返回如下值(這些都是例子,並不是真實的值):

f('Arjen') = 2323
f('Baron') = 7437
f('Peter') = 8784
f('Vadim') = 2458

  索引的數據結構爲

Slot Value
2323 Pointer to row 1
2458 Pointer to row 4
7437 Pointer to row 2
8784 Pointer to row 3

  空間(R-TREE)索引

  MyISAM支持空間索引。你可以把它和地圖類型一起使用。比如GEOMETRY。不像B-Tree索引,它並不要WHERE條件來操作左邊前綴的索引。它通過所有的維度來索引數據。因此,查找可以有效地使用任意維度的組合。然而你必須要使用MySQL GIS函數。比如MBRCONTAINS( )。

    全文索引

  FULLTEXT是MyISAM表的一個特殊的索引類型。它在文本中找到一個關鍵詞,而並不是在索引中直接比較着兩個值。Full-text搜索不同於其他類型的匹配。它有許多細微的差別。比如stopwords,stemming,plurals以及Boolean searching。

  這些基本都和搜索引擎相關了。

  給一個列加全文索引並不能消除B-Tree索引的值。全文索引是匹配而不是WHERE條件的操作。

  我們會在全文搜索中,詳細討論。



發佈了37 篇原創文章 · 獲贊 12 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章