2011-04-22 39 views
1

MySQL 5.1,Ubuntu 10.10 64bit,Linode虛擬機。Mysql更新性能突然降臨

所有表格均爲InnoDB

我們的一臺生產機器使用包含31個相關表的MySQL數據庫。在一張表中,有一個字段包含顯示值,這些值可能會每天改變數次,具體取決於條件。

顯示值的這些更改將在使用時間內全天使用。腳本會定期運行並檢查一些可能導致更改的便宜條件,並在條件滿足時更新顯示值。然而,這種懶惰的方法並沒有捕捉到所有可能出現的應該更新顯示值的場景,以便在工作時間內將後臺處理負載降到最低。

每晚一次腳本清除存儲在表中的所有顯示值並重新計算它們,從而捕獲所有可能的更改。這是一個非常昂貴的操作。

這已經運行了大約6個月。突然,3天前,夜間劇本的運行時間從平均40秒降至11分鐘。

存儲數據的總體比例沒有顯着變化。

我已經調查儘可能最好,而突然運行較慢的腳本部分是寫入新顯示值的最後一條更新語句。每行執行一次,給定行(INT(11))id和新顯示值(也是INT)。

update `table` set `display_value` = ? where `id` = ? 

有趣的是,之前的所有值的清洗是爲執行:

update `table` set `display_value` = null 

而這個說法仍然以相同的速度運行,一如既往。

display_value字段未編入索引。主鍵是idtable中有4個其他外鍵在執行期間的任何時候都沒有修改。

最終曲線球:如果我將這個模式轉儲到測試虛擬機,並執行相同的腳本,它將在40秒內運行,而不是11分鐘。我沒有試圖在生產機器上重建模式,因爲這不是一個長期的解決方案,我想了解這裏發生了什麼。

我的索引有問題嗎?在同一行上進行數千次更新之後,它們是否會陷入其中?


更新

我能夠運行在最優化的模式,徹底解決了這個問題。由於InnoDB不支持優化,這迫使重建,並解決了這個問題。也許我的索引損壞了?

mysqlcheck -A -o -u <user> -p 
+0

經過上週末進一步的測試,我一直無法弄清楚的突然變化。與以前的歷史相比,這個腳本仍然需要很長時間才能執行。我甚至完全重新啓動了生產機器。 – 2011-04-24 13:11:32

回答

2

有一個機會的UPDATE聲明不會在id使用索引,但是,這是非常不可能的(如果可能的),像你這樣的查詢。

您的表是否有機會被長時間運行的併發查詢/ DML鎖定?桌子使用哪個引擎?

另外,逐個記錄更新表並不高效。您可以將值加載到一個臨時表中批量的方式,並用一個命令更新主表:

CREATE TEMPORARY TABLE tmp_display_values (id INT NOT NULL PRIMARY KEY, new_display_value INT); 

INSERT 
INTO tmp_display_values 
VALUES 
(?, ?), 
(?, ?), 
…; 

UPDATE `table` dv 
JOIN tmp_display_values t 
ON  dv.id = t.id 
SET  dv.new_display_value = t.new_display_value; 
+0

感謝您的回覆。所有的表都是InnoDB。在執行時,應該沒有其他查詢在運行。我們的客戶羣都睡着了,沒有其他自動化流程正在運行。我意識到效率低下,直到現在,它從來都不是一個考慮因素。 – 2011-04-22 13:43:51

+0

我能夠通過重新構建模式來解決問題,但您關於性能的觀點仍然完全有效,因此我已將您的響應標記爲解決方案。謝謝! – 2011-04-27 00:26:47