高性能MySQL05-索引原理

一、簡介

索引類似於書籍的目錄,要想找到一本書的某個特定主題,需要先查找書的目錄,定位對應的頁碼。

存儲引擎使用類似的方式進行數據查詢,先去索引當中找到對應的值,然後根據匹配的索引找到對應的數據行。一般來說,在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索引原理以及慢查詢優化

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