2016-11-12 169 views
0

我想在MYSQL(亞馬遜RDS)中運行多表更新,它非常緩慢。MYSQL多表更新非常緩慢

我在做什麼?

基於1小時的時間範圍刪除所有重複的行。

下面我創建了一個臨時表來標識表中的重複行。此查詢在2秒內運行。

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ; 

CREATE TEMPORARY TABLE tmpIds (id int primary key); 
INSERT into tmpIds 
SELECT distinct 
    d.id 
FROM api d INNER JOIN api orig 
    on d.domain_id = orig.domain_id and d.user_id = orig.user_id 
WHERE 
    orig.created_at < d.created_at 
    AND d.created_at <= DATE_ADD(orig.created_at, Interval 1 hour) 
    AND d.type = 'api/check-end' 
    AND d.created_at >= '2016-08-01'; 

SET TRANSACTION ISOLATION LEVEL READ COMMITTED ; 

問題是更新查詢,它需要很長時間才能在生產服務器上運行。它也鎖定api表。

SET @TRIGGER_DISABLED = 1; 

UPDATE 
    api 
SET 
    deleted_at = now() 
WHERE type = 'api/check-end' AND created_at >= '2016-08-01' 
    AND id IN (SELECT id FROM tmpIds); 

SET @TRIGGER_DISABLED = 0; 

我也試過這個版本:

SET @TRIGGER_DISABLED = 1; 

UPDATE 
    api a, 
    tmpIds ti 
SET 
    a.deleted_at = now() 
WHERE 
    type = 'api/check-end' AND created_at >= '2016-08-01' AND a.domain_id < 10 AND a.id = ti.id; 

SET @TRIGGER_DISABLED = 0; 

STATS

  • 臨時表:32,000行
  • API表:總 - 25萬行,where子句後(類型,created_at) 200,000行。
  • 該api表具有昂貴的觸發器,這就是爲什麼我把它們關掉 。
  • 1000分鐘更新運行6分鐘。
  • 上有API表的主鍵
+0

顯示說明。您可以做的一件事是用JOIN替換子查詢,但問題可能是臨時表無法索引,您可能更適合使用真正的表,您可以根據需要截斷表。 – Mihai

回答

0

問題是下面的語句指數:

SET @TRIGGER_DISABLED = 1; 

沒有禁用觸發器。我必須刪除api表上的UPDATE觸發器,並在1.3秒內運行UPDATE。

任何關於在運行查詢時禁用觸發器的最佳方法的幫助?

+0

如果你不需要觸發器,可以放在一起並使用事件調度器來創建一個事件,該事件將在特定時間間隔內執行任何觸發器的操作。看起來你有一些沉重的處理,如果你在更新發生時不需要觸發器,那麼可以替換它呢? –

+0

感謝您的回覆,我們將把所有觸發器移動到存儲過程中。 – DropAcid