1. 程式人生 > >mysql 儲存引擎InnoDB — 索引

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 = '名字'; 

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