筆記很無味,點贊請準備竟纳。
索引定義
數(shù)據(jù)庫索引撵溃,是數(shù)據(jù)庫管理系統(tǒng)中一個排序的數(shù)據(jù)結(jié)構(gòu)疚鲤,以協(xié)助快速查詢,更新數(shù)據(jù)庫表中的數(shù)據(jù)缘挑。
從定義中可以看出集歇,索引其實就是一種數(shù)據(jù)結(jié)構(gòu)。數(shù)據(jù)都是以文件的形式存儲在磁盤上的语淘,每一行數(shù)據(jù)都有它的磁盤地址诲宇,如果沒有索引,要從幾百萬行數(shù)據(jù)中檢索一條數(shù)據(jù)惶翻,只能遍歷整張表才能找過結(jié)果姑蓝。有了索引之后,只需要在索引里面去檢索這條數(shù)據(jù)就可以了吕粗,因為索引是一種特殊的專門用來快速檢索的數(shù)據(jù)結(jié)構(gòu)它掂,當我們找到數(shù)據(jù)磁盤地址后,就可以拿到想要的數(shù)據(jù)溯泣。
索引類型
以InnoDB存儲引擎為例,索引類型有:
-
Normal(普通索引)
也叫非唯一索引榕茧,是最普通的索引垃沦,沒有任何限制條件。
-
Unique(唯一索引)
唯一索引要求鍵值不能重復(fù)用押。
主鍵索引是一種特殊的唯一索引肢簿,它多了一個限制條件,要求鍵值不能為空蜻拨。
-
Fulltext(全文索引)
全文索引主要是針對比較大的數(shù)據(jù)池充,比如我們存放的是消息內(nèi)容,有幾kb的數(shù)據(jù)缎讼,如果要解決like查詢效率低的問題收夸,可以創(chuàng)建全文索引。只有文本類型的字段才可以創(chuàng)建全文索引血崭,比如char卧惜、varchar、text夹纫。
全文索引的使用:
select * from table where match(content) against ('xxxx' IN NATURAL LANGUAGE MODE);
-
聚集索引(聚簇索引)
聚集索引就是索引鍵值的邏輯順序跟表數(shù)據(jù)行的物理存儲順序是一致的咽瓷。在InnoDB中,主鍵索引就是聚集索引舰讹,非主鍵索引是非聚集索引茅姜。
索引存儲模型
索引的存儲模型有二分查找、二叉查找樹(BST Binary Search Tree)月匣、平衡二叉樹(AVL Tree)钻洒、多路平衡查找樹(B Tree)奋姿、加強版多路平衡查找樹(B+ Tree)。
存儲模型是一步一步演進過來的航唆。
InnoDB邏輯存儲結(jié)構(gòu)
mysql的存儲結(jié)構(gòu)分為5級胀蛮,表空間、段糯钙、簇粪狼、頁、行任岸。
- 表空間
表空間可以看做是InnoDB存儲引擎邏輯結(jié)構(gòu)的最高層再榄,所有的數(shù)據(jù)都存放在表空間中。表空間又分為:系統(tǒng)表空間享潜、獨占表空間困鸥、通用表空間、臨時表空間剑按、Undo表空間疾就。
- 段(Segment)
表空間是由各個段組成,段又分為:數(shù)據(jù)段艺蝴、索引段猬腰、回滾段。
段是一個邏輯概念猜敢,一個ibd文件(獨立的表空間文件)里面會有很多個段組成姑荷。
創(chuàng)建一個索引會創(chuàng)建兩個段,一個是索引段(leaf node segment)缩擂,一個是數(shù)據(jù)段(non-leaf node segment)鼠冕。索引段管理非葉子節(jié)點的數(shù)據(jù),數(shù)據(jù)段管理葉子節(jié)點數(shù)據(jù)胯盯。
- 簇(Extent)
一個段又是由多個簇(也可以叫區(qū))組成懈费,每個簇的大小是1MB(64個連續(xù)的頁)。
每一個段至少有個一個簇博脑,一個段所管理的空間大小是無限的楞捂,可以一直擴展下去,擴展的最小單位就是簇趋厉。
- 頁(Page)
簇是由連續(xù)的頁組成的空間寨闹,一個簇中有64個連續(xù)的頁。
一個表空間最多擁有2^32個頁君账,默認情況下一個頁的大小為16KB繁堡,也就是說一個表空間最多存儲64TB的數(shù)據(jù)。
- 行(Row)
InnoDB存儲引擎是面向行(Row-oriented)存儲的。
索引使用原則
-
列的離散度
列的離散度計算公式:count(distinct(column_name))/count(*)椭蹄,列的全部不同值和所有數(shù)據(jù)行的比例闻牡。數(shù)據(jù)行數(shù)相同的情況下,分子越大绳矩,列的離散度就越高罩润。
簡單來說,如果列的重復(fù)值越多翼馆,離散度就越低割以,重復(fù)值越少,離散度就越高应媚。
-
聯(lián)合索引最左匹配
聯(lián)合索引在B+Tree中是復(fù)合的數(shù)據(jù)結(jié)構(gòu)严沥,它是按照從左到右的順序來建立搜索樹的。
我們在建立聯(lián)合索引的時候中姜,一定要把最常用的列放到最左邊消玄。
例如:給表table中建立聯(lián)合索引a和b,
select * from table where a='xxx' and b='xxx' /*是可以用到聯(lián)合索引的丢胚。*/
select * from table where a='xxx' /*可以用到聯(lián)合索引*/
select * from table where b='xxx' /*無法使用聯(lián)合索引*/
給a和b建立聯(lián)合索引其實就是相當于(a)和(a翩瓜,b)建立了兩個索引。
在給a携龟、b兔跌、c建立聯(lián)合索引的時候其實就是建立了(a)索引,(a,b)索引骨宠,(a,b,c)索引,這時相满,如果條件where b=‘xxx‘和where b=‘xxx' and c='xxx'层亿,還有where a='xxx' and c='xxx'都是用不到聯(lián)合索引的。
說明聯(lián)合索引的使用條件時不能不使用第一個字段立美,也不能中斷匿又。
什么時候用不到索引
在索引列上使用函數(shù)(replace、substr建蹄、concat碌更、sum、count洞慎、avg)痛单、表達式、計算(+劲腿、-旭绒、、/*)。
字符串不加引號挥吵,出現(xiàn)隱式轉(zhuǎn)換重父。
like條件前面帶%。
-
負向查詢
not like 不能使用索引忽匈。
!=房午、<>、not in在某些情況下可能用到索引丹允。
注意:一個sql語句是否使用到索引郭厌,是跟數(shù)據(jù)庫版本,數(shù)據(jù)量嫌松、數(shù)據(jù)選擇度都有關(guān)系的沪曙。
其實用不用到索引,最終都是由優(yōu)化器說了算萎羔。
優(yōu)化器是基于cost開銷來決定的液走,怎么樣開銷小就怎么來。它不基于規(guī)則贾陷,也不基于語義缘眶。
覆蓋索引
在輔助索引里面,不管是單列索引還是聯(lián)合索引髓废,如果select后的數(shù)據(jù)列只要從索引中就能夠得到巷懈,不用在從數(shù)據(jù)區(qū)中讀取,這時候使用的索引就叫覆蓋索引慌洪,這樣也避免了回表顶燕。
回表
非主鍵索引,是先通過索引找到主鍵索引的鍵值冈爹,在通過主鍵值查出索引里面沒有的數(shù)據(jù)涌攻,它比基于主鍵索引查詢的時候多了一次查詢,這個過程就是回表频伤。
索引下推
例如:給a和b建立索引恳谎。
- 先根據(jù)a列從存儲引擎中把符合規(guī)則的數(shù)據(jù)拉取到mysql的server層。
- 在server層按照b進行數(shù)據(jù)過濾憋肖。
這個過程就叫索引下推
B+ Tree
特點
- 它的關(guān)鍵字的數(shù)量是跟路數(shù)相等的因痛。
- B+Tree的根據(jù)節(jié)點和枝節(jié)點都不會存儲數(shù)據(jù),只有葉子節(jié)點才存儲數(shù)據(jù)岸更。搜索到關(guān)鍵字不會直接返回鸵膏,會到最后一層葉子節(jié)點。
- B+Tree的每個葉子節(jié)點增加了一個指向相鄰葉子節(jié)點的指針怎炊,它的最后一個數(shù)據(jù)會指向下一個葉子節(jié)點的第一個數(shù)據(jù)较性,這樣就形成了一個有序鏈表的結(jié)構(gòu)用僧。
- 它是根據(jù)左閉右開的區(qū)間來檢索數(shù)據(jù)的。
[每天進步一點點]mysql筆記整理(二):事務(wù)與鎖
- 整理不易赞咙,轉(zhuǎn)載請注明出處责循,喜歡的小伙伴可以關(guān)注公眾號查看更多喜歡的文章。
- 微信:ffj2000