mysql官方對索引的定義為:索引(index)是幫助mysql高效獲取資料的資料結構。可以得到索引的本質:索引是資料結構。索引的目的在於提高查詢效率,可以模擬字典。
可以將索引理解為「排好序的快速查詢資料結構」。
在資料之外,資料庫系統還維護著滿足特定查詢演算法的資料結構,這些資料結構以某種方式引用(指向)資料,這樣就可以在這些資料結構上實現高階查詢演算法。這種資料結構就是索引。下圖就是一種可能的索引方式示例:
左邊是資料表,一共有兩列七條記錄,最左邊的是資料記錄的實體地址
為了加快col2的查詢,可以維護乙個右邊所示的二叉查詢樹,每個節點分別包含索引鍵值和乙個指向對應資料記錄實體地址的指標,這樣就可以運用二叉查詢在一定的複雜度內獲取到相應資料,從而快速的檢索出符合條件的記錄。
二叉樹
二叉樹弊端之一:二叉樹很可能會發生兩邊不平衡的情況。
b-tree: (b:balance) 會自動根據兩邊的情況自動調節,使兩端無限趨近於平衡狀態。可以使效能最穩定。(myisam使用的方式)
b-tree弊端:(插入/修改操作多時,b-tree會不斷調整平衡,消耗效能)從側面說明了索引不是越多越好。
b+tree:innodb 所使用的索引。
一般來說索引本身也很大,不可能全部儲存在記憶體中,因此索引往往以索引檔案的形式儲存的磁碟上。我們平常所說的索引,如果沒有特別指明,都是指b樹(多路搜尋樹,並不一定是二叉的)結構組織的索引。其中聚集索引,次要索引,覆蓋索引,復合索引,字首索引,唯一索引預設都是使用b+樹索引,統稱索引。當然,除了b+樹這種型別的索引之外,還有哈稀索引(hash index)等。
①類似大學圖書館建書目索引,提高資料檢索的效率,降低資料庫的io成本。
②通過索引列對資料進行排序,降低資料排序的成本,降低了cpu的消耗。
①實際上索引也是一張表,該錶儲存了主鍵與索引字段,並指向實體表的記錄,所以索引列也是要占用空間的。
②雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對表進行insert、update和delete。因為更新表時,mysql不僅要儲存資料,還要儲存一下索引檔案每次更新新增了索引列的字段,都會調整因為更新所帶來的鍵值變化後的索引資訊。
③索引只是提高效率的乙個因素,如果你的mysql有大資料量的表,就需要花時間研究建立最優秀的索引,或優化查詢語句。
即乙個索引只包含單個列,乙個表可以有多個單列索引。
索引列的值必須唯一,但允許有空值。
即乙個索引包含多個列
設定為主鍵後資料庫會自動建立索引,innodb為聚簇索引。
create [unique ] index indexname on (columnname(length))
alter mytable add [unique ] index [indexname] on (columnname(length))
drop index [indexname] on mytable
alter table tbl_name add primary key (column_list): 該語句新增乙個主鍵,這意味著索引值必須是唯一的,且不能為null。
alter table tbl_name add unique index_name (column_list): 這條語句建立索引的值必須是唯一的(除了null外,null可能會出現多次)。
alter table tbl_name add index index_name (column_list): 新增普通索引,索引值可出現多次。
alter table tbl_name add fulltext index_name (column_list):該語句指定了索引為 fulltext ,用於全文索引。
一顆b樹,淺藍色的塊我們稱之為乙個磁碟塊,可以看到每個磁碟塊包含幾個資料項(深藍色所示)和指標(黃色所示),
如磁碟塊1包含資料項17和35,包含指標p1、p2、p3,
p1表示小於17的磁碟塊,p2表示在17和35之間的磁碟塊,p3表示大於35的磁碟塊。
真實的資料存在於葉子節點即3、5、9、10、13、15、28、29、36、60、75、79、90、99。
非葉子節點不儲存真實的資料,只儲存指引搜尋方向的資料項,如17、35並不真實存在於資料表中。
如果要查詢資料項29,那麼首先會把磁碟塊1由磁碟載入到記憶體,此時發生一次io,在記憶體中用二分查詢確定29在17和35之間,鎖定磁碟塊1的p2指標,記憶體時間因為非常短(相比磁碟的io)可以忽略不計,通過磁碟塊1的p2指標的磁碟位址把磁碟塊3由磁碟載入到記憶體,發生第二次io,29在26和30之間,鎖定磁碟塊3的p2指標,通過指標載入磁碟塊8到記憶體,發生第三次io,同時記憶體中做二分查詢找到29,結束查詢,總計三次io。
真實的情況是,3層的b+樹可以表示上百萬的資料,如果上百萬的資料查詢只需要三次io,效能提高將是巨大的,如果沒有索引,每個資料項都要發生一次io,那麼總共需要百萬次的io,顯然成本非常非常高。
b+tree 第二級的 資料並不能直接取出來,只作索引使用。在記憶體有限的情況下,查詢效率高於 b-tree
b-tree 第二級可以直接取出來,樹形結構比較重,在記憶體無限大的時候有優勢。
在記憶體有限的情況下,b+tree 永遠比 b-tree好。無限記憶體則後者方便。
1)b-樹的關鍵字和記錄是放在一起的,葉子節點可以看作外部節點,不包含任何資訊;b+樹葉子節點中只有關鍵字和指向下乙個節點的索引,記錄只放在葉子節點中。(一次查詢可能進行兩次i/o操作)
2)在b-樹中,越靠近根節點的記錄查詢時間越快,只要找到關鍵字即可確定記錄的存在;而b+樹中每個記錄的查詢時間基本是一樣的,都需要從根節點走到葉子節點,而且在葉子節點中還要再比較關鍵字。從這個角度看b-樹的效能好像要比b+樹好,而在實際應用中卻是b+樹的效能要好些。因為b+樹的非葉子節點不存放實際的資料,這樣每個節點可容納的元素個數比b-樹多,樹高比b-樹小,這樣帶來的好處是減少磁碟訪問次數。儘管b+樹找到乙個記錄所需的比較次數要比b-樹多,但是一次磁碟訪問的時間相當於成百上千次記憶體比較的時間,因此實際中b+樹的效能可能還會好些,而且b+樹的葉子節點使用指標連線在一起,方便順序遍歷(例如檢視乙個目錄下的所有檔案,乙個表中的所有記錄等),這也是很多資料庫和檔案系統使用b+樹的緣故。
b+樹的磁碟讀寫代價更低
b+樹的內部結點並沒有指向關鍵字具體資訊的指標。因此其內部結點相對b 樹更小。如果把所有同一內部結點的關鍵字存放在同一盤塊中,那麼盤塊所能容納的關鍵字數量也越多。一次性讀入記憶體中的需要查詢的關鍵字也就越多。相對來說io讀寫次數也就降低了。
b+樹的查詢效率更加穩定
由於非終結點並不是最終指向檔案內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查詢必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每乙個資料的查詢效率相當。
①主鍵自動建立唯一索引;
②頻繁作為查詢條件的字段應該建立索引(where 後面的語句);
③查詢中與其它表關聯的字段,外來鍵關係建立索引;
④單鍵/組合索引的選擇問題(在高併發下傾向建立組合索引);
⑤查詢中排序的字段,排序欄位若通過索引去訪問將大大提高排序速度;
⑥查詢中統計或者分組字段。
①表記錄太少;
②經常增刪改的表;
原因:提高了查詢速度,同時卻會降低更新表的速度,如對表進行insert、update和delete。因為更新表時,mysql不僅要儲存資料,還要儲存一下索引檔案
③where條件裡用不到的字段不建立索引;
④資料重複且分布平均的表字段,因此應該只為最經常查詢和最經常排序的資料列建立索引。
注意,如果某個資料列包含許多重複的內容,為它建立索引就沒有太大的實際效果。
索引優化分析(三)
是mysql提供的一種日誌記錄,用來記錄在mysql中響應時間超過閾值的語句,具體指執行時間超過long query time值的sql,則會被記錄到慢查詢日誌中 long query time的預設值為10s,sql語句執行超過10s,則記錄下來,在結合explain sql語句分析。1 檢視是否...
索引優化分析(二)
explain sql語句 explain select from table name查詢結果如下 1 id selectct 查詢的序列號,包含一組數字,表示查詢中執行select子句或操作表的順序 查詢順序 a id相同,執行順序由上至下 b id不同,如果是子查詢,id的序號會遞增,id值越...
MySQL索引優化分析
1.通過訂單號查詢某個訂單,用唯一索引 資料量幾百萬以上 2.order by 排序時,後面欄位加 強制指定索引 select from orderforce index idx ordere order by order level,input date 哪些情況需要建索引 1 主鍵,唯一索引 2...