order_item のすべての行を更新しようとしています。Status は新しく作成された列であり、order_update テーブルからの最新の値を持っている必要があります。1 つのアイテムに複数の更新を含めることができます。
PostgreSQL 9.1 を使用しています
私はこの更新SQLを持っています。
テーブルorder_item
には 800K のレコードがあります。
テーブルorder_update
には 5Mil のレコードがあります。
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;