MySQL數據庫的索引

原文鏈接:http://c.biancheng.net/view/2604.html

1 索引

  • 索引是MySQL數據庫中的重要對象之一,用於快速找出某個列中有某一特定值的行。
  • 創建索引時,需要確保該索引是應用在SQL查詢語句的條件。實際上索引也是一張表,該表保存了主鍵與索引字段,並指向實體表的記錄。
  • 索引分爲單列索引和組合索引。
    • 單例索引:一個索引只包含單個列,一個表可以有多個單列索引,但這不是組合索引。
    • 組合索引:一個索引包含多個列。
  • 不足:雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對錶進行insert 、update 、delete因爲更新表的收,MySQL不僅要保存數據,還有保存一下索引文件。建立索引會佔用磁盤空間的索引文件。

2 爲什麼要使用索引?

  • 它是數據庫性能調優技術的基礎,常用於實現數據的快速檢索。
  • 索引就是根據表中的一列或若干列按照一定順序建立的列值與記錄行之間的對應關係表,實質上是一張描述索引列的列值與原表中記錄行之間一一對應關係的有序表。

3 訪問方式

  • 順序訪問
    順序訪問是在表中實行全表掃描,從頭到尾逐行遍歷,直到在無序的行數據中找到符合條件的目標數據,這種方式實現比較簡單,但是當表中有大量數據的時候,效率非常低下。例如,在幾千萬條數據中查找少量的數據時, 使用順序訪問方式將會遍歷所有的數據,花費大量的時間,顯然會影響數據庫的處理性能。
  • 索引訪問
    索引訪問時通過遍歷索引來直接訪問表中記錄行的方式,使用這種方式的前提是對錶建立一個索引,在列上創建了索引之後,查找數據時可以直接根據該列上的索引找到對應記錄行的位置,從而快捷地查找到數據。索引存儲了指定列數據值的指針,根據指定的排序順序對這些指針排序。
  • 例如,在學生基本信息表 students 中,如果基於 student_id 建立了索引,系統就建立了一張索引列到實際記錄的映射表,當用戶需要查找 student_id 爲 12022 的數據的時候,系統先在 student_id 索引上找到該記錄,然後通過映射表直接找到數據行,並且返回該行數據。因爲掃描索引的速度一般遠遠大於掃描實際數據行的速度,所以採用索引的方式可以大大提高數據庫的工作效率。

4 索引的分類

索引的類型和存儲引擎有關,每種存儲引擎所支持的索引類型不一定完全相同。

4.1 物理分類

根據存儲方式的不同,MySQL 中常用的索引在物理上分爲以下兩類。

  1. B-樹索引
  • B-樹索引又稱爲 BTREE 索引,目前大部分的索引都是採用 B-樹索引來存儲的。B-樹索引是一個典型的數據結構,其包含的組件主要有以下幾個
    • 葉子節點:包含的條目直接指向表裏的數據行。葉子節點之間彼此相連,一個葉子節點有一個指向下一個葉子節點的指針。
    • 分支節點:包含的條目指向索引裏其他的分支節點或者葉子節點。
    • 根節點:一個 B-樹索引只有一個根節點,實際上就是位於樹的最頂端的分支節點
    • 基於這種樹形數據結構,表中的每一行都會在索引上有一個對應值。因此,在表中進行數據查詢時,可以根據索引值一步一步定位到數據所在的行。
  • B-樹索引可以進行全鍵值、鍵值範圍和鍵值前綴查詢,也可以對查詢結果進行 ORDER BY 排序。但 B-樹索引必須遵循左邊前綴原則,要考慮以下幾點約束:
    • 查詢必須從索引的最左邊的列開始。
    • 查詢不能跳過某一索引列,必須按照從左到右的順序進行匹配。
    • 存儲引擎不能使用索引中範圍條件右邊的列。
  1. 哈希索引
  • 哈希(Hash)一般翻譯爲“散列”,也有直接音譯成“哈希”的,就是把任意長度的輸入(又叫作預映射,pre-image)通過散列算法變換成固定長度的輸出,該輸出就是散列值。
  • 哈希索引也稱爲散列索引或 HASH 索引。MySQL 目前僅有 MEMORY 存儲引擎和 HEAP 存儲引擎支持這類索引。其中,MEMORY 存儲引擎可以支持 B- 樹索引和 HASH 索引,且將 HASH 當成默認索引。
  • HASH 索引不是基於樹形的數據結構查找數據,而是根據索引列對應的哈希值的方法獲取表的記錄行。哈希索引的最大特點是訪問速度快,但也存在下面的一些缺點:
    • MySQL 需要讀取表中索引列的值來參與散列計算,散列計算是一個比較耗時的操作。也就是說,相對於 B- 樹索引來說,建立哈希索引會耗費更多的時間。
    • 不能使用 HASH 索引排序。
    • HASH 索引只支持等值比較,如“=”“IN()”或“<=>”。
    • HASH 索引不支持鍵的部分匹配,因爲在計算HASH 值的時候是通過整個索引值來計算的。

4.2 邏輯分類

  1. 普通索引
    普通索引是最基本的索引類型,唯一任務是加快對數據的訪問速度,沒有任何限制。創建普通索引時,通常使用的關鍵字是 INDEX 或 KEY。
  • 創建索引

    語法:CREATE INDEX ON MYTABLE(username(length));
    如果是CHAR,VARCHAR 類型,length可以小於字段實際長度;如果是blob和text類型,必須指定length。

  • 添加索引

    語法:ALTER table tablename add index indexName(columnName)

  • 創建表的時候直接指定

    CREATE TABLE mytable(
    ID INT NOT NULL,
    username VARCHAR(16) NOT NULL,
    INDEX [indexName] (username(length))
    );

  • 刪除索引

    DROP INDEX [indexName] ON mytable;

  1. 唯一性索引
    唯一性索引是不允許索引列具有相同索引值的索引。如果能確定某個數據列只包含彼此各不相同的值,在爲這個數據列創建索引的時候就應該用關鍵字 UNIQUE 把它定義爲一個唯一性索引。
    創建唯一性索引的目的往往不是爲了提高訪問速度,而是爲了避免數據出現重複。索引列的值必須唯一,但是允許有控制。如果是組合索引,則列值的組合必須唯一。

  2. 主鍵索引
    主鍵索引是一種唯一性索引,即不允許值重複或者值爲空,並且每個表只能有一個主鍵。主鍵可以在創建表的時候指定,也可以通過修改表的方式添加,必須指定關鍵字 PRIMARY KEY。

注意:主鍵是數據庫考察的重點。注意每個表只能有一個主鍵。

  1. 空間索引
    空間索引主要用於地理空間數據類型 GEOMETRY。
  2. 全文索引
    全文索引只能在 VARCHAR 或 TEXT 類型的列上創建,並且只能在 MyISAM 表中創建。
  • 索引在邏輯上分爲以上 5 類,但在實際使用中,索引通常被創建成單列索引和組合索引。
    • 單列索引就是索引只包含原表的一個列。
    • 組合索引也稱爲複合索引或多列索引,相對於單列索引來說,組合索引是將原表的多個列共同組成一個索引。

提示:一個表可以有多個單列索引,但這些索引不是組合索引。一個組合索引實質上爲表的查詢提供了多個索引,以此來加快查詢速度。
比如,在一個表中創建了一個組合索引(c1,c2,c3),在實際查詢中,系統用來實際加速的索引有三個:單個索引(c1)、雙列索引(c1,c2)和多列索引(c1,c2,c3)。

爲了提高索引的應用性能,MySQL中的索引可以根據具體應用採用不同的索引策略。這些索引策略所對應的索引類型有聚集索引、次要索引、覆蓋索引、複合索引、前綴索引、唯一索引等。

5 索引的使用原則和注意事項

雖然索引可以加快查詢速度,提高 MySQL 的處理性能,但是過多地使用索引也會造成以下弊端:

  • 創建索引和維護索引要耗費時間,這種時間隨着數據量的增加而增加。
  • 除了數據表佔數據空間之外,每一個索引還要佔一定的物理空間。如果要建立聚簇索引,那麼需要的空間就會更大。
  • 當對錶中的數據進行增加、刪除和修改的時候,索引也要動態地維護,這樣就降低了數據的維護速度。

注意:索引可以在一些情況下加速查詢,但是在某些情況下,會降低效率。

索引只是提高效率的一個因素,因此在建立索引的時候應該遵循以下原則:

  • 在經常需要搜索的列上建立索引,可以加快搜索的速度。
  • 在作爲主鍵的列上創建索引,強制該列的唯一性,並組織表中數據的排列結構。
  • 在經常使用表連接的列上創建索引,這些列主要是一些外鍵,可以加快表連接的速度。
  • 在經常需要根據範圍進行搜索的列上創建索引,因爲索引已經排序,所以其指定的範圍是連續的。
  • 在經常需要排序的列上創建索引,因爲索引已經排序,所以查詢時可以利用索引的排序,加快排序查詢。
  • 在經常使用 WHERE 子句的列上創建索引,加快條件的判斷速度。

與此對應,在某些應用場合下建立索引不能提高 MySQL 的工作效率,甚至在一定程度上還帶來負面效應,降低了數據庫的工作效率,一般來說不適合創建索引的環境如下:

  • 對於那些在查詢中很少使用或參考的列不應該創建索引。因爲這些列很少使用到,所以有索引或者無索引並不能提高查詢速度。相反,由於增加了索引,反而降低了系統的維護速度,並增大了空間要求。

  • 對於那些只有很少數據值的列也不應該創建索引。因爲這些列的取值很少,例如人事表的性別列。查詢結果集的數據行佔了表中數據行的很大比例,增加索引並不能明顯加快檢索速度。

  • 對於那些定義爲 TEXT、IMAGE 和 BIT 數據類型的列不應該創建索引。因爲這些列的數據量要麼相當大,要麼取值很少。

  • 當修改性能遠遠大於檢索性能時,不應該創建索引。因爲修改性能和檢索性能是互相矛盾的。當創建索引時,會提高檢索性能,降低修改性能。當減少索引時,會提高修改性能,降低檢索性能。因此,當修改性能遠遠大於檢索性能時,不應該創建索引。

  • 轉載自:http://c.biancheng.net/view/2604.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章