在上述那個表中,如果執行了select * from t where k between 3 and 5,需要執行幾次樹的搜尋操作,會掃瞄多少行?
表的初始化語句:
現在看看select * from t where k between 3 and 5這條sql查詢語句的執行流程:
1、在k索引樹上找到k=3記錄,取得id=300
2、再到id索引樹上查到id=300對應r3
3、在k索引樹取下乙個值k=5,取得id=500
4、再回到id索引樹查到id=500對應的r4
5、在k索引樹取下乙個值k=6,不滿足條件,迴圈結束
回到主鍵索引樹搜尋的過程,稱為回表。這個查詢過程讀了k索引樹的3條記錄(步驟1、3和5),回表了兩次(步驟2、4)。
如果執行 select id from t where k between 3 and 5,這時只需要查id的值,而id的值已經在k索引樹上了,因此可以直接提供查詢結果,不需要回表。也就是說,在這個查詢裡面,索引k已經「覆蓋了」查詢需求,稱為覆蓋索引。
由於覆蓋索引可以減少樹的搜尋次數,顯著提公升查詢效能,所以使用覆蓋索引是乙個常用的效能優化手段。
在乙個市民資訊表上,是否有必要將身份證號和名字建立聯合索引?
假設市民表的定義是這樣的:
create table `tuser` (
`id` int(11) not null,
`id_card` varchar(32) default null,
`name` varchar(32) default null,
`age` int(11) default null,
`ismale` tinyint(1) default null,
primary key (`id`),
key `id_card` (`id_card`),
key `name_age` (`name`,`age`)
) engine=innodb
如果根據身份證號查詢市民資訊的需求,只需要在身份證號上面建立索引就夠了。而再建立乙個(身份證號、名字)的聯合索引,是不是浪費空間?
如果有乙個高頻請求,要根據市民的身份證號來查詢姓名,這個聯合索引就有意義,它可以在這個高頻請求上用到覆蓋索引,不再需要回表查整行記錄,減少語句的執行時間。
當然索引欄位的維護是有代價的。建立冗餘索引來支援覆蓋索引時就需要權衡考慮。
b+樹這種索引結構,可以利用索引的「最左字首」,來定位記錄。
用(name, age)這個聯合索引來分析。
索引項是按照索引定義裡面出現的字段順序排序的。
當查詢所有名字是「張三」的人時,可以快速定義到id4,然後向後遍歷得到所有需要的結果。
如果要查的所有名字第乙個字是「張」。那條件為「 where name like '張 %' 」。這時查詢到第乙個符合條件的記錄是id3,然後向後遍歷,直到不滿足條件為止。
這個最左字首可以是聯合索引的最左n個字段,也可以是字串索引的最左m個字元。
所以在建立聯合索引時,如何安排索引內的字段順序?
第一原則是,如果通過調整順序,可以少維護乙個索引,那麼這個順序往往就是需要優先考慮採用的。
查詢條件裡面只有b的語句,是無法使用(a,b)這個聯合索引的,這時不得不維護另外乙個索引,也就是說需要同時維護(a,b)(b)這兩個索引。
這時候需要考慮的就是空間。比如name欄位是比age欄位大的,那就建議建立乙個(name,age)的聯合索引和乙個(age)單字段索引。
以上面的聯合索引(name, age)為例。如果現在有乙個需求:檢索出表中"名字第乙個字是張,而且年齡是10歲的所有男孩"。那麼,sql語句:
mysql> select * from tuser where name like '張 %' and age=10 and ismale=1;
由字首索引規則,用「張」,找到第乙個滿足條件的記錄id3。然後判斷其他條件是否滿足。
mysql5.6引入的索引下推優化(index condition pushdown),可以在索引遍歷過程中,對索引中包含的字段先做判斷,直接過濾掉不滿足條件的記錄,減少回表次數。
無索引下推:
這個圖中特意去掉了age的值,是因為innodb並不會去看age的值,只是按順序把「name第乙個字是『張』 」的記錄一條條取出來回表。因此,需要回表4次。
索引下推:
上兩個圖中,每乙個虛線代表回表一次。
這個圖中對於不等於10的直接跳過,所以只需要回表2次。
mysql索引下推 MySQL中的索引下推
前段時間看了一下資料庫相關知識,出現了索引下推這個名詞,有必要記錄下來作為知識儲備。索引下推用一句話總結是 索引下推是資料庫檢索資料過程中為減少回表次數而做的優化。首先介紹下什麼是資料庫回表,回表是一種資料庫檢索過程。通常發生在使用二級索引檢索非主索引資料的過程中。舉個例子 usertest資料表 ...
MySQL學習筆記(四)索引(上)
經常可能發生,某個sql查詢比較慢,分析完原因後,可能就會想到 給某個欄位加個索引 這樣的方案。索引的出現就是為了提高資料查詢的效率。實現索引的方式有很多種,所以這裡也就引入了索引模型。比較常見的,雜湊表 有序陣列和搜尋樹。雜湊表以鍵值對儲存資料,只要輸入對應的key,就可以找到對應的value。雜...
學習筆記 mysql索引(四) 多列索引
多列索引有兩個意思,乙個是在多個列上建立乙個索引,另乙個意思是在多個列上分別建立索引。比較直觀能夠想到,如果是在多個列上建立乙個索引,那麼如果where條件裡正好又是這些列,那麼將獲得較好的效能。如果分別建立索引,where中又有多個分別建立的索引的列,那mysql優化器將如何處理呢?explain...