第一,數據庫的組成:存儲 + 實例程序員
沒必要多說,數據固然須要存儲;存儲了還不夠,顯然須要提供程序對存儲的操做進行封裝,對外提供增刪改查的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的體系結構刪除】
爲何咱們說要小表驅動大表?
【小表驅動大表會快?什麼鬼?MN和NM不是同樣的麼?有鬼的地方,就有索引!】
對於絕大數的應用系統,讀寫比例在10:1,甚至100:1,並且insert/update很難出現性能問題,遇到最多的,最棘手的就是select了,select優化是重中之重,顯然少不了索引!
提及MySQL的索引,咱們會冒出不少這些東西:BTree索引/B+Tree索引/Hash索引/彙集索引/非彙集索引...這麼多,暈頭!
索引究竟是什麼,想解決什麼問題?
老生常談了,官網說MySQL索引是一種數據結構,索引的目的就是爲了提升查詢效率。
說白了,不使用索引的話,磁盤IO次數比較多!要想減小磁盤IO次數,怎麼辦?
咱們想經過不斷縮小想要獲取的數據的範圍來篩選出最終想要的結果,把每次查找數據的磁盤IO次數控制在一個很小的數量級,最好是常數數量級。
爲了應對上述問題,B+Tree索引出來了!
在MySQL中,不一樣存儲引擎對索引的實現方式是不一樣的,這裏將重點分析MyISAM和Innodb。
咱們知道對於MyISAM引擎而言,數據文件和索引文件是分離的。從圖中也能夠看出,經過索引查找到後,就獲得了數據的物理地址,而後根據地址定位數據文件中的記錄便可。這種方式也叫"非彙集索引"。
而對於Innodb引擎而言,數據文件自己是索引文件!通俗點說,葉子節點上,MyISAM存儲的是記錄的物理地址,而Innodb上存儲的是數據內容,這種方式即"彙集索引"。
另一點須要注意的是,對於Innodb而言,主鍵索引中葉子節點存儲的是數據內容,而普通索引的葉子節點中存儲的是主鍵值!也就是說,對於Innodb的普通索引字段查找,先經過普通索引的B+Tree查找到主鍵後,而後經過主鍵索引的B+Tree進行查找。從這裏你能夠看出,對於Innodb而言,主鍵的創建很是重要!
而對於MyISAM而言,主鍵索引和普通索引僅僅的區別在於主鍵只須要查找到一條記錄便可中止,而普通索引容許重複,找到一條記錄後須要繼續查找,在結構上沒有區別,如上圖所示。
想利用索引,就得「乾淨」
什麼叫「乾淨」?就是不要讓索引參與計算!好比在索引上應用函數,極可能致使索引失效。爲何呢?
其實不用想,B+Tree上存儲的是數據,要比較的話,須要把全部的數據都應用上函數,顯然成本太大。
想創建索引,看看區分度
索引雖然物美價廉,可是也別亂來。count(distinct col) / count(*)能夠算一下col的區分度,顯然對於主鍵而言,就是1。區分度過低的話,能夠考慮下,是否還有必要創建索引呢?
Hash索引
這裏並非要深刻分析Hash索引,而是要說明一下Hash的思想真是無處不在!
在MySQL的Memory存儲引擎中,存在hash函數,給一個key,經過hash函數進行計算獲得地址,因此一般狀況下,hash索引查找,會很是快,O(1)的速度。可是也存在hash衝突,和HashMap同樣,經過單鏈表的形式解決。
思考下,hash索引是否支持範圍查詢呢?
顯然是不支持的,它只能給一個KEY去查找。就如同HashMap同樣,查找key包含"zhangfengzhe"的,會很快麼?
在此我向你們推薦一個架構學習交流羣。交流學習羣號:478030634 裏面會分享一些資深架構師錄製的視頻錄像:有Spring,MyBatis,Netty源碼分析,高併發、高性能、分佈式、微服務架構的原理,JVM性能優化、分佈式架構等這些成爲架構師必備的知識體系。還能領取免費的學習資源,目前受益良多
SQL優化的場景不少,網上的技巧也不少,徹底記不住!
要想完全解決這個問題,我想只有把索引背後的數據結構和原理作適當的理解,遇到書寫SQL或者SQL慢查詢的時候,咱們有基礎去分析,再利用好explain工具去驗證,就應該問題不大呢。
explain查詢的結果,能夠告訴你哪些索引正在被使用,表是如何被掃描的等等。這裏我將演示個Demo。
數據表student:
注意複合索引(age,address)
符合最左前綴匹配
複合索引失效
OK,到這裏,準備結束了,查詢容易,優化不易,且寫且珍惜!