SQL語句執行慢原因分析


一個 SQL 執行的很慢,分兩種情況討論:
 
一、大多數情況下很正常,偶爾很慢,則有如下原因
 
(1)、數據庫在刷新臟頁,例如 redo log buffer寫滿了需要同步到磁盤。
當我們要往數據庫插入一條數據、或者要更新一條數據的時候,我們知道數據庫會在內存中把對應字段的數據更新了,但是更新之后,這些更新的字段並不會馬上同步持久化到磁盤中去,而是把這些更新的記錄寫入到 redo log 日記中去,等到空閑的時候,再通過redo log 里的日記把最新的數據同步到磁盤中去。(當內存數據頁跟磁盤數據頁內容不一致的時候,我們稱這個內存頁為“臟頁”。內存數據寫入到磁盤后,內存和磁盤上的數據頁的內容就一致了,稱為“干凈頁”。)
刷臟頁有下面4種場景(后兩種不用太關注“性能”問題):
1、redolog寫滿了:redo log 里的容量是有限的,如果數據庫一直很忙,更新又很頻繁,這個時候 redo log 很快就會被寫滿了,這個時候就沒辦法等到空閑的時候再把數據同步到磁盤的,只能暫停其他操作,全身心來把數據同步到磁盤中去的,而這個時候,就會導致我們平時正常的SQL語句突然執行的很慢,所以說,數據庫在在同步數據到磁盤的時候,就有可能導致我們的SQL語句執行的很慢了。
2、內存不夠用了:如果一次查詢較多的數據,恰好碰到所查數據頁不在內存中時,需要申請內存,而此時恰好內存不足的時候就需要淘汰一部分內存數據頁,如果是干凈頁,就直接釋放,如果恰好是臟頁就需要刷臟頁。
3、MySQL 認為系統“空閑”的時候:這時系統沒什么壓力。
4、MySQL 正常關閉的時候:這時候,MySQL 會把內存的臟頁都 flush 到磁盤上,這樣下次 MySQL 啟動的時候,就可以直接從磁盤上讀數據,啟動速度會很快。
 
(2)、執行的時候,遇到鎖,如表鎖、行鎖。
 
執行的這條語句,剛好這條語句涉及到的表,別人在用,並且加鎖了,我們拿不到鎖,只能慢慢等待別人釋放鎖了。或者,表沒有加鎖,但要使用到的某個一行被加鎖了,這個時候,我也沒辦法啊。
如果要判斷是否真的在等待鎖,我們可以用 show processlist這個命令來查看當前的狀態哦。
 
二、這條 SQL 語句一直執行的很慢,則有如下原因。
 
(1)、沒有用上索引:例如該字段沒有索引;由於對字段進行運算、函數操作導致無法用索引。一條語句執行都很慢的時候,可能是該語句沒有用上索引了,不過具體是啥原因導致沒有用上索引的呢,就要會分析了。
 
(2)、數據庫選錯了索引。
 由於統計的失誤,導致系統沒有走索引,而是走了全表掃描,是導致 SQL 語句執行的很慢的原因。統判斷是否走索引,掃描行數的預測其實只是原因之一,這條查詢語句是否需要使用使用臨時表、是否需要排序等也是會影響系統的選擇的,可以通過強制走索引的方式來查詢,例如
select * from t force index(a) where c < 100 and c < 100000;

 

 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM