我正在尝试更新 order_item 中的每一行。Status 是一个新创建的列,并且必须具有 order_update 表中的最新值。一个项目可以有多个更新。
我正在使用 PostgreSQL 9.1
我有这个更新sql。
该表order_item
有 800K 记录。
该表order_update
有 500 万条记录。
update order_item
set status = (
select production_stage
from order_update
where id = (
select max(id)
from order_update
where order_item_id = order_item.id
)
);
我怎样才能让这个 sql 以最好的方式执行。我知道更新需要一些时间,我只想尽快更新。
我发现在 5Mil 记录上执行此 sql 时。
select max(id) from order_update where order_item_id = 100;
解释:
Result (cost=784.10..784.11 rows=1 width=0)" InitPlan 1 (returns $0)
-> Limit (cost=0.00..784.10 rows=1 width=8)
-> Index Scan Backward using order_update_pkey on order_update (cost=0.00..104694554.13 rows=133522 width=8)
Index Cond: (id IS NOT NULL)
Filter: (order_item_id = 100)
大约需要 6 秒。
当我在 1Mil 记录中执行相同的 sql 时:
说明:
Aggregate (cost=13.43..13.44 rows=1 width=8) -> Index Scan using
order_update_order_item_id_idx on order_update (cost=0.00..13.40
rows=11 width=8)
Index Cond: (order_item_id = 100)
大约需要 11 毫秒。
11 毫秒与 6 秒。为什么会有巨大的差异?
为了缩小一点,我试试这个:
select id from order_update where order_item_id = 100 order by id asc
limit 1
Total query runtime: 41 ms.
然后这个:
select id from order_update where order_item_id = 100 order by id desc
limit 1
Total query runtime: 5310 ms.
所以 asc 和 desc 的巨大差异。
解决方案:创建索引:
CREATE INDEX order_update_mult_idx ON order_update (order_item_id, id DESC);
更新 :
UPDATE order_item i
SET test_print_provider_id = u.test_print_provider_id
FROM (
SELECT DISTINCT ON (1)
test_print_provider_id
FROM orders
ORDER BY 1, id DESC
) u
WHERE i.order_id = u.id
AND i.test_print_provider_id IS DISTINCT FROM u.test_print_provider_id;