优化删除引用多个表

时间:2014-12-18 22:58:19

标签: mysql

我们有一个存储客户地址的表格。然后,在整个系统的一些其他表中使用这些地址,以将地址与订单相关联。我们希望定期删除一年内未在订单上使用过的所有旧地址。

address table:
id | address | created_at
1  | 1234 Rd | 2011-03-12 12:45:09
2  | 2345 Rd | 2012-04-12 13:39:19
3  | 3456 Rd | 2012-05-12 14:33:12
4  | 4567 Rd | 2014-12-12 15:19:54

customer_order table:
id | address_id | created_at
1  | 1          | 2011-03-12 12:50:00
2  | 2          | 2012-04-12 12:55:00
3  | 2          | 2014-09-12 12:50:00

group_order table:
id | address_id | created_at
1  | 2          | 2012-07-12 19:23:56
2  | 3          | 2012-10-19 14:36:28

所以我们要删除ID为1和3的地址,因为它们在一年多的时间里没有被用于订单。我们将保留最近创建的#4地址,并在去年使用#2,因此不应将其删除。

目前我所拥有的是:

DELETE FROM address WHERE created_at < DATE_SUB(NOW(), INTERVAL 365 DAY) AND id NOT IN (
  SELECT address_id FROM group_order WHERE created_at > DATE_SUB(NOW(), INTERVAL 365 DAY)
  UNION DISTINCT
  SELECT address_id FROM customer_order WHERE created_at > DATE_SUB(NOW(), INTERVAL 365 DAY)
)

但是,我的地址表包含800000多行,customer_order包含2.5M +行,group_order包含100000多行,还有另一个包含几百行的表,我还需要添加它们。因此删除需要执行时间长(子查询本身在大约4秒内返回400000多行,但删除时间要长得多)。

有更有效的方法吗?

1 个答案:

答案 0 :(得分:0)

我最终使用PHP将子查询的结果传递给外部查询(获取每个ID,然后 implode 进入 NOT IN 在外部查询中列出。

我希望mysql能够足够聪明地看到子查询不依赖于外部查询,因此只运行一次并缓存结果,但我想它正在为每一行运行子查询外部查询,因此导致长时间运行(每个子查询约~4秒* ~800000)。