mysql 存儲引擎InnoDB(二)索引

mysql 存儲引擎Innodb — 索引

簡介:
索引可以包含一個或多個列的值。如果索引包含多個列,那麼列的順序也十分重要。MySQL只能高效地使用索引的最左前綴列。下面會有詳細的介紹。
大家都知道索引能讓服務器快速定位到表的指定位置,但這不是索引的唯一作用。使用索引有如下三大優點:

  1. 索引大大減少了服務器需要掃描的數據量。
  2. 索引可以幫助服務器避免排序和臨時表。
  3. 索引可以講隨機I/O變爲順序IO。

一、索引類型

1. B+樹索引(btree索引)
B+樹索引是最爲常用的,也是最有效的索引。B+樹最早是從平衡二叉樹演化過來的,但不是二叉樹。B+樹通常意味着所有的值都是按順序存儲的,並且每個葉子頁到根的距離相同。
注意:B+樹索引不能找到一個給定值的具體行,只能找到被查找數據行所在的頁。數據庫把頁讀到內存,在內存中搜索需要查找的數據。

下圖展示了b+樹索引的抽象表示(圖片來源:高性能mysql第三版):
mysql B+樹索引

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)
)

上表建的索引,對如下類型的查詢有效

  1. 全值匹配
    可以用於查找姓xx,名xx,出生於xx的人
  2. 匹配最左前綴
    可以用於查找姓xx的人,即只使用索引的第一列
  3. 匹配列前綴
    可以匹配某一列的值的開頭部分。例如可以查找姓氏爲X頭的人
  4. 匹配範圍值
    可以查找姓X和XX之間的人
  5. 精確匹配某一列並範圍匹配另外一列
    可以匹配姓X名字X開頭的人,即last_name 全匹配,first_name 範圍匹配
  6. 只訪問索引的查詢
    查詢只需要訪問索引,無需訪問數據行

索引查詢的限制

  1. 如果不是從索引的最左列開始查找,不能使用索引。
    例如,上表不能用索引查詢first_name爲x的人,也不能查出生於X的人。因爲這兩列不是最左數據列。也無法查詢姓氏以X結尾的人。
  2. 不能跳列索引
    也就是說不能查詢姓X,出生於XX的人,如果不指定名,只能索引姓,不能索引出生日期。
  3. 如果查詢的某個列是範圍查詢,其右邊的列無法索引。
    例如,where last_name = 'x' and first_name like 'J%' and dob = 'xx' 這個查詢,只能索引last_namefirst_name,不能索引dob

三、其他

1.索引設計原則

  1. 最適合建索引的列是where子句後面的列和連接子句中指定的列。
  2. 使用唯一索引。考慮某列中值的分佈。對於唯一值的列,索引效果最好,具有多個重複值的列,索引效果最差。比如記錄性別的列,此列值只有‘M’,‘F’,對此列索引沒多大用,不管搜哪個,都回得出大約一半的行。
  3. 使用短索引。例如有個char(200)的列,列值前10的值多數都是唯一的,那麼就不要對整列進行索引,只對列的前10個字符索引

2.不能使用索引的情況

  1. 如果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 = '名字'; 

Mysql InnoDB介紹
https://blog.csdn.net/hhy107107/article/details/82703926

MySQL 存儲過程
https://blog.csdn.net/hhy107107/article/details/81269946


[1]姜承堯 .MySQL技術內幕:InnoDB存儲引擎 機械工業出版社
[2]高性能MySQL 第三版:電子工業出版社

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