1. 程式人生 > 其它 >SQL語句執行慢原因分析

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;