mysql查詢選擇字段,會導(dǎo)致索引無效嗎?
本文將探討當(dāng)選取特定字段時(shí)索引失效的問題。讓我們以一個(gè)例子來說明。
假設(shè)我們有一個(gè)如下所示的sql查詢:
SELECT dl.`user_type` AS userType, dl.`user_name` AS userName, dl.`phone` AS userPhone, pc.`name` AS courtName, dl.`build_unit` AS buildName, dl.`dev_name` AS deviceName, dl.`dev_no` AS deviceNo, dl.`create_time` AS openTime, dl.`status` FROM dev_device_log dl LEFT JOIN base_project_court pc ON dl.`court_id` = pc.`id` ORDER BY dl.`id` DESC LIMIT 0, 100;
在這個(gè)查詢中,當(dāng)我們注釋掉 pc.name 字段時(shí),它能夠使用索引,但在添加該字段后問題就出現(xiàn)了。
答案在于索引類型和數(shù)據(jù)長度。索引是用于快速查找數(shù)據(jù)的樹狀數(shù)據(jù)結(jié)構(gòu),其長度限制受其包含的字段長度限制。
在這個(gè)例子中,主鍵索引是 dev_device_log 表中的 id 字段。但是,當(dāng)選擇 pc.name 字段時(shí),需要使用覆蓋索引,覆蓋索引包含查詢中所有必需的字段,以避免回表操作。
base_project_court 表中 name 字段的長度為 varchar(30),字符集為 utf8mb4。這意味著一個(gè)字符占用 4 字節(jié)。因此,索引長度為 30 * 4 + varchar 的前綴長度。
mysql 優(yōu)化器在查詢時(shí)會評估使用索引和回表的效率,在這個(gè)例子中,優(yōu)化器可能會認(rèn)為回表的效率比使用索引更高,因?yàn)樵撍饕L度較大,無法滿足覆蓋索引的要求。
通過在 id 和 name 字段上創(chuàng)建復(fù)合索引,我們可以改善這種情況。復(fù)合索引的長度較短,優(yōu)化器更愿意將其用于覆蓋索引。
綜上所述,當(dāng)查詢中選擇的字段會影響索引的長度并超出其限制時(shí),可能會導(dǎo)致索引失效。因此,在設(shè)計(jì)查詢時(shí),需要考慮字段長度和索引類型,以確保查詢性能得到優(yōu)化。