自己對mysql的一點理解吧,當然技術有限,就借鑒的一些大佬的文章,希望能幫助到大家!( ̄▽ ̄)ノ
1.什么是mysql?
mysql是關系型資料庫,比較常見的關系型資料庫有mysql/oracle/sql server/sqlite ;存資料使用的是表,這樣的話結構比較固定,易于維護,我們通常使用crud去操作表中的資料;這里的crud就是insert,delete,update,select
與之相對的是非關系型資料庫,如redis/mongoDB,是一種key-value形式的存盤,不理解的可以簡單的看作json那樣存盤的;
至于兩者之間的優缺點可以簡單參考這個大哥的博客
2.mysql中的sql語言有幾種?
在mysql中,有4種語言:
(1)DDL -- Data Definition Language,中文是資料庫定義語言,也就是create(創建資料庫或者資料表),alter(修改資料表相關資訊),drop(洗掉資料庫或者資料表)這幾個常用關鍵字,
只有創建表的時候,或者我們后期需要給表加索引之類的可能會用到,平常用的比較少
(2)DML-- Data Manipulation Language,中文是資料庫操作語言,這個也就是我們常用的crud操作,注意,我們還需要記住一個explain關鍵字,這個explain是用于分析你寫的sql陳述句執行效率的一個好用的工具,可以查看到有沒有使用到索引等資訊
(3)一筆帶過
DCL:資料庫控制語言,例如Grant —為用戶授予權限 revoke–撤回授權權限
TCL:事務控制語言,例如Commit --保存已完成的內容,rollback —回滾
3.什么sql最影響mysql效率?
不考慮讀寫分離的情況下,最影響mysql的效率的就是查詢陳述句,也就是你寫的那一大串的select xx from xx這種,所以我們一般就是優化查詢陳述句;
4.如何分析sql的執行效率呢?
我們要找到一些執行的很慢的sql,首先我們需要開啟mysql的慢查詢日志,設定時間限制,當超過這個時間限制的就記錄到日志檔案中,然后我們就用下面這種方式分析就ok了!那么怎么開啟慢查詢日志呢?看這里
使用explain查看sql的執行計劃,如下所示,有興趣的可以看看執行計劃中每個欄位的意思,例如possible_keys 表示可能使用的索引,key 表示實際使用的索引等等,有興趣的可以看看這個大哥的博客

注:還有一種更加細致的分析sql性能消耗的,使用show profile,有興趣的可以看看這個
5.通常如何優化查詢sql呢?
從上面我們知道了如何分析一條sql中的效率,最常用的優化方案便是加索引;
6.索引是什么?
索引是個什么東西呢?這里涉及到資料結構中的一個B+樹,索引在磁盤中是以檔案的形式存在,其實可以看做一張表,也是會占用物理空間的!!!
通俗易懂一點的解釋就是書籍目錄:在word檔案中目錄肯定也是占物理空間的對吧,而且我們點擊目錄就可以直接跳轉到對應的正文處,所以我們可以大概的知道索引可能存的是實際資料的物理地址空間(后面也可以存實際的資料哦!取決于引擎)
那么問題來了,所有索引都是這么存的嗎?
7.索引的分類
以innodb為例,索引分為兩種:
(1)聚集(clustered)索引,也叫聚簇索引,一個表只能有一個,
(2)非聚集(unclustered)索引,也叫稀疏索引,或者叫做普通索引,多個,
看名字就覺得想放棄了,其實聚集索引就是主鍵索引,其他的索引都叫做非聚集索引(比如聯合索引,唯一索引啥的,這些都是非聚集索引的邏輯分類)
8.兩種索引的不同之處
首先說一下mysql中innodb存資料的方式,首先我們要有這么一個想象的畫面,資料庫表的資料,都是存放在聚集索引下面的,下面畫個圖就了解了:
有這么一張表,id是主鍵(這里有個地方需要注意,對于innodb引擎,如果我們在建表陳述句那里有指定主鍵,那么就ok,沒有指定主鍵,mysql就會偷偷的創建一個主鍵索引,我們是看不到的,表中也沒有)

那么主鍵索引應該就是這樣的,下圖所示,這個時候實際的資料就是存到主鍵索引的葉子節點中的!

現在問題來了,那么非聚集索引是怎么存的呢?例如我把上表中name欄位添加索引...
然后我們思考,非聚集索引的結構也是b+樹,和聚集索引一樣,不同的是葉子節點中村的就不是實際的資料了,而是主鍵的值;
我們首先查詢到葉子節點的主鍵的值,然后通過這個主鍵的值再到聚集索引中查詢一次,才能拿到真正的資料!也就是說,通過非聚集索引查資料,一般要查詢兩次才行!第一次查詢出來的是主鍵的值,第二次通過主鍵的值去聚集索引中查詢實際的資料(用專業一點的詞語叫做回表);
為了更清晰的理解聚集索引和非聚集索引,我在網上偷了一張比較好理解的圖(可惜不是b+樹,但是原理一樣),如下所示,左邊是聚集索引,葉子節點存的是實際的資料;右邊是非聚集索引,存的是聚集索引的值;

9.是否所有的非聚集索引查詢的時候都需要查詢兩次呢(知識點:覆寫索引)?
在第8點中說了一般是查詢兩次,通常有 "一般" 這種詞語就說明還有特殊情況;
例如還是以上面的那個表為例,首先給name添加索引,那么看看這個sql:select id from user where name = "小王";
首先這個sql肯定會走非聚集索引name,找到葉子節點的存的id為1,這時你覺得還需要把1拿去再去查一次聚集索引么?肯定不需要啊,因為我們sql中只需要這個id就行了啊,已經查詢出來了,為什么還要去把那一條資料查詢出來呢?
這個時候只需要查詢一次就ok了,專業名詞叫做覆寫索引,專業解釋為:如果一個索引包含(或覆寫)所有需要查詢的欄位的值,稱為‘覆寫索引’,即只需掃描索引而無須回表,
10.主鍵自增比較好還是uuid比較好?
經常看到的主鍵是自增好點還是隨機字串(例如雪花演算法,uuid)好?其實資料量小的話是自增好,首先占用的空間小啊,uuid那么多位,另外還因為一點,這里用到一點平衡多叉樹的知識,就是分裂(建議新手去看看多叉樹的分裂,b+樹不是很好理解,點擊這里看看2-3-4樹的分裂);
而且看到題目中有主鍵兩個字,我們就知道肯定跟聚集索引有關呀!廢話,因為我們需要用到主鍵去構建聚集索引呀,那么如果不是自增的,比如我們再insert資料的時候,主鍵分別為1,10,,5,20,4,3,1這種,為了保存平衡,那么b+樹的節點就會分裂,重新組成新的節點,當資料量很大的時候,性能影響還是很大的,而自增的話,直接就在b+樹后面添加節點就行了,不需要分裂!但是使用自增還有一個壞處,就是id可預測性,簡直為爬蟲等一些東西打開了方便之門...
如果是在分庫分表的情況下還是用隨機字串吧,確保全域id的唯一性,有興趣的還可以再深入了解一下;
11.B+樹為什么比B樹更適合作為索引,或者說為什么innodb使用B+樹作為索引?
這個問題答案我就借用一下這個老哥的;
其實就是要明白B樹和B+樹的區別,B樹所有節點都存了資料,而B+樹只有葉子節點才存了資料嘛,這就使得B+樹的效率比較穩定,而且由于每個葉子節點之間也有指標相互連接,這樣使得范圍查詢會很方便,不需要從根節點再遍歷一次;
12.除了B+樹,你還能想到使用什么資料結構當作索引呢?
第一想法肯定是hash表啊,用過hashmap的都知道,這東西是真的好用,時間復雜度O(1);
那么問題來了,這么好用的東西為什么mysql的innodb引擎就是不用呢?留個印象,mysql中的MEMORY存盤引擎索引默認用的是hash
例如,你想想你把下面這些資料放到hashmap中,(1,10),(2,20),(3,30),(4,40),然后我需要找到key大于2小于4的資料,怎么找?如果我還要對key進行排序再輸出呢,怎么辦?
所以用hash作為索引,有幾點需要注意:
(1)Hash索引僅僅能滿足“=”,“IN”,不能支持范圍查詢
(2)對于排序操作Hash索引也滿足不了
(3)Hash索引不能避免表掃描
(4)當有大量資料的Hash值相等的時候Hash索引的性能大打折扣(這個也就是hash中經典的桶碰撞問題)
13.mysql為什么不用MyISAM引擎作為默認的引擎呢?
這個應該知道一點常識,MyISAM引擎不支持事務,不支持外鍵,默認是表鎖,查詢的效率比innodb要高等等, 還會經常和innodb做比較;
我再多說一點:首先,通過前面這么大的篇幅我們知道了如果使用innodb引擎,那么主索引檔案(或者聚集索引檔案)和資料檔案實際上是放在一起的;
然后,MyISAM引擎引擎索引檔案和資料檔案是分開的!!!注意,是分開的,也就是說B+樹葉子節點存放的是實際行資料的指標,例如下面這樣(圖是偷的( ̄▽ ̄)ノ),該引擎下所有的索引都是這樣的,注意,存的是物理地址啊!

14.什么是最左匹配原則?
在說這個問題之前,我們回憶一下,索引的邏輯分類有單列索引和組合索引吧,其中除了主鍵索引資料聚集索引,其他的索引都屬于非聚集索引,最左原則就是對于組合索引來說的!
還有一點,B+樹索引的葉子節點是已經排序好了的,我們才能根據索引值去走B+樹查詢,
例如我們用最開始我們的表,我們對name和age創建一個組合索引:CREATE INDEX name_age_Index ON "user"("name", "age");

那么現在我們需要將這個name和age看成一個整體,例如就這個組合索引的B+索引如下,我就簡單畫一下,順便多添加了幾行資料:

上圖我們能發現什么?首先是根據組合索引的第一個欄位進行排序的,當第一個欄位是一樣的,才會繼續對第二個欄位進行排序;那么你直接使用select id from age = "5",你覺得會走這個索引么?肯定不會啊,因為葉子節點的age明顯都不是排序的啊,怎么找啊?
所以只要有點數學基礎,即使組合索引包含三列,CREATE INDEX name_age_Index ON "user"("name", "age","score");,我們用到name和age會走索引,但是用到name和score只會走name索引,不會走score索引!
最后再獎勵自己一下幾個最左匹配原則的題目練習一下,點點這里
=========================截至目前時間2020/12/12==========================
后續還會記錄一下mysql相關的知識,未完待續
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/233416.html
標籤:其他
上一篇:Java中常用修飾符淺談
