【JAVA今法修真】 第七章 洞天風雲起,索引混亂平
您好,我是南橘,萬法仙門的掌門,剛剛從九州世界穿越到地球,因為時空亂流的影響導致我的法力全失,現在不得不通過這個平台向廣大修真天才們借去力量。你們的每一個點贊,每一個關注都是讓我回到九州世界的助力,兄弟萌來為我注入修為吧!關注WX號:南橘ryc 。在公眾號上,除了可以看到雲小霄的照片,李小庚的畫像也很快出爐哦。
等我回去以後,大家都是萬法仙門的長老,我會給大家數不盡的天材地寶,人人如龍,全民飛升
通遼州,自古修時代分割天下九州以來,三十六洞天佔了七個,七十二福地佔了十四個,是九州大陸上數一數二的富貴州。而隨着今法到來,以一家一姓為主佔據洞天福地的時代已然過去,雲中洞天服務慢慢取代了傳統的不可移動的固定洞天。作為通遼州傳統強宗,佔據了大半洞天福地的萬法仙門,更是闊氣到可以給每一個築基期圓滿的弟子配發專屬的雲洞天。
「師弟,你們雲霄殿沒有自己的私有雲嗎?」後勤部金丹期執事林建成凝重地盯着李小庚遞過來的玉牌。
「當然有啊。」李小庚笑了笑,打了個響指。
雲中洞天之所以以雲中為名,便是因為它如同天上的雲朵一樣可以伴隨修士左右,同時在隱藏的時候又能夠如雲霧一般散去。
精心裝飾過的洞府,琳琅滿目的修真典籍和天材地寶整齊擺放在超豪華16核32G私人云中洞天器內,周圍環繞的淡淡金色光暈象徵著DDoS高防特性,鑲嵌在正中心的兩顆符文石證明它自帶通遼雲海兩洲三中心災備。
至今還用着十年前突破金丹期後門派分配的只有雙核4G服務器的林建成嘴角抽了抽:「師弟已經有了這麼好的東西,就沒必要再來領這種單核的雲中洞天了吧。」
「師兄此言差矣。」李小庚再一個響指(可以設定一些條件作為洞天啟動關閉的扳機),洞天慢慢變淡直到完全消失,然後抱拳道:「長者賜,不敢辭,畢竟是宗門派發,我必將好好珍惜。」
「…」後勤部一直是整個萬法仙門,亦或是大部分仙門裡最有「價值」的部門,因為很多家中富裕或者長輩出手闊氣的弟子都不會再來領取宗門發放的制式裝備,這個時候,這些裝備就成為了後勤部門的獎金。
林建成見李小庚完全沒有放棄領取的意思,只能悻悻的放下本來馬上到手的裝備,一本正經的說道:「好吧,既然你選擇領取雲中洞天,我也按宗門的規矩考考你幾個問題。」
「還請師兄賜教。」
「什麼是覆蓋索引?」
1、覆蓋索引
如果一個索引包含了滿足SQL語句中字段與條件的數據,那麼它就叫做覆蓋索引。
覆蓋索引只需要在一棵索引樹上就能獲取SQL所需的所有列數據,無需回表,速度更快。
既然提到了回表,那麼我先講一下什麼叫回表。
回表的流程:
- 第一步在輔助索引 B+樹中檢索 , 到達其葉子節點獲取對應的主鍵
- 第二步使用主鍵在主索引 B+樹中再執行一次 B+樹檢索操作, 最終到達葉子節點即可獲取整行數據。
我們能很清晰的看出來,左邊的是聚集索引,右邊的是輔助索引,上圖告訴我們如果回表查詢的話,會先在輔助索引中找到主鍵值,再去聚集索引中找到全部的信息。在InnoDB 中,表數據文件本身就是按 B+Tree 組織的一個索引結構,這棵樹的葉點data 域保存了完整的數據記錄。這個索引的 key 是數據表的主鍵,因此 InnoDB 表數據文件本身就是主索引(聚集索引)。
聚集索引:
- 如果定義了主鍵,那麼主鍵就是聚集索引
- 如果沒有定義主鍵,那麼第一個not NULL unique列是聚集索引
- 如果都沒有,則InnoDb會創建一個隱藏row-id作為聚集索引
而輔助索引就是我們平常用到的非主鍵索引。
「哦,師弟的sql基礎很不錯嘛,那你可知咱們萬法仙門制式的雲中洞天的數據結構是什麼嗎?」
「是B+樹!它使用了B+樹!」李小庚開始玩起爛梗。
「那你說說為什麼要使用B+樹吧,順便解釋一下B+樹的查詢方式。」林建成好像並沒有看懂李小庚的梗:「當然,師弟不要覺得我在難為你,畢竟作為雲霄殿的弟子,我這個做師兄的對你的期望自然也會高一些,相信宗門的師長們也是這樣想的。」
「好的師兄,沒問題師兄。」李小庚依舊滿臉燦爛的笑容。
2、B+樹
首先,B+樹是B樹的一種擴展,如下圖所見,在B+樹內,非葉子節點不再存儲數據,僅僅存在索引,而葉子節點負責存儲具體的數據,且最底層的數據直接之間從左到右是按順序分佈,形成一個雙鏈表的結構。也就是說,各層節點中的索引數據均是下一層相應節點中的最大或者最小的索引的複寫。
B+樹最核心的特點:
- 只有葉子節點保存數據
- 多路非二叉
- 增加了相鄰接點的指向指針
- B+樹的非葉子節點的每一個關鍵字對應一個指針,而關鍵字則是子樹的最大,或者最小值
通過這些特點,我們其實可以總結出B+樹的優點:
- B+樹相比B樹的存儲效率更高。B+樹其實是多級索引,這種結構與Redis中跳躍表是非常的相似(以後會講),最下一層是所有關鍵碼的全集,因此可以把此層形成順序的雙鏈鏈表,正因為在B+樹裏面非葉層節點不需要存儲額外的指向磁盤的指針,所以相比之前的B樹,B+樹存儲效率更高。
- B+樹的高度更小,也就是說B+樹的檢索效率更高
- B+樹支持範圍檢索,因為葉子節點形成有序鏈表,所以能夠很好的支持範圍查找。
- 插入和刪除更為方便,其實流程和B樹類似,但B+樹裏面,關鍵碼的個數和子節點的個數是對等的,所以從記憶角度來說,B+樹更方便記憶使用,而B樹則需要時刻注意節點數和關鍵碼的對應關係。
- 時間複雜度低,因為從宏觀上可以做到一次排除一半的數據,並且在寫入時也沒有進行其他額外的數據查找性工作,所以對於b樹來說,其讀寫的時間複雜度都是O(log2n)。
當然,相比於B樹,其實B+樹還是有一些缺點的,比如只有葉子節點才存放數據,所以不會出現那種靈機一動,這也就意味着查找B+樹,就必須到葉子節點才能返回結果。
B+樹的查詢方式:
- 1 從root出發查詢到葉節點。
- 2 從葉節點的最左側出發,進行順序查找,同時也可使用進行範圍查找。
「那麼,下一個問題。」林建成一邊把玩着雲中洞天的客戶端,一邊陰惴惴地盯着李小庚:「師弟的理論基礎還真是牢固啊,不過接下來,師兄想考驗一下你的動手能力,師弟不介意吧。」
「當然是師兄說什麼就怎麼辦啦~」李小庚臉上的笑容也越發燦爛了,可他笑的越開心,林建成內心就越發不爽。
「那好。」林建成捏着洞天的手突然發出青綠色的光芒,緊接着,洞天客戶端(類似一個水晶球的樣子)里忽然彷彿被風神之詩席捲了一般。
「我屮艸芔茻!」李小庚從一臉嚴肅,不苟言笑,看起來毫無私心的林建成的手裡接過洞天客戶端:「師兄您這是讓我自己修復好它?」
「是的,李小庚師弟,這個洞天已經屬於你了,但是在使用它之前,我對你的最後一個考驗就是將它復原。」
「你知道為什麼你永遠比不過我嗎?」就像陽光穿過黑夜,如同黎明悄悄划過天邊,二師姐羅妍忽然一把奪過李小庚手中的客戶端,打量了片刻:「因為你自卑,懦弱,和我鬥了那麼多年後發現鬥不過我,就只能去刁難我的師弟。」
「師弟你記住,一個強者最重要的不是有多麼高深的法力,也不是多麼厲害的法寶,而是有着穩定的情緒,清晰的思路,堅定的自信,和永不言棄的精神,而不是一個只能揮刀向弱者的勇士」。
「說完了嗎?永遠有着吃不完的天材地寶,用不盡的數據資源,和最新式法器的大小姐。」林建成冷哼了一聲:「的確,我不如你,我的基礎款飛劍比不過你的劍陣,我的社區版編譯器鬥不過你的專業版,我的一品金丹自然也比不過你的一品龍紋加強版。你可以一直在研究院燃燒經費,而我只能在後勤部撈撈油水,補貼我那可憐至極的小工坊。甚至,我可能永遠都沒辦法奢侈到使用這位築基期師弟的雲中洞天。」
「你們雲霄殿的背景太大,我惹不起,還請羅大小姐和李師弟大人有大量,這個雲中洞天就當做賠罪送給弟了,告辭!」林建成一伸手從雲霧中召喚出自己的雲中洞天,然後轉手丟給李小庚,隨後劍訣一捏,飄然而去。
「師姐?這?」李小庚屬實是被震驚到了。
「沒事,一個手下敗將而已,只是沒想到把你牽扯進來了,他的東西你拿着就行,在萬法仙門裡,他不敢找你麻煩。」羅妍在研究所呆久了,回憶了片刻才艱難對李小庚的露出了一個笑容:「這個雲中洞天你要不要嘗試着修復一下?」
「可以,我來試試吧。」李小庚摸索了一下:「優化索引的方式就行了吧?」
「思路正確,林建成並沒有做的太過分,所以你嘗試優化一下索引就行了。」
3、利用覆蓋索引優化sql
我們通過覆蓋索引,查詢想要的數據字段都是索引鍵值的一部分,直接存放在索引的子葉層級,不需要通過輔助索引來一次回表查詢,效率很高。
覆蓋索引不僅僅只包含你寫在WHERE條件內的字段,而且還包含所有SELECT 需要的字段,以及在GROUP BY 或ORDER BY 子句內的字段。那麼我可以怎麼通過覆蓋索引來優化我們的sql呢?
1、全表查詢SQL優化、可以把需要查詢的列加入索引>select count(name) from user;
比如這個很常見的查詢數量的sql,我們就可以把user加入索引,這樣就可以免去回表查詢
ALERT TABLE user ADD index index_name(name);
2、列表查詢回表優化
select id,name,sex from user where name='fawaikuangtuzhangsan' ALERT TABLE user ADD index index_name_sex(name,sex);
將單列索引(name)升級為聯合索引(name, sex),即可避免回表。
3、其他方式都差不多,都是通過將所有查詢的列加入覆蓋索引以達成防止回表的目的,當然,這個東西需要看情況用,不然長長的索引列也會帶來存儲上的壓力
覆蓋索引可以完美的解決二級索引回表查詢問題。但是前提是一定得注意查詢時候索引的最左側匹配原則
4、最左匹配原則
最左優先,以最左邊的為起點任何連續的索引都能匹配上。如果是聯合索引,那麼key也由多個列組成,同時,索引只能用於查找key是否存在(相等),遇到範圍查詢 (>、<、between、like左匹配)等就不能進一步匹配了,後續退化為線性查找。
建立了聯合索引abc
ALTER TABLE `ryc` ADD INDEX index_a_b_c(`a`,`b`,`c`);
select * from ryc where a = '1' and b = '2' and c = '3' select * from ryc where b = '2' and a = '1' and c = '3' select * from ryc where c = '3' and b = '2' and a = '1' select * from ryc where a = '3' and b = '2' select * from ryc where a = '3'
這些情況搜索都不影響查詢結果,因為它們都是從最左邊開始,同時因為Mysql中有查詢優化器,會自動優化查詢順序 ,當然我們最好可以按順序寫,最少看起來都舒服一些
select * from ryc where b = '3' and c = '2' select * from ryc where b = '3'
而這些沒情況有從最左邊開始,最後查詢沒有用到索引,用的是全表掃描
select * from ryc where a = '3' and c = '2'
如果是這種情況呢,就只命中了a的索引,c還是得老老實實的去掃描
如果遇到了><之類的範圍查詢,在範圍查詢之前,如果滿足最左匹配原則,那麼就可以按索引走,在範圍查詢之後的就不管了
如:select * from ryc where a = '3' and b = '2' and c<7
這種情況就滿足了最左匹配原則的查詢
select * from ryc where a > 3 and b = '2' and c<7
這種情況就只有a能夠查索引了,bc都需要全表掃描了
如果是order by排序的情況,那麼又有一些不同
select * from ryc order by b,c,a limit 10;
大家覺得這種情況能不能用到索引?
很遺憾,沒有,不過這個 filesort 並不是說通過磁盤文件進行排序,而只是告訴我們進行了一個排序操作而已,當然,using filesort不一定引起mysql的性能問題。但是如果查詢次數非常多,那麼每次在mysql中進行排序,還是會有影響的。
select * from ryc order by a limit 10; select * from ryc order by a,b limit 10; select * from ryc where a =1 order by b,c limit 10;