我有一个大表(> 50M 行),我正在尝试将其转换为新的表格式。作为此过程的一部分,从第一次插入返回的行 ID 需要在第二次插入到第二个表中时使用。
我使用的 CTE 看起来像这样:
WITH inserted_data AS (
INSERT INTO table1 (column1, column2, column3, column4)
SELECT value1, value2, value3, value4
FROM original_table
RETURNING rowid, column4
)
INSERT INTO table2 (table1_id, column4)
SELECT rowid, column4
FROM inserted_data;
问题是,这慢得令人无法接受。仅 4800 行需要 21 秒,而 9600 行则需要大约 50 秒。按照这个速度,我预计 5000 万条记录大约需要 3 天的时间。我的时间限制在2小时左右。
如果我只执行第一次插入(无 CTE),查询速度会快 100 倍,对于 4800 行和 9600 行分别大约需要 200 毫秒和 500 毫秒。我知道第二次插入的时间也可以忽略不计。按照这个速度,查询将在指定的时间内完成。
问题是,我如何重写查询以按照单个查询可以完成的速度执行。将数据库中的所有数据转移到外部程序中会很麻烦且容易出错,并且需要额外的资源。如果我做一些类似编写带有循环的函数之类的事情,那么我不会一次性插入,并且我预计那里的性能也会很差。我认为使用临时表没有帮助,因为问题似乎仅在于 CTE 的存在。
我试过这个:
INSERT INTO table2 (table1_id, column4)
SELECT rowid, column4
FROM (
WITH inserted_data AS (
INSERT INTO table1 (column1, column2, column3, column4)
SELECT value1, value2, value3, value4
FROM original_table
RETURNING rowid, column4
)
)
但这给了我:
syntax error at or near "INTO"
如何将插入分成两个语句?第二个
insert
可能看起来像:
INSERT INTO table2
(table1_id, column4)
SELECT t1.rowid
, ot.column4
FROM original_table ot
JOIN table1 t1
ON t1.column1 = ot.value1
AND t1.column2 = ot.value2
AND t1.column3 = ot.value3
AND t1.column4 = ot.value4
对于
original_table
中的每一行,连接条件会查找插入到 table1
中的行。