Java乾貨分享:2020年學習的java乾貨,包括基礎+資料+視頻免費

作為一名工作了4年的程序猿,今天我將站在程序員的角度以MySQL為例探索數據庫的奧秘!


在分享這篇文章之前呢,我先分享下我總結的一些乾貨,我自己也是一位從事了6年開發的全棧工程師,今年年初我整理了一份最適合2018年學習的java乾貨,包括基礎+資料+視頻,都是免費的,在這裡相信有許多想要學習Java的同學,關注小編頭條號,私信【學習】即可。
數據庫基本原理

Java乾貨分享:2020年學習的java乾貨,包括基礎+資料+視頻免費


我對DB的理解
第一,數據庫的組成:存儲 + 實例
不必多說,數據當然需要存儲;存儲了還不夠,顯然需要提供程序對存儲的操作進行封裝,對外提供增刪改查的API,即實例。
一個存儲,可以對應多個實例,這將提高這個存儲的負載能力以及高可用;多個存儲可以分佈在不同的機房、地域,將實現容災。
第二,按Block or Page讀取數據
用大腿想也知道,數據庫不可能按行讀取數據(Why? ^_^)。實質上,數據庫,如Oracle/MySQL,都是基於固定大小(比如16K)的物理塊(Block or Page,我這裡就不區分統一稱為Block)來實現調度和管理的。要知道Block是數據庫的概念,如何對應到文件系統呢?顯然需要指出“這個Block的地址在哪裡”,當查找到地址後,讀取固定大小的數據就相當於完成了Block的讀取了。
數據庫很聰明的,它不會僅僅只讀取需要讀取的Block,它還會替我們把附近的Block塊都讀取加載至內存。實際上,這是為了減少IO次數,提高命中率。事實上,一個Block塊的附近Block也是熱點數據,這種處理方式很有必要!
第三,磁盤IO是數據庫的性能瓶頸
毫無疑問,數據在磁盤上,少不了磁盤IO。什麼磁頭旋轉,定位磁道,尋址的過程,就不說了,我們是程序員,也管不了這些。但是這個過程確實是非常耗時的,和內存讀取不是一個數量級,所以後來出現了很多方式來減少IO,提升數據庫性能。


比如,增加內存,讓數據庫把數據更多的加載至內存。內存雖好,但也不能濫用,為什麼這麼說呢?假設數據庫中有100G數據,如果都加載至內存,也就說數據庫要管理100G磁盤數據+100G內存數據,你說累不累?(數據庫要處理磁盤和內存的映射關係,數據的同步,還要對內存數據進行清理,如果涉及數據庫事務,又是一系列複雜操作......)不過這裡需要指出的是,為了加快內存查找速度,數據庫一般對內存進行HASH存放。
比如,利用索引,索引相比內存,是一個性價比非常高的東西,後文詳細介紹MySQL的索引原理。
比如,利用性能更好的磁盤...(和咱們就沒關係呢)
第四,提出一些問題思考下:
為什麼我們說利用delete刪除一個表的數據較trancate一個表要慢?
【一個按行查找刪除,多費勁;一個基於Block的體系結構刪除】
為什麼我們說要小表驅動大表?
【小表驅動大表會快?什麼鬼?M*N和N*M不是一樣的麼?有鬼的地方,就有索引!】
探索MySQL索引背後的原理
對於絕大數的應用系統,讀寫比例在10:1,甚至100:1,而且insert/update很難出現性能問題,遇到最多的,最棘手的就是select了,select優化是重中之重,顯然少不了索引!

說起MySQL的索引,我們會冒出很多這些東西:BTree索引/B+Tree索引/Hash索引/聚集索引/非聚集索引...這麼多,暈頭!
索引到底是什麼,想解決什麼問題?
老生常談了,官網說MySQL索引是一種數據結構,索引的目的就是為了提高查詢效率。
說白了,不使用索引的話,磁盤IO次數比較多!要想減少磁盤IO次數,怎麼辦?
我們想通過不斷縮小想要獲取的數據的範圍來篩選出最終想要的結果,把每次查找數據的磁盤IO次數控制在一個很小的數量級,最好是常數數量級。
為了應對上述問題,B+Tree索引出來了!
Hello,B+Tree
在MySQL中,不同存儲引擎對索引的實現方式是不同的,這裡將重點分析MyISAM和Innodb。

Java乾貨分享:2020年學習的java乾貨,包括基礎+資料+視頻免費


MyISAM引擎的B+Tree索引結構
我們知道對於MyISAM引擎而言,數據文件和索引文件是分離的。從圖中也可以看出,通過索引查找到後,就得到了數據的物理地址,然後根據地址定位數據文件中的記錄即可。這種方式也叫"非聚集索引"。
需要注意的是,對於Innodb而言,主鍵索引中葉子節點存儲的是數據內容,而普通索引的葉子節點中存儲的是主鍵值!也就是說,對於Innodb的普通索引字段查找,先通過普通索引的B+Tree查找到主鍵後,然後通過主鍵索引的B+Tree進行查找。
而對於MyISAM而言,主鍵索引和普通索引僅僅的區別在於主鍵只需要查找到一條記錄即可停止,而普通索引允許重複,找到一條記錄後需要繼續查找,在結構上沒有區別,如上圖所示。
索引雖然物美價廉,但是也別亂來。count(distinct col) / count(*)可以算一下col的區分度,顯然對於主鍵而言,就是1。區分度太低的話,可以考慮下,是否還有必要建立索引呢?
在MySQL的Memory存儲引擎中,存在hash函數,給一個key,通過hash函數進行計算得到地址,所以通常情況下,hash索引查找,會非常快,O(1)的速度。但是也存在hash衝突,和HashMap一樣,通過單鏈表的形式解決。

Java乾貨分享:2020年學習的java乾貨,包括基礎+資料+視頻免費


SQL優化神器:explain
SQL優化的場景很多,網上的技巧也很多,完全記不住!
要想徹底解決這個問題,我想只有把索引背後的數據結構和原理做適當的理解,遇到書寫SQL或者SQL慢查詢的時候,我們有基礎去分析,再利用好explain工具去驗證,就應該問題不大呢。
explain查詢的結果,可以告訴你哪些索引正在被使用,表是如何被掃描的等等。這裡我將演示個Demo。


數據表student:

Java乾貨分享:2020年學習的java乾貨,包括基礎+資料+視頻免費


注意複合索引(age,address)

Java乾貨分享:2020年學習的java乾貨,包括基礎+資料+視頻免費


符合最左前綴匹配

Java乾貨分享:2020年學習的java乾貨,包括基礎+資料+視頻免費


複合索引失效。OK,到這裡,準備結束了,查詢容易,優化不易,且寫且珍惜!
資料獲取方式,關注小編,私信【學習】即可,手機用戶可直接私信,然後私信回覆【學習】然後今天就分享到這裡,大家記得點贊收藏,分享轉發,關注小編哦!免費領取本文的Java視頻學習教程。


分享到:


相關文章: