1.MySql邏輯架構
| 客戶端
____________\|/_____________
| ________________________ |
| |________連接____________| |---客戶端通過連接服務,
| ______ ______________ | 將要執行的sql指令傳輸過來
| | | | 解析sql | |
| | | |--------------| |
| | | | 預處理 | |
| | | |--------------| |
| | 緩存 | | 查詢優化器 | |---服務器解析並優化sql,
| | | |--------------| | 生成最終的執行計劃並執行
| | | | 生成執行計劃 | |
| | | |--------------| |
| | | | 執行 | |
| |______| |______________| |
| ________________________ |
| | | |
| | 存儲引擎 | |---存儲引擎:負責數據的儲存和提取
| |________________________| |
|____________________________|
2.鎖
|
|-實現方式劃分 |--樂觀鎖,通常用於數據競爭不激烈的場景,多讀少寫,通過版本號和時間戳實現
| |--悲觀鎖,通常用於數據競爭激烈的場景,每次操作都會鎖定數據
|
|-影響範圍分 |--表鎖,鎖定整張表,開銷最小,但是會加劇鎖競爭
| |--行鎖,鎖定行級別,開銷最大,但是可以最大程度的支持併發
| | MVCC是行級鎖的變種,多數情況下避免了加鎖操作,開銷更低
| | MVCC是通過保存數據的某個時間點快照實現的
3.事務隔離級別(事務內和事務間可見性)
|
|--未提交讀:(Read UnCommitted),事務中的修改,即使沒提交對其他事務也是可見的
| 事務可能讀取未提交的數據,造成髒讀
|
|--提交讀:(Read Committed),一個事務開始時,只能看見已提交的事務所做的修改
| 也叫不可重複讀,同一個事務多次讀取同樣記錄可能不同
|
|--可重複讀:(RepeatTable Read),同一個事務中多次讀取同樣的記錄結果時結果相同
|
|--可串行化:Serializable),最高隔離級別,強制事務串行執行
4.存儲引擎
|
|--InnoDB引擎,最重要,使用最廣泛的存儲引擎。被用來設計處理大量短期事務,具有高性能和自動崩潰恢復的特性
|
|--MyISAM引擎,不支持事務和行級鎖,崩潰後無法安全恢復
5.性能優化
|
|--Schema和數據類型優化 |---數據類型|----(Unsigned)TinyInt,SmallInt,MediumInt,Int,BigInt
| | |----Float,Double,Decimal;VarChar,Char(適合存儲固定長度的字符串,如MD5值),Blob,Text
| | |----DateTime,TimeStamp
| |
| |---優化建議:儘量使用對應的數據類型。比如,不要用字符串類型保存時間,用整型保存IP。
|
|--索引|---作用:過濾(filter),排序或分組(sort/group),覆蓋(cover)
| |---原則:MySql只能高效的利用索引的最左前綴列
| |
| |---特點|----大部分情況下,索引都比較小,可以加載在內存中;
| | |----當使用覆蓋索引時,可以避免很多的磁盤操作,因此對性能也會有極大的改善
| |
| |---按物理存儲劃分:非聚集索引,聚集索引(葉子節點中存放的即爲整張表的行記錄數據,通過雙向鏈表進行維護表數據邏輯上的連續)
| |
| |---類型|----主鍵索引:alert table tablename add primary key (`字段名`)
| | 按使用|----唯一索引: alter table tablename add unique key (`字段名`); |-----單列索引
| | 劃分 |----普通索引: alter table tablename add index (`字段名`);---------|-----多列索引
| | |----全文索引: alter table tablename add FULLTEXT(`字段名`); | 包含特殊索引:覆蓋索引
| | |
| | |----索引查詢:show indexes from `表名`; 或 show keys from `表名`;
| | |----索引刪除:alter table `表名` drop index 索引名;
聚集索引
|
|特點:聚集索引不一定是主鍵,主鍵默認聚集的,所以是聚集索引;表必須有聚集索引,可以沒有主鍵;
|
|-innodb引擎的聚集索引 |
| |--有主鍵,那麼這個主鍵就是作爲聚集索引
| |--沒有主鍵,那麼該表的第一個唯一非空索引被作爲聚集索引
| |--沒有主鍵也沒有合適的唯一索引,那麼innodb內部會生成一個隱藏的主鍵作爲聚集索引,
| | 這個隱藏的主鍵是一個6個字節的列,該列的值會隨着數據的插入自增。
一個使用索引的基本查詢的工作流
|
|--step1. 使用索引以查找匹配的記錄,並得到數據的指針
|--step2. 使用相關數據的指針
|--step3. 返回查詢到的記錄
|
|--當可以使用覆蓋索引時,索引將會覆蓋查詢中的所有字段,因此第二步將會被跳過,於是查詢流程就變成了下面這樣:
|--step1. 使用索引以查找匹配的記錄
|--step2. 返回查詢到的記錄(因爲所有的記錄都在內存中)
6.索引優化案例
|
|--單個等於查詢 |---SELECT * FROM t WHERE c = 100;
| |---//給c字段創建索引
| |---SELECT c1, c2 FROM t WHERE c = 100
| |---//創建一個(c,c1,c2)的索引,因爲這樣是覆蓋索引(注意不是創建(c1,c2,c))
|
|--多個等於查詢 |---SELECT * FROM t WHERE c = 100 and d = 'xyz';
| |---//創建索引(c,d)或(d,c)
| |---//最常見的錯誤是建立兩個索引:一個是c,一個是d。
| |---//儘管MySQL根據index_merge算法能同時使用這兩個索引,但這樣依然是糟糕的選擇
|
|--等於與不等於並存的查詢 |---SELECT * FROM t WHERE c > 100 and d = 'xyz';
| |---//只要有一列使用了不等於計算,那麼它將阻止<其他列>使用索引
| |---//創建一個(d,c)的索引,這時候c和d兩個條件都會走索引
|
|--多個不等於查詢 |---SELECT * FROM t WHERE c > 100 and b < 10 and d = 'xyz';
| |---//定要把等於條件(在這裏是d)所在列,放在索引的最左側;(創建索引(d,b)或是索引(d,c))
| |---//還可以:按照字段b分區(partition on b),然後創建索引(d,c);
| |---//或按照字段c分區(partition onc),然後創建索引(d,b)
|
|--多個等於與排序 |---SELECT * FROM t WHERE c = 100 and d = 'xyz' ORDER BY b;
| |---//索引中字段的順序必須:先過濾後排序;創建(c,d,b)或(d,c,b)
| |---SELECT c1, c2 FROM t WHERE c = 100 and d = 'xyz' ORDER BY b
| |---//創建一個集過濾、排序、覆蓋於一體的索引:(c,d,b,c1,c2)
|
|--不等於與排序 |---SELECT * FROM t WHERE c > 100 and d = 'xyz' ORDER BY b
| |---//(d,b)或(d,c)。至於哪種效率更高,這取決於你的數據
| |---SELECT * FROM t WHERE c > 100 ORDER BY b
| |---//b和c只能選一種,具體選哪一種同樣和你的數據有關