mysql 儲存引擎InnoDB — 索引
mysql 儲存引擎Innodb — 索引
簡介: 索引可以包含一個或多個列的值。如果索引包含多個列,那麼列的順序也十分重要。MySQL只能高效地使用索引的最左字首列。下面會有詳細的介紹。 大家都知道索引能讓伺服器快速定位到表的指定位置,但著不是所有的唯一作用。使用索引有如下三大優點:
- 索引大大減少了伺服器需要掃描的資料量。
- 索引可以幫助伺服器避免排序和臨時表。
- 索引可以講隨機I/O變為順序IO。
一、索引型別
1. B+樹索引(btree索引) B+樹索引是最為常用的,也是最有效的索引。B+樹最早是從平衡二叉樹演化過來的,但不是二叉樹。B+樹通常意味著所有的值都是按順序儲存的,並且每個葉子頁到根的距離相同。 注意:B+樹索引不能找到一個給定值的具體行,只能找到被查詢資料行所在的頁。資料庫把頁讀到記憶體,在記憶體中搜索需要查詢的資料。
下圖展示了b+樹索引的抽象表示(圖片來源:高效能mysql第三版):
B+樹索引分為兩種:
- 聚集索引 按照每張表的主鍵構造一顆B+樹,葉子節點存放整張表的行記錄資料,也將聚集索引的葉子節點成為資料頁。
- 輔助索引 輔助索引也稱非聚集索引,葉子節點不包含行記錄的全部資料,每個節點包含一個書籤(bookmark),該書籤儲存了相應行資料的聚集索引鍵。
2. hash索引
InnoDB支援的hash索引是自適應的(自適應雜湊索引,Adaptive Hash Index, AHI),InnoDB會根據表的使用情況,自動為表生成hash索引,不能人為干預。
hash索引只能用於等值查詢,例如:select x from xxxx where xx = xxx
where xx > xxx
)
# 檢視當前hash索引使用情況
show engine innodb status
# 檢視AHI是否啟用 預設啟用ON,如若想關閉,將ON改為OFF
show variables like 'innodb_adaptive_hash_index'
3. 全文索引 全文索引是一種特殊型別的索引,它查詢的是文字中的關鍵詞,而不是直接比較索引中的值。MySQL5.6以後,innodb支援全文索引 在相同列上同時建立全文索引和B+樹索引不會有衝突,適用於Match Against操作,而不是普通的where條件操作。
使用全文索引
# 建立文章表,指定使用InnoDB引擎,title、content新增全文索引
CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
content TEXT,
FULLTEXT (title,content)
) ENGINE=InnoDB CHARACTER SET utf8mb4;
# 插入十萬條資料(測試全文索引查詢效率,多插點資料。這裡使用儲存函式)
# 對儲存過程不熟悉的,可以看下我另一篇部落格
# https://blog.csdn.net/hhy107107/article/details/81269946
delimiter ;;
CREATE procedure insert_more ()
BEGIN
DECLARE i int DEFAULT 1;
WHILE i < 100000
DO
INSERT INTO articles(id, title, content) values (null, 'title', REPEAT('content',7000));
SET i = i + 1;
END WHILE;
COMMIT;
END;;
delimiter ;
# 執行插入
call insert_more
# 隨便往其中一條記錄的content欄位的內容中加測試兩個字
# 普通查詢,不走索引
[SQL] SELECT * FROM articles WHERE content like '%測試%'
受影響的行: 0
時間: 44.967s
# 使用全文索引
[SQL] SELECT * FROM articles WHERE MATCH (title,content) AGAINST ('測試' IN boolean MODE);
受影響的行: 0
時間: 0.195s
二、組合索引
- 組合索引 一個索引包含多個列
現有一個people表, 有一個組合索引,包含三個列
create table people (
last_name varchar(50) not null,
first_name varchar(50) not null,
dob date not null,
gender enum('m', 'f') not null,
key(last_name, first_name, dob)
)
上表建的索引,對如下型別的查詢有效
- 全值匹配 可以用於查詢姓xx,名xx,出生於xx的人
- 匹配最左字首 可以用於查詢姓xx的人,即只使用索引的第一列
- 匹配列字首 可以匹配某一列的值的開頭部分。例如可以查詢姓氏為X頭的人
- 匹配範圍值 可以查詢姓X和XX之間的人
- 精確匹配某一列並範圍匹配另外一列
可以匹配姓X名字X開頭的人,即
last_name
全匹配,first_name
範圍匹配 - 只訪問索引的查詢 查詢只需要訪問索引,無需訪問資料行
索引查詢的限制
- 如果不是從索引的最左列開始查詢,不能使用索引。
例如,上表不能用索引查詢
first_name
為x的人,也不能查出生於X的人。因為這兩列不是最左資料列。也無法查詢姓氏以X結尾的人。 - 不能跳列索引 也就是說不能查詢姓X,出生於XX的人,如果不指定名,只能索引姓,不能索引出生日期。
- 如果查詢的某個列是範圍查詢,其右邊的列無法索引。
例如,
where last_name = 'x' and first_name like 'J%' and dob = 'xx'
這個查詢,只能索引last_name
和first_name
,不能索引dob
三、其他
1.索引設計原則
- 最適合建索引的列是where子句後面的列和連線子句中指定的列。
- 使用唯一索引。考慮某列中值的分佈。對於唯一值的列,索引效果最好,具有多個重複值的列,索引效果最差。比如記錄性別的列,此列值只有‘M’,‘F’,對此列索引沒多大用,不管搜哪個,都回得出大約一半的行。
- 使用短索引。例如有個char(200)的列,列值前10的值多數都是唯一的,那麼就不要對整列進行索引,只對列的前10個字元索引
2.不能使用索引的情況
- 如果mysql查詢的列不是獨立的,不能使用索引。索引列不能是表示式的一部分,也不能是函式的引數。
例如:
select user_id from user where user_id + 1 = 5
;
3.索引提示 mysql 支援索引提示(index hint),顯式的告訴優化器使用哪個索引。 當某條sql語句可以選擇的索引非常多,優化器選擇執行計劃的時間開銷可能會比較大。這時候,我們可以強制讓優化器不進行執行路徑的成本分析,直接使用指定的索引進行查詢
# 指定使用firstName索引 firstName是索引名稱
SELECT * FROM `user` force index (firstName) WHERE last_name = '姓氏' and first_name = '名字';
# 使用explain關鍵字檢視執行計劃 結果中,possible_keys為可選擇的索引, key表示當前使用的索引
explain SELECT * FROM `user` force index (firstName) WHERE last_name = '姓氏' and first_name = '名字';
[1]姜承堯 .MySQL技術內幕:InnoDB儲存引擎 機械工業出版社 [2]高效能MySQL 第三版:電子工業出版社