前綴索引
一個(gè)字符串列太長(zhǎng),使用整列作為索引膏执,太占空間。如果這個(gè)字符串使用到了前綴進(jìn)行匹配查詢或者查詢整個(gè)字符串(例如:where address like "guizhou%"),可以考慮使用前綴索引菜职。前綴索引選擇的長(zhǎng)度,取決于長(zhǎng)度多少的字符串能夠?qū)?shù)據(jù)庫(kù)里的所有字符串盡量區(qū)分開來(lái)肉微。
為了更好的理解區(qū)分度(選擇性)匾鸥,用一個(gè)例子說(shuō)明一下:
dabcjm,daacdb,dajbac,dbdcmk,dbjkac,dbmjdf
如果只索引了長(zhǎng)度為1的前綴字符,那么索引就沒(méi)有意義碉纳,因?yàn)?個(gè)字符串的索引都是d.而索引2個(gè)字符勿负,有三個(gè)是da,三個(gè)是db劳曹。索引3個(gè)字符的話奴愉,6個(gè)字符就完全區(qū)分開來(lái)了。
多列索引
如果where查詢語(yǔ)句有多個(gè)條件铁孵,需要考慮添加多列索引锭硼,而不是多個(gè)單列索引。由于InnDB的索引查詢方式蜕劝。多個(gè)單列索引檀头,查詢方式是查詢每個(gè)單列索引,并合并結(jié)果集岖沛,效果肯定比多列索引要差暑始,可能性能還不如不加索引。
如果查詢中只使用到部分索引婴削,那么使用到索引最前列的廊镜,才會(huì)走索引查詢。
看一個(gè)例子唉俗。
select user_name, phone_num from user
where user_name = 'jack' and phone_num = '13709178888';
如果建立user_name,phone_num索引嗤朴,user_name放在索引的最前面。那么
select user_name, phone_num from user
where user_name = 'jack';
是可以使用到索引的互躬,而
select user_name, phone_num from user
where phone_num = '13709178888';
不會(huì)使用到索引播赁。
通常情況下,選擇區(qū)分度高的索引作為索引的最前列吼渡。
聚集索引
聚集索引是在索引的葉子節(jié)點(diǎn)存儲(chǔ)了所有的字段數(shù)據(jù)容为。InnDB主鍵上才建聚集索引。
InnDB 的索引(包括聚集索引和非聚集索引)的葉子節(jié)點(diǎn)都會(huì)存儲(chǔ)主鍵值,而MyISAM引擎葉子節(jié)點(diǎn)會(huì)存儲(chǔ)表記錄的指針坎背。
覆蓋索引
如果某個(gè)查詢只使用了索引的值替劈,那么稱這個(gè)查詢?yōu)槭褂昧烁采w索引的查詢。
select user_name, phone_num from user
where user_name = 'jack' and phone_num = '13709178888';
如果建了一個(gè)多列索引得滤,索引列為user_name,和phone_num.那么這個(gè)查詢就用了覆蓋索引陨献。
覆蓋索引如果加上延遲查詢的策略(見《高性能MySQL》),往往能很管用。
覆蓋索引是非常有用的工具懂更,可以極大的提高性能眨业,因?yàn)椴樵冎恍枰獟呙杷饕龝?huì)帶來(lái)許多好處:
1、索引條目遠(yuǎn)小于數(shù)據(jù)行大小沮协,如果只讀取索引龄捡,極大減少數(shù)據(jù)訪問(wèn)量
2、索引是有按照列值順序存儲(chǔ)的慷暂,對(duì)于I/O密集型的范圍查詢要比隨機(jī)從磁盤讀取每一行數(shù)據(jù)的IO要少的多