概述:mysql
索引(Index)是幫助MySQL高效獲取數據的數據結構。算法
索引是以表列爲基礎的數據庫對象,它保存着表中排序的索引列,而且記錄了索引列在數據表中的物理存儲位置,實現了表中數據的邏輯排序,sql
其主要目的是提升數據庫系統的性能,加快數據的查詢速度和減小系統的響應時間。數據庫
在MySQL中,索引是在存儲引擎層而不是服務器層實現的。因此每種存儲引擎的索引都不必定徹底相同。服務器
MYSQL目前提供了一下4種索引:數據結構
B-Tree 索引:最多見的索引類型,大部分引擎都支持B樹索引。Innodb 存儲引擎的 B-Tree 索引實際使用的存儲結構其實是 B+樹。
HASH 索引:只有Memory引擎支持,使用場景簡單。
R-Tree 索引(空間索引):空間索引是MyISAM的一種特殊索引類型,主要用於地理空間數據類型。
Full-text (全文索引):全文索引也是MyISAM的一種特殊索引類型,主要用於全文檢索,InnoDB從MYSQL5.6版本提供對全文索引的支持。oracle
B-Tree索引:函數
也就是一般所指的索引。性能
InnoDB使用B+Tree這種數據結構。優化
B+Tree:每個葉子節點都包含指向下一個葉子節點的指針,從而方便葉子節點的範圍遍歷。
適合查找範圍數據。好比:找出全部以I到K開頭的名字。
B-Tree索引具體又可分爲:
普通索引:
最基本的索引類型。
–直接建立索引 CREATE INDEX index_name ON table(column(length)) –修改表結構的方式添加索引 ALTER TABLE table_name ADD INDEX index_name ON (column(length)) –建立表的時候同時建立索引 CREATE TABLE `table` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL , `time` int(10) NULL DEFAULT NULL , PRIMARY KEY (`id`), INDEX index_name (title(length)) ) –刪除索引 DROP INDEX index_name ON table
惟一索引:
索引列的值必須惟一,但容許有空值(注意和主鍵不一樣)。若是是組合索引,則列值的組合必須惟一。
–建立惟一索引 CREATE UNIQUE INDEX indexName ON table(column(length)) –修改表結構 ALTER TABLE table_name ADD UNIQUE indexName ON (column(length)) –建立表的時候直接指定 CREATE TABLE `table` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL , `time` int(10) NULL DEFAULT NULL , PRIMARY KEY (`id`), UNIQUE indexName (title(length)) );
主鍵索引:
它是一種特殊的惟一索引,不容許有空值。通常是在建表的時候同時建立主鍵索引。
也能夠用 ALTER 命令,但不能用CREATE INDEX語句建立主鍵索引。
每一個表只能有一個主鍵。 (主鍵至關於聚合索引,是查找最快的索引)
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, PRIMARY KEY(ID) );
多列索引(組合索引):
ALTER TABLE table_name ADD INDEX indexName( name, address ) ;
對於多列組合的索引,若是刪除其中的某列,則該列也會從索引中刪除。若是刪除組成索引的全部列,則整個索引將被刪除。
根據數據的存儲方式的不一樣,B-Tree索引又可分爲彙集索引和非彙集索引:
CREATE CLUSTERED INDEX indexName ON mytable(mycolumn)
InnoDB的彙集索引其實是在同一個結構中保存了B-Tree索引和數據行。
由於沒法同時把數據行存放在兩個不一樣的地方,因此一個表只能有一個彙集索引。
表數據按照索引的順序來存儲的,也就是說索引項的順序與表中記錄的物理順序一致。
對於彙集索引, 葉子結點即存儲了真實的數據行,再也不有另外單獨的數據頁 。
非彙集索引 :
CREATE UNCLUSTERED INDEX indexName ON mytable(mycolumn)
表數據存儲順序與索引順序無關。
對於非彙集索引,葉結點包含索引字段值及指向數據頁數據行的邏輯指針,其行數量與數據錶行數據量一致。
可使用B-Tree索引的查詢類型,以多列索引key(last_name, first_name, dob)爲例:
B-Tree的一些限制:
哈希索引:
基於哈希表實現,只有精確匹配索引全部列的查詢纔有效。
由於它對每行中的全部索引列計算出一個哈希碼,做爲哈希表的鍵(原理是基於拉鍊法的解決碰撞的策略)。
在MySQL中只有Memory引擎顯式地支持哈希索引,Memory引擎同時也支持B-Tree索引。
InnoDB中的自適應哈希索引:某些索引值使用很是頻繁時,會在內存中基於B-Tree索引只上再建立一個hash索引。
哈希索引的一些限制:
空間數據索引(R-Tree):
ALTER TABLE table_name ADD SPATIAL INDEX indexName( line ) ;
MyISAM表支持空間索引,能夠用做地理數據存儲。
空間索引會從全部維度來索引數據,能夠有效地使用任意維度來進行組合查詢。
必須使用 GIS 相關的函數來維護數據。
全文索引:
它查找的是文本中的關鍵詞,而不是直接比較索引中的值。
使用 MATCH AGAINST,而不是普通的 WHERE。
–直接建立索引 CREATE FULLTEXT INDEX index_content ON article(content) –修改表結構添加全文索引 ALTER TABLE article ADD FULLTEXT index_content(content)
索引的優勢:
建立惟一性索引,保證數據庫表中每一行數據的惟一性
大大加快數據的檢索速度,這也是建立索引的最主要的緣由
加速表和表之間的鏈接,特別是在實現數據的參考完整性方面特別有意義。
在使用分組和排序子句進行數據檢索時,一樣能夠顯著減小查詢中分組和排序的時間。
經過使用索引,能夠在查詢的過程當中使用優化隱藏器,提升系統的性能。
索引的缺點 :
建立索引和維護索引要耗費時間,這種時間隨着數據量的增長而增長
索引須要佔物理空間,除了數據表佔數據空間以外,每個索引還要佔必定的物理空間,若是要創建聚簇索引,那麼須要的空間就會更大
當對錶中的數據進行增長、刪除和修改的時候,索引也要動態的維護,下降了數據的維護速度
應該在這些列上建立索引:
在常常須要搜索的列上,能夠加快搜索的速度;
在做爲主鍵的列上,強制該列的惟一性和組織表中數據的排列結構;
在常常用在鏈接的列上,這些列主要是一些外鍵,能夠加快鏈接的速度;
在常常須要根據範圍進行搜索的列上建立索引,由於索引已經排序,其指定的範圍是連續的;
在常常須要排序的列上建立索引,由於索引已經排序,這樣查詢能夠利用索引的排序,加快排序查詢時間;
在常用在WHERE子句中的列上面建立索引,加快條件的判斷速度。
不該該建立索引的的這些列具備下列特色:
第一,對於那些在查詢中不多使用或者參考的列不該該建立索引。這是由於,既然這些列不多使用到,所以有索引或者無索引,並不能提升查詢速度。相反,因爲增長了索引,反而下降了系統的維護速度和增大了空間需求。
第二,對於那些只有不多數據值的列也不該該增長索引。這是由於,因爲這些列的取值不多,例如人事表的性別列,在查詢的結果中,結果集的數據行佔了表中數據行的很大比例,即須要在表中搜索的數據行的比例很大。增長索引,並不能明顯加快檢索速度。
第三,對於那些定義爲text, image和bit數據類型的列不該該增長索引。這是由於,這些列的數據量要麼至關大,要麼取值不多。
第四,當修改性能遠遠大於檢索性能時,不該該建立索引。這是由於,修改性能和檢索性能是互相矛盾的。當增長索引時,會提升檢索性能,可是會下降修改性能。當減小索引時,會提升修改性能,下降檢索性能。所以,當修改性能遠遠大於檢索性能時,不該該建立索引。
較頻繁的做爲查詢條件的字段應該建立索引
定義有主鍵的數據列必定要創建索引。由於主鍵能夠加速定位到表中的某一行。
定義有外鍵的數據列必定要創建索引。外鍵列一般用於表與表之間的鏈接,在其上建立索引能夠加快表間的鏈接。
惟一性太差的字段不適合單首創建索引,即便頻繁做爲查詢條件,好比性別只有男,女
更新很是頻繁的字段不適合建立索引
不會出如今 WHERE 子句中的字段不應建立索引
表記錄比較少,例如一兩千條甚至只有幾百條記錄的表,不必建索引,讓查詢作全表掃描就行了;
對於定義爲text、image和bit數據類型的列不要創建索引。
能夠考慮使用索引的主要有 兩種類型的列:在where子句中出現的列,在join子句中出現的列,而不是在SELECT關鍵字後選擇列表的列;
使用短索引,若是對字符串列進行索引,應該指定一個前綴長度,可節省大量索引空間,提高查詢速度;好比很長的字符串,對前10個或者20個字符進行索引可以節省大量索引空間,也可能會使查詢更快。
利用最左前綴:Mysql會一直向右查找直到遇到範圍操做(>,<,like、between)就中止匹配。好比a=1 and b=2 and c>3 and d=6;此時若是創建了(a,b,c,d)索引,那麼後面的d索引是徹底沒有用到,當換成了(a,b,d,c)就能夠用到。
MySQL只對一下操做符才使用索引:<,<=,=,>,>=,between,in, 以及某些時候的like(不以通配符%或_開頭的情形)。
不要過分索引,只保持所需的索引。每一個額外的索引都要佔用額外的磁盤空間,並下降寫操做的性能。 在修改表的內容時,索引必須進行更新,有時可能須要重構,所以,索引越多,所花的時間越長。
惟一索引與主鍵索引的比較:
Hash索引和btree索引的區別: