18.MySQL組合索引與最左匹配原則詳解[高性能Mysql+網(wǎng)絡(luò)資源整理]

前言

之前在網(wǎng)上看到過很多關(guān)于mysql聯(lián)合索引最左前綴匹配的文章,自以為就了解了其原理,最近面試時(shí)和面試官交流,發(fā)現(xiàn)遺漏了些東西,這里自己整理一下這方面的內(nèi)容。

什么時(shí)候創(chuàng)建組合索引?

當(dāng)我們的where查詢存在多個(gè)條件查詢的時(shí)候,我們需要對(duì)查詢的列創(chuàng)建組合索引

為什么不對(duì)沒一列創(chuàng)建索引

  • 減少開銷
  • 覆蓋索引
  • 效率高

減少開銷:假如對(duì)col1、col2、col3創(chuàng)建組合索引,相當(dāng)于創(chuàng)建了(col1)、(col1,col2)、(col1,col2,col3)3個(gè)索引
覆蓋索引:假如查詢SELECT col1, col2, col3 FROM 表名,由于查詢的字段存在索引頁中,那么可以從索引中直接獲取,而不需要回表查詢

效率高:對(duì)col1、col2、col3三列分別創(chuàng)建索引,MySQL只會(huì)選擇辨識(shí)度高的一列作為索引。假設(shè)有100w的數(shù)據(jù),一個(gè)索引篩選出10%的數(shù)據(jù),那么可以篩選出10w的數(shù)據(jù);對(duì)于組合索引而言,可以篩選出100w10%10%*10%=1000條數(shù)據(jù)

最左匹配原則

假設(shè)我們創(chuàng)建(col1,col2,col3)這樣的一個(gè)組合索引,那么相當(dāng)于對(duì)col1列進(jìn)行排序,也就是我們創(chuàng)建組合索引,以最左邊的為準(zhǔn),只要查詢條件中帶有最左邊的列,那么查詢就會(huì)使用到索引

創(chuàng)建測(cè)試表

CREATE TABLE `student` (
 `id` int(11) NOT NULL,
 `name` varchar(10) NOT NULL,
 `age` int(11) NOT NULL,
 PRIMARY KEY (`id`),
 KEY `idx_id_name_age` (`id`,`name`,`age`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

填充100w測(cè)試數(shù)據(jù)

DROP PROCEDURE pro10;
CREATE PROCEDURE pro10()
BEGIN
    DECLARE i INT;
    DECLARE char_str varchar(100) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    DECLARE return_str varchar(255) DEFAULT '';
    DECLARE age INT;
    SET i = 1;
    WHILE i < 5000000 do
        SET return_str = substring(char_str, FLOOR(1 + RAND()*62), 8);
        SET i = i+1;
        SET age = FLOOR(RAND() * 100);
        INSERT INTO student(id, name, age) values(i, return_str, age);
    END WHILE;
END;
 
CALL pro10();

場(chǎng)景測(cè)試

可以看到以下查詢都使用到了索引

EXPLAIN SELECT * FROM student WHERE id = 2;

EXPLAIN SELECT * FROM student WHERE id = 2 AND name = 'defghijk';

EXPLAIN SELECT * FROM student WHERE id = 2 AND age = 8;

EXPLAIN SELECT * FROM student WHERE id = 2 AND name = 'defghijk' and age = 8;

可以看到如上查詢也使用到了索引,id放前面和放后面查詢到的結(jié)果是一樣的,MySQL會(huì)找出執(zhí)行效率最高的一種查詢方式,就是先根據(jù)id進(jìn)行查詢

EXPLAIN SELECT * FROM student WHERE name = 'defghijk' AND id = 2;
EXPLAIN SELECT * FROM student WHERE age = 8 AND id = 2;
EXPLAIN SELECT * FROM student WHERE name = 'defghijk' and age = 8 AND id = 2;

可以看到該查詢沒有使用到索引,類型為index,查詢行數(shù)為4989449,幾乎進(jìn)行了全表掃描,由于組合索引只針對(duì)最左邊的列進(jìn)行了排序,對(duì)于name、age只能進(jìn)行全部掃描

EXPLAIN SELECT * FROM student WHERE name = 'defghijk' AND age = 8;

總結(jié)

如上測(cè)試,可以看到只要查詢條件的列中包含組合索引最左邊的那一列,不管該列在查詢條件中的位置,都會(huì)使用索引進(jìn)行查詢

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容