2016-11-12 172 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