覆蓋索引是一種特殊的復(fù)合索引,所有查詢的列都包括在索引中濒蒋。這種情況下盐碱,MySQL 能直接從索引返回?cái)?shù)據(jù)把兔,不用訪問行數(shù)據(jù)。
考慮一種情形瓮顽,我們不使用SELECT * FROM Country
县好,而只需要國(guó)家的名稱。例子12展示了暖混,復(fù)合索引(大洲缕贡,人口,名稱)能夠用上前兩列來過濾行拣播,然后從第 3 列返回值晾咪。
例子12:使用3列覆蓋索引
ALTER TABLE Country ADD INDEX c_p_n (Continent,Population,Name);
EXPLAIN FORMAT=JSON
SELECT Name FROM Country WHERE continent='Asia' and population > 5000000;
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "8.07" # 查詢代價(jià)進(jìn)一步減少了 67%
},
"table": {
"table_name": "Country",
"access_type": "range",
"possible_keys": [
"p",
"c",
"p_c",
"c_p",
"c_p_n"
],
"key": "c_p_n",
"used_key_parts": [
"Continent",
"Population"
],
"key_length": "5",
"rows_examined_per_scan": 32,
"rows_produced_per_join": 15,
"filtered": "100.00",
"using_index": true, # 表明是覆蓋索引
"cost_info": {
"read_cost": "1.24",
"eval_cost": "3.09",
"prefix_cost": "8.07",
"data_read_per_join": "3K"
},
"used_columns": [
"Name",
"Continent",
"Population"
],
"attached_condition": "((`world`.`Country`.`Continent` = 'Asia') and (`world`.`Country`.`Population` > 5000000))"
}
}
}
EXPLAIN 中的using_index
表示使用了覆蓋索引。它是一項(xiàng)被低估了的優(yōu)化诫尽,許多從業(yè)者不正確地認(rèn)為覆蓋索引能讓代價(jià)減少為一半禀酱,因?yàn)椴挥迷L問行。而在例子12中我們看到其代價(jià)相比例子11減少到了三分之一牧嫉。
在生產(chǎn)環(huán)境中剂跟,由于索引的聚集效果,覆蓋索引可能更好地利用內(nèi)存空間酣藻。然而曹洽,如果次級(jí)索引與聚集索引(主鍵)沒有關(guān)聯(lián),就會(huì)有多得多的頁需要被訪問辽剧。
(這里的 “關(guān)聯(lián)” 是指 “大致遵循一樣的順序”送淆。例如,一個(gè)時(shí)間戳的次級(jí)索引會(huì)與自增主鍵有很高的關(guān)聯(lián)怕轿;而人口和大洲與國(guó)家編號(hào)就沒有什么關(guān)聯(lián)偷崩。)
譯自:
Covering Indexes - The Unofficial MySQL 8.0 Optimizer Guide