我有这张叫transactions
的桌子。它具有两列id
和report_id
。 id
是主键。
我想创建两个新表transaction_ids
和report_ids
,它们都只有一个列id
。
这两个新表都应该分别具有唯一事务ID和唯一报告ID的列表。
想到的第一个解决方案是:
Step 1:
insert into transaction_ids (select id from transactions); // as `trasnactions.id` is a primary key, uniqueness is guaranteed
Step 2:
insert into report_ids (select distinct report_id from transactions); // using DISTINCT to make sure uniqueness
-- OR --
create unique index on report_ids(id);
insert into report_ids (select report_id from transactions) on conflict(id) do nothing; // using on conflict to make sure of uniqueness
这里的问题是我遍历transactions
表两次。我认为这是一个for循环,我可以遍历该表一次,并在每次迭代时将transaction.id
和transaction.report_id
都推到正确的表中(假设我对该表存在on冲突处理report_ids
。
问题1 :有没有一种方法可以完成此操作,而无需最终编写for
循环。我对for
循环没有任何要求。只是我不得不多写几行;现在我只需两行就可以完成同样的事情。
问题2 :另外,我担心,如果我在for循环中并排插入一行,那么与只询问整列中的内容相比,postgres会花费很多时间一口气。在这种情况下,我将不得不比较仅遍历一次的性能提升是否值得通过逐行插入行来弥补性能损失
我还考虑过使用CTE:
with _ as (insert into transaction_ids (select id from transactions))
insert into report_ids (select distinct report_id from transactions);
-- OR --
create unique index on report_ids(id);
with _ as (insert into transaction_ids (select id from transactions))
insert into report_ids (select report_id from transactions) on conflict(id) do nothing;
但是,即使在这里,IMO仍然存在遍历两次的问题。 问题3 :这种方法比第一种方法有什么优势
问题4 :是否有推荐/首选/标准的方式来处理这种情况?
P.S .:我很担心,因为transactions
表的大小很大:
select pg_size_pretty(pg_total_relation_size('transactions'));
pg_size_pretty
----------------
2282 MB
(1 row)
select count(id) from transactions;
count
---------
1465605
(1 row)
select count(report_id) from transactions;
count
---------
1360204
(1 row)
select count(distinct report_id) from transactions;
count
--------
168508
(1 row)