我们有一个存储客户地址的表格。然后,在整个系统的一些其他表中使用这些地址,以将地址与订单相关联。我们希望定期删除一年内未在订单上使用过的所有旧地址。
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多行,但删除时间要长得多)。
有更有效的方法吗?
答案 0 :(得分:0)
我最终使用PHP将子查询的结果传递给外部查询(获取每个ID,然后 implode 进入 NOT IN 在外部查询中列出。
我希望mysql能够足够聪明地看到子查询不依赖于外部查询,因此只运行一次并缓存结果,但我想它正在为每一行运行子查询外部查询,因此导致长时间运行(每个子查询约~4秒* ~800000)。