「筆記很無味,點贊請準備。」node
❝數據庫索引,是數據庫管理系統中一個排序的數據結構,以協助快速查詢,更新數據庫表中的數據。mysql
❞
從定義中能夠看出,索引其實就是一種「數據結構」。數據都是以文件的形式存儲在磁盤上的,每一行數據都有它的磁盤地址,若是沒有索引,要從幾百萬行數據中檢索一條數據,只能遍歷整張表才能找過結果。有了索引以後,只須要在索引裏面去檢索這條數據就能夠了,由於索引是一種特殊的專門用來快速檢索的數據結構,當咱們找到數據磁盤地址後,就能夠拿到想要的數據。web
以InnoDB存儲引擎爲例,索引類型有:sql
Normal(普通索引)數據庫
❝也叫非惟一索引,是最普通的索引,沒有任何限制條件。微信
❞
Unique(惟一索引)數據結構
❝惟一索引要求鍵值不能重複。編輯器
主鍵索引是一種特殊的惟一索引,它多了一個限制條件,要求鍵值不能爲空。函數
❞
Fulltext(全文索引)post
❝全文索引主要是針對比較大的數據,好比咱們存放的是消息內容,有幾kb的數據,若是要解決like查詢效率低的問題,能夠建立全文索引。只有文本類型的字段才能夠建立全文索引,好比char、varchar、text。
❞
全文索引的使用:
select * from table where match(content) against ('xxxx' IN NATURAL LANGUAGE MODE);
複製代碼
彙集索引(聚簇索引)
❝彙集索引就是索引鍵值的邏輯順序跟表數據行的物理存儲順序是一致的。在InnoDB中,主鍵索引就是彙集索引,非主鍵索引是非彙集索引。
❞
索引的存儲模型有二分查找、二叉查找樹(BST Binary Search Tree)、平衡二叉樹(AVL Tree)、多路平衡查找樹(B Tree)、增強版多路平衡查找樹(B+ Tree)。
存儲模型是一步一步演進過來的。
mysql的存儲結構分爲5級,表空間、段、簇、頁、行。
❝表空間能夠看作是InnoDB存儲引擎邏輯結構的最高層,全部的數據都存放在表空間中。表空間又分爲:系統表空間、獨佔表空間、通用表空間、臨時表空間、Undo表空間。
❞
❝表空間是由各個段組成,段又分爲:數據段、索引段、回滾段。
段是一個邏輯概念,一個ibd文件(獨立的表空間文件)裏面會有不少個段組成。
建立一個索引會建立兩個段,一個是索引段(leaf node segment),一個是數據段(non-leaf node segment)。索引段管理非葉子節點的數據,數據段管理葉子節點數據。
❞
❝一個段又是由多個簇(也能夠叫區)組成,每一個簇的大小是1MB(64個連續的頁)。
每個段至少有個一個簇,一個段所管理的空間大小是無限的,能夠一直擴展下去,擴展的最小單位就是簇。
❞
❝簇是由連續的頁組成的空間,一個簇中有64個連續的頁。
一個表空間最多擁有2^32個頁,默認狀況下一個頁的大小爲16KB,也就是說一個表空間最多存儲64TB的數據。
❞
❝InnoDB存儲引擎是面向行(Row-oriented)存儲的。
❞
列的離散度
❝列的離散度計算公式:count(distinct(column_name))/count(*),列的所有不一樣值和全部數據行的比例。數據行數相同的狀況下,分子越大,列的離散度就越高。
簡單來講,若是列的重複值越多,離散度就越低,重複值越少,離散度就越高。
❞
聯合索引最左匹配
❝聯合索引在B+Tree中是複合的數據結構,它是按照從左到右的順序來創建搜索樹的。
❞
咱們在創建聯合索引的時候,必定要把最經常使用的列放到最左邊。
例如:給表table中創建聯合索引a和b,
select * from table where a='xxx' and b='xxx' /*是能夠用到聯合索引的。*/
select * from table where a='xxx' /*能夠用到聯合索引*/
select * from table where b='xxx' /*沒法使用聯合索引*/
複製代碼
給a和b創建聯合索引其實就是至關於(a)和(a,b)創建了兩個索引。
在給a、b、c創建聯合索引的時候其實就是創建了(a)索引,(a,b)索引,(a,b,c)索引,這時,若是條件where b=‘xxx‘和where b=‘xxx' and c='xxx',還有where a='xxx' and c='xxx'都是用不到聯合索引的。
「說明聯合索引的使用條件時不能不使用第一個字段,也不能中斷。」
在索引列上使用函數(「replace、substr、concat、sum、count、avg」)、表達式、計算(「+、-、*、/」)。
字符串不加引號,出現隱式轉換。
like條件前面帶%。
負向查詢
❝not like 不能使用索引。
!=、<>、not in在某些狀況下可能用到索引。
「注意:一個sql語句是否使用到索引,是跟數據庫版本,數據量、數據選擇度都有關係的。」
❞
其實用不用到索引,最終都是由「優化器」說了算。
「優化器是基於cost開銷來決定的,怎麼樣開銷小就怎麼來。它不基於規則,也不基於語義。」
❝在輔助索引裏面,不論是單列索引仍是聯合索引,若是select後的數據列只要從索引中就可以獲得,不用在從數據區中讀取,這時候使用的索引就叫覆蓋索引,這樣也避免了回表。
❞
❝非主鍵索引,是先經過索引找到主鍵索引的鍵值,在經過主鍵值查出索引裏面沒有的數據,它比基於主鍵索引查詢的時候多了一次查詢,這個過程就是回表。
❞
❝例如:給a和b創建索引。
先根據a列從存儲引擎中把符合規則的數據拉取到mysql的server層。 在server層按照b進行數據過濾。 這個過程就叫索引下推
❞