閒扯
很多時候我們面對很慢的查詢的時候會一籌莫展,這個時候大部分人都會很自然的想到建索引這條路。
事實上索引確實是個很好的優化方式,乙個良好的索引能夠提公升不止一倍的效率,還能帶來併發能力的提公升。
但是索引也不是萬能的,不然的話我大可以給一張表的所有列上都加上索引,但是基本上所有的dba都會有一條認知--不要盲目加索引。
那麼如何給乙個表加索引,這其實是個很複雜又很簡單的問題,首先我們需要了解索引。
乙個案例
新建一張表:
create table testc
a int primary key auto_increment,
b int,
c int,
d int,
e varchar(20),
key (b,c,d)
插入幾條資料:
insert into testc values (4,3,1,1,'d');
insert into testc values (1,1,1,1,'a');
insert into testc values (8,8,8,8,'h');
insert into testc values (2,2,2,2,'b');
insert into testc values (5,2,3,5,'e');
insert into testc values (3,3,2,2,'c');
insert into testc values (7,4,5,5,'g');
insert into testc values (6,6,4,4,'f');
此時可以畫出索引和資料列的關係簡圖:
這裡資料是按照堆表的形式畫的,實際上innodb引擎的表是按照聚簇索引組織的,但是這不是本文的重點。
如果執行下面這條sql,將會如何選擇索引:
select * from testc where b >= 2 and b < 8 and c > 1 and d != 4 and e != 'a';
首先明確索引的最左字首原則,此時索引掃瞄的下界是由b確定的,根據「b>=2」這個條件可以確定下界是[2,2,2]這個索引記錄。
接下來確定上界,上界由》,=這種符號確定,因此觀察到b<8這個條件,可以確定上界是[8,8,8]這個索引記錄,因此索引的掃瞄範圍一定是[[2,2,2],[8,8,8]),注意是左閉右開區間。
然後需要確定有哪些條件可以在索引上進行篩選,此時需要關注c和d上的條件,c>1代表可以排除掉[3,1,1]這個索引,而d!=4則可以排除掉[6,4,4]這個索引,因此此時需要掃瞄的索引行只有[2,2,2],[2,3,5],[3,2,2]和[4,5,5]。
在完全確定了索引可以做的事情之後,就要看看哪些條件不能使用索引,此時關注到e!=』a』這個條件,這是沒有辦法在索引上進行的,只能定位到具體的記錄上進行篩選。那麼此時就需要進行回表操作了。
這裡引申出幾個概念如下:index key:用於確定sql查詢在索引中的連續範圍(起始範圍+結束範圍)的查詢條件,被稱之為index key;
index filter:在完成了index key的提取後,索引列上的篩選條件;
table filter:所有不屬於索引列上的篩選條件。
而indexkey中又有上下界的概念,用於確定索引掃瞄的範圍,因此可以細分為index first key和index last key。
index first key:
從索引的第乙個鍵值開始,檢查其在where條件中是否存在,若存在並且條件是=、>=,則將對應的條件加入index first key之中,繼續讀取索引的下乙個鍵值,使用同樣的提取規則;若存在並且條件是》,則將對應的條件加入index first key中,同時終止index first key的提取;若不存在,同樣終止index first key的提取。
index last key:
從索引的第乙個鍵值開始,檢查其在where條件中是否存在,若存在並且條件是=、<=,則將對應條件加入到index last key中,繼續提取索引的下乙個鍵值,使用同樣的提取規則;若存在並且條件是 < ,則將條件加入到index last key中,同時終止提取;若不存在,同樣終止index last key的提取。
又見二分查詢
注意前文中的這句話:首先明確索引的最左字首原則,此時索引掃瞄的下界是由b確定的,根據「b>=2」這個條件可以確定下界是[2,2,2]這個索引記錄。
這不就是在乙個有序的序列上找乙個key嗎?那不用二分查詢用什麼?
其實在innodb內部不僅僅是索引掃瞄的時候用到了二分查詢,在頁面的槽管理中也是要用到二分查詢的。
所以一定要掌握二分查詢。
閒扯這次的題圖是一道紅色閃電。
願我們的國家的核心技術有一天像一道紅色閃電,劈在美帝的頭上。
願從這次晶元時間以後痛定思痛,不再受制於美帝國主義。
參考
MySQL如何使用索引
概念 索引用於快速查詢具有特定列值的行。沒有索引,mysql必須從第一行開始,然後通讀整個表以找到相關的行。表越大,耗費時間越多。如果表中有相關列的索引,mysql可以快速確定要在資料檔案中間查詢的位置,而不必檢視所有資料。這比順序讀取每一行要快得多。大多數mysql索引 primary key,u...
mysq索引類別
索引都是在儲存引擎層面實現的 1.btree索引 使用b tree資料結構建立的索引,索引值都是按順序存放的,儲存引擎不需要再全表掃瞄,取而代之的是從索引的根節點開始掃瞄,根節點存放了子節點的指標,隨著向下層查詢,隨著查詢值和節點值的比較 指標中右節點葉值的上下限 最終找到記錄。btree索引可以選...
MySql如何使用索引 一
我們都知道在 mysql 中使用索引可以提高查詢效率,但有時候真正執行sql查詢的時候卻沒有按照我們的預想使用索引,而是全表掃瞄,導致有慢sql影響了整個 的效率,甚至導致 崩潰,所以我們需要了解mysql是如何選擇使用索引的,以便建立合適的索引 本文基於mysql5.7,innodb引擎 假設有一...