文章參考:https://joonwhee.blog.csdn.net/article/details/106893197
問題:如何做慢 SQL 優化?
首先要搞明白慢的原因是什么:是查詢條件沒有命中索引?還是 load 了不需要的資料列?還是資料量太大?所以優化也是針對這三個方向來的:
-
首先用 explain 分析陳述句的執行計劃,查看使用索引的情況,是不是查詢沒走索引,如果可以加索引解決,優先采用加索引解決,
-
分析陳述句,看看是否存在一些導致索引失效的用法,是否 load 了額外的資料,是否加載了許多結果中并不需要的列,對陳述句進行分析以及重寫,
-
如果對陳述句的優化已經無法進行,可以考慮表中的資料量是否太大,如果是的話可以進行垂直拆分或者水平拆分,
1. 水平拆分與垂直拆分
1.1 水平分表
例:QQ的登錄表
-
假設QQ的用戶有100億,如果只有一張表,每個用戶登錄的時候資料庫都要從這100億中查找,會很慢很慢,如果將這一張表分成100份,每張表有1億條,就小了很多,比如
qq0,qq1,qq1...qq99表, -
用戶登錄的時候,可以將用戶的
id%100,那么會得到0-99的數,查詢表的時候,將表名qq + 取模的數連接起來,就構建了表名,比如123456789用戶,取模的89,那么就到qq89表查詢,查詢的時間將會大大縮短,
1.2 垂直分表
- 垂直分割指的是:表的記錄并不多,但是欄位卻很長,表占用空間很大,檢索表的時候需要執行大量的IO,嚴重降低了性能,這時需要把大的欄位拆分到另一個表,并且該表與原表是一對一的關系,
例如:學生答題表student_question,有如下5個欄位:
Id,name,分數,題目,回答,其中題目和回答是比較大的欄位,Id,name,分數比較小,
如果我們只想查詢id為8的學生的分數:select 分數 from tt where id = 8;
- 雖然只是查詢分數,但是
題目和回答這兩個大欄位也是要被掃描的,很消耗性能,然而我們只需要關心分數,并不想查詢題目和回答,這種情況下就可以使用垂直分割, - 我們可以把題目單獨放到一張表中,通過id與tt表建立一對一的關系,同樣將回答單獨放到一張表中,這樣我們查詢
student_question中的分數的時候就不會掃描題目和回答這兩個大欄位了,
1.3 小結
- 水平分割是表中資料量過大,嚴重影響查詢效率時,將1張資料量龐大的表按照某種條件進行拆分成N張名稱不同欄位和資料型別相同的表,
- 垂直分割是表中記錄數不多,但是欄位很多,且欄位長,表占用空間大的情況下,把大的欄位拆分到另一個表,并且該表與原表是一對一的關系,
2. 主從復制
參考文章:MySQL主從復制讀寫分離,看這篇就夠了
2.1 MySQL主從復制介紹
MySQL主從復制涉及到三個執行緒,一個運行在主節點(Log Dump Thread),其余兩個(I/O Thread,SQL Thread)運行在從節點,如下圖所示
主從復制默認是異步的模式,具體程序如下:
-
從節點上的 I/O 執行緒連接主節點,請求讀取主庫的二進制日志檔案(bin log 日志)的指定位置(bin log position)之后的日志內容;
-
主節點執行緒接收到來自從節點 I/O 執行緒的請求后,讀取主節點中的二進制日志檔案(bin log 日志)的指定位置之后的日志資訊,回傳給從節點,
- 回傳給從節點的內容資訊中除了日志所包含的資訊之外,還包括本次回傳的資訊的 bin-log file(二進制日志檔案) 以及 bin-log position(讀取的位置);
-
從節點的 I/O 執行緒接收到內容后,將接收到的日志內容更新到 relay log (中繼日志)中,并將讀取到的 bin log file(檔案名)和position(位置)保存到 master-info 檔案中,以便在下一次讀取的時候能夠清楚的告訴 Master “我需要從某個bin-log 的哪個位置開始往后的日志內容”
-
從節點的 SQL 執行緒檢測到 relay-log 中新增加了內容后,會決議 relay-log 的內容,并在本資料庫中執行,
2.2 異步復制,主庫宕機后,資料可能丟失?
可以使用半同步復制或全同步復制,
- 半同步復制:
修改陳述句寫入bin log后,不會立即給客戶端回傳結果,而是首先通過log dump 執行緒將 binlog 發送給從節點,從節點的 I/O 執行緒收到 binlog 后,寫入到 relay log,然后回傳 ACK 給主節點,主節點 收到 ACK 后,再回傳給客戶端成功,
半同步復制的特點:
- 確保事務提交后 binlog 至少傳輸到一個從庫,不保證從庫應用完這個事務的 binlog,
- 性能有一定的降低,回應時間會更長,
- 網路例外或從庫宕機,卡主主庫,直到超時或從庫恢復,
- 全同步復制:主節點和所有從節點全部執行了該事務并確認才會向客戶端回傳成功,因為需要等待所有從庫執行完該事務才能回傳,所以全同步復制的性能必然會收到嚴重的影響,
2.3 主庫寫壓力大,從庫復制很可能出現延遲?
-
可以使用并行復制(并行是指從庫多個SQL執行緒并行執行 relay log),解決從庫復制延遲的問題,
-
MySQL 5.7 中引入基于組提交的并行復制,其核心思想:一個組提交的事務都是可以并行回放,因為這些事務都已進入到事務的 prepare 階段,則說明事務之間沒有任何沖突(否則就不可能提交),
-
判斷事務是否處于一個組是通過 last_committed 變數,last_committed 表示事務提交的時候,上次事務提交的編號,如果事務具有相同的 last_committed,則表示這些事務都在一組內,可以進行并行的回放,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/279876.html
標籤:其他
上一篇:從零搭建若依(Ruoyi-Vue)管理系統(9)--Mybatias分頁支持
下一篇:sql資料庫從零開始學習(一)
