索引具有時間和空間上的代價,
空間上的代價:每建立一個索引,都會建立一棵B+樹,每一棵B+樹的每個節點都是一個資料頁,一個資料頁會默認占用16KB的存盤空間,一棵很大的B+樹由很多資料頁組成,這將占用很大一片空間,
時間上的代價:每當對表中的資料進行增刪改查操作時,都需要修改各個B+樹索引,存盤引擎需要額外的時間進行頁面 分裂,頁面回收等操作,以維護節點和記錄的排序,
掃描區間和邊界條件
select * from single_table where id>=2 and id<=100;
比如上面陳述句中,與掃描全部的聚簇索引相比,掃描id值在[2,100]區間中中的記錄資料已經很大程度上減少了需要掃描的數量,所以提高了查詢效率,
我們把只包含一個值的掃描區間稱為單點掃描區間,
包含多個值的掃描區間稱為范圍掃描區間,
如果想使用某個索引來執行查詢,但是又無法通過搜索條件形成合適的掃描區間來減少需要掃描的數量的時,則不考慮使用這個索引執行查詢 ,
對于B+樹索引來說,只要索引列和常數使用=、<=>、IN、NOT IN、IS NULL、IS NOT NULL、>、<、>=、<=、BETWEEN、!=或者LIKE運算子連接起來,就可以產生所謂的掃描區間,不過有些需要注意:
- IN運算子的語意與若干個等值匹配運算子(
=)之間用OR連接起來的語意是一樣的, !=產生的掃描區間容易被忽略,比如:
select * from single_table where id != 2 ;
此時的掃描區間是(-∞,2)和(2,+∞),
- LIKE運算子只有在匹配完整的字串或者匹配的字串的前綴才產生合適的掃描區間,
使用聯合索引執行查詢時對應的掃描區間
假設為表中的key_part1,key_part2,key_part3列建立idx_key_part二級索引,
先按著key_part1列的值排序,在key_part1列的值相同的情況下,再按照key_part2列的值排序,在key_part1列的值和key_part2列的值相同的情況下,再按照key_part3列的值排序,
- 對于查詢陳述句:
select * from single_table where key_part1 = 'a' and key_part3 = 'c';
對于符合key_part1 = 'a'條件的二級索引記錄,并不是直接按照key_part3列的值進行排序的,我們若想使用idx_key_part索引,可以定位到key_part1 = 'a'的第一條記錄,然后沿著記錄所在鏈表向后掃描,所以這個掃描區間是['a','a'],
- 對于查詢陳述句:
select * from single_table where key_part1 < 'b' and key_part2 = 'a';
對于符合key_part1 < 'b'條件的二級索引記錄,并不是直接按照key_part2列的值進行排序的,我們不能根據key_part2 = 'a'進一步減少需要掃描的記錄數量,所以這個掃描區間是(-∞,'b'),
- 對于查詢陳述句:
select * from single_table where key_part1 <= 'b' and key_part2 = 'a';
對于符合 key_part1 < 'b'條件的二級索引記錄,并不是直接按照key_part2列的值進行排序的,
但是對于符合 key_part1 = 'b'條件的二級索引記錄時,是按照key_part2列的值排序的,當掃描到第一條不符合key_part1 <= 'b' and key_part2 = 'a'條件的第一條記錄時,就可以結束掃描,
所以這個掃描 區間是[(-∞,-∞),('b','a')],
索參考于排序
-
使用聯合索引是,
ORDER BY子句后面的列順序也必須按照索引列的順序給出, -
對于聯合索引進行排序的場景,要求各個排序列的排列規則是一致的,要么是按照
ASC(升序),要么是按照DESC(降序)排列規則,
使用
ORDER BY進行降序排列是可以使用索引的,
- 排序列包含非同一個索引的列是不能使用索引的,
- 排序列是某個聯合索引的索引列,但是排序列在聯合索引中并不連續不能使用索引,
- 排序列不是以單獨列名出現在
ORDER BY子句中(可能是函式或者運算式修飾過的形式)不能使用索引,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/247231.html
標籤:其他
