一、簡介
索引類似於書籍的目錄,要想找到一本書的某個特定主題,需要先查找書的目錄,定位對應的頁碼。
存儲引擎使用類似的方式進行數據查詢,先去索引當中找到對應的值,然後根據匹配的索引找到對應的數據行。一般來說,在WHERE和JOIN中出現的列需要建立索引,但也不完全如此,因爲MySQL只對<,<=,=,>,>=,BETWEEN,IN,以及某些時候的LIKE纔會使用索引。
索引有很多種類型,都是實現在存儲引擎層的。Mysql主要支持如下幾種索引:
1)普通索引
2)唯一索引
3)主鍵索引
4)組合索引
5)全文索引
二、語法
CREATE TABLE table_name[col_name data type]
[unique|fulltext][index|key][index_name](col_name[length])[asc|desc]
1)unique|fulltext爲可選參數,分別表示唯一索引、全文索引
2)index和key爲同義詞,兩者作用相同,用來指定創建索引
3)col_name爲需要創建索引的字段列,該列必須從數據表中該定義的多個列中選擇
4)index_name指定索引的名稱,爲可選參數,如果不指定,默認col_name爲索引值
5)length爲可選參數,表示索引的長度,只有字符串類型的字段才能指定索引長度
6)asc或desc指定升序或降序的索引值存儲
例 :
# 1)添加INDEX(普通索引)
mysql>ALTER TABLE `table_name` ADD INDEX index_name ( `column` )
# 2)添加UNIQUE(唯一索引)
mysql>ALTER TABLE `table_name` ADD UNIQUE ( `column`)
# 3)添加PRIMARY KEY(主鍵索引)
mysql>ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` )
# 4)添加組合索引
mysql>ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`)
# 5)添加FULLTEXT(全文索引)
mysql>ALTER TABLE `table_name` ADD FULLTEXT ( `column`)
相關操作:
# 查看錶結構
desc table_name;
# 查看生成表的SQL
show create table table_name;
# 查看索引
show index from table_name;
show keys from table_name;
# 查看執行時間
set profiling = 1;
SQL...
show profiles;
# 查看索引的使用情況
show status like '%Handler_read%' ;
三、索引的機制
傳統的查詢方法,是按照表的順序遍歷的,不論查詢幾條數據,mysql需要將表的數據從頭到尾遍歷一遍。在我們添加完索引之後,mysql一般通過BTREE算法生成一個索引文件,在查詢數據庫時,找到索引文件進行遍歷(折半查找大幅查詢效率),找到相應的鍵從而獲取數據。
1、索引對性能的影響:
1)創建索引是爲產生索引文件的,佔用磁盤空間
2)大大減少服務器需要掃描的數據量
3)幫助服務器避免排序和臨時表
4)將隨機I/O變順序I/O
5)雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對錶進行insert、update和delete。因爲更新表時,不僅要保存數據,還要保存一下索引文件(因爲dml操作同樣也會對索引文件進行修改)。
2、在哪些column上使用索引:
1)較頻繁的作爲查詢條件字段應該創建索引
2)唯一性太差的字段不適合創建索引,儘管頻繁作爲查詢條件,例如gender性別字段
3)更新非常頻繁的字段不適合作爲索引
4)不會出現在where子句中的字段不該創建索引
3、索引的創建原則:
1)最適合索引的列是出現在WHERE子句中的列,或連接子句中的列而不是出現在SELECT關鍵字後面的列。
2)索引列的基數越大,索引的效果越好。
3)對字符串進行索引,應該制定一個前綴長度,可以節省大量的索引空間
4)根據情況創建複合索引,複合索引可以提高查詢效率
5)避免創建過多索引,索引會額外佔用磁盤空間,降低寫操作效率
6)主鍵儘可能選擇比較短的數據類型,可以有效減少索引的磁盤佔用,提高查詢效率。
4、索引的使用場景
1)對於非常小的表,大部分情況下全表掃描效率更高
2)中到大型表,索引非常有效
3)特大型的表,建立和使用索引的代價將隨之增長,可以使用分區技術來解決
四、索引類型
1、普通索引
是最基本的索引,它沒有任何限制。它有以下幾種創建方式:
1)直接創建索引
CREATE INDEX index_name ON `table` (`column`(length));
2)修改表結構的方式添加索引
ALTER TABLE `table_name` ADD INDEX index_name (`column`(length))
3)創建表的時候同時創建索引
CREATE TABLE `c` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) NOT NULL ,
`content` text NULL ,
PRIMARY KEY (`id`),
INDEX title (`title`(5))
);
4)刪除索引
DROP INDEX index_name ON `table`;
2、唯一索引
與前面的普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。
1)創建唯一索引
CREATE UNIQUE INDEX index_name ON `table` (`column`(length));
2)修改表結構
ALTER TABLE `table_name` ADD UNIQUE index_name (`column`(length));
3)創建表的時候直接指定
CREATE TABLE `d` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) NOT NULL ,
`content` text NULL ,
`time` int(10) NULL DEFAULT NULL ,
PRIMARY KEY (`id`),
UNIQUE title (`title`(5))
);
3、主鍵索引
是一種特殊的唯一索引,一個表只能有一個主鍵,不允許有空值。主鍵可以與外鍵構成參照完整性約束,防止數據不一致。
一般是在建表的時候同時創建主鍵索引:
CREATE TABLE `e` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) NOT NULL ,
PRIMARY KEY (`id`)
);
4、組合索引
將多個列組合在一起創建索引。
只有在查詢條件中使用了創建索引時的第一個字段,索引纔會被使用。使用組合索引時遵循最左前綴集合。
ALTER TABLE `table` ADD INDEX name_city_age (`name`,`city`,`age`);
5、全文索引
MySQL自帶的全文索引只能用於MyISAM,對文本的內容進行分詞,進行搜索。
主要用來查找文本中的關鍵字,而不是直接與索引中的值相比較。fulltext索引跟其它索引大不相同,它更像是一個搜索引擎,而不是簡單的where語句的參數匹配。fulltext索引配合match against操作使用,而不是一般的where語句加like。它可以在create table,alter table ,create index使用,不過目前只有char、varchar,text 列上可以創建全文索引。值得一提的是,在數據量較大時候,現將數據放入一個沒有全局索引的表中,然後再用CREATE index創建fulltext索引,要比先爲一張表建立fulltext然後再將數據寫入的速度快很多。
1)創建表的時候添加全文索引
CREATE TABLE `article` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) NOT NULL ,
`content` text NULL ,
`time` int(10) NULL DEFAULT NULL ,
PRIMARY KEY (`id`),
FULLTEXT (content)
);
2)修改表結構添加全文索引
ALTER TABLE `article` ADD FULLTEXT index_content (`content`);
3)直接創建索引
CREATE FULLTEXT INDEX index_content ON `article` (`content`);
6、外鍵
用於建立和加強兩個表數據之間的鏈接的一列或多列。外鍵約束主要用來維護兩個表之間數據的一致性。簡言之,表的外鍵就是另一表的主鍵,外鍵將兩表聯繫起來。一般情況下,要刪除一張表中的主鍵必須首先要確保其它表中的沒有相同外鍵。比如,A表中的一個字段,是B表的主鍵,那他就可以是A表的外鍵。
外鍵的使用條件:
① 兩個表必須是InnoDB表,MyISAM表暫時不支持外鍵
② 外鍵列必須建立了索引,MySQL 4.1.2以後的版本在建立外鍵時會自動創建索引,但如果在較早的版本則需要顯式建立;
③ 外鍵關係的兩個表的列必須是數據類型相似,也就是可以相互轉換類型的列,比如int和tinyint可以,而int和char則不可以;
五、注意事項
1、複合索引遵循前綴原則
# 如複合索引:KEY(a,b,c)
# 如下查詢方式索引有效:
WHERE a = 1 and b = 2 and c = 3
WHERE a = 1 and b = 2
WHERE a = 1
# 如下方式索引無效:
WHERE b = 2 and c = 3
WHERE a = 1 and c = 3
2、以通配符%和_開頭作查詢時,MySQL不會使用索引。
3、column is null 可以使用索引
4、如果MySQL估計使用索引比全表掃描更慢,會放棄使用索引
5、如果or前的條件中的列有索引,後面的沒有,索引都不會被用到
6、列類型是字符串,查詢時一定要給值加引號,否則索引失效
7、不要在索引列上進行運算,這將導致索引失效,如:
SELECT * FROM table_name WHERE YEAR(column_name)<2017;
六、經典實例
1、簡單描述MySQL中,索引,主鍵,唯一索引,聯合索引的區別,對數據庫的性能有什麼影響?
2、創建MySQl複合索引應該注意哪些事項?
[答案參考本文]
參考
1、《高性能MySQL》 [美]Baron Scbwartz, Peter Zaitsev, Vadim Tkacbenko 著
2、 蹲廁所的熊:MySQL索引原理以及慢查詢優化