本身對mysql的一點理解吧,固然技術有限,就借鑑的一些大佬的文章,但願能幫助到你們!( ̄▽ ̄)ノhtml
1.什麼是mysql?mysql
mysql是關係型數據庫,比較常見的關係型數據庫有mysql/oracle/sql server/sqlite ;存數據使用的是表,這樣的話結構比較固定,易於維護,咱們一般使用crud去操做表中的數據;這裏的crud就是insert,delete,update,selectredis
與之相對的是非關係型數據庫,如redis/mongoDB,是一種key-value形式的存儲,不理解的能夠簡單的看做json那樣存儲的;算法
至於二者之間的優缺點能夠簡單參考這個大哥的博客sql
2.mysql中的sql語言有幾種?數據庫
在mysql中,有4種語言:json
(1)DDL -- Data Definition Language,中文是數據庫定義語言,也就是create(建立數據庫或者數據表),alter(修改數據表相關信息),drop(刪除數據庫或者數據表)這幾個經常使用關鍵字,數據結構
只有建立表的時候,或者咱們後期須要給表加索引之類的可能會用到,日常用的比較少oracle
(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相關的知識,未完待續