【发布时间】:2010-10-09 00:13:03
【问题描述】:
我正在尝试尽快将记录从一个表复制到另一个表。
目前我有一个与此类似的简单光标循环:
FOR rec IN source_cursor LOOP
INSERT INTO destination (a, b) VALUES (rec.a, rec.b)
END LOOP;
我想把它加速到超快,所以我正在尝试一些 BULK 操作(一个 BULK FETCH,然后是一个 FORALL 插入):
这是我对批量选择/forall 插入的内容。
DECLARE
TYPE t__event_rows IS TABLE OF _event%ROWTYPE;
v__event_rows t__event_rows;
CURSOR c__events IS
SELECT * FROM _EVENT ORDER BY MESSAGE_ID;
BEGIN
OPEN c__events;
LOOP
FETCH c__events BULK COLLECT INTO v__event_rows LIMIT 10000; -- limit to 10k to avoid out of memory
EXIT WHEN c__events%NOTFOUND;
FORALL i IN 1..v__event_rows.COUNT SAVE EXCEPTIONS
INSERT INTO destinatoin
( col1, col2, a_sequence)
VALUES
( v__event_rows(i).col1, v__event_rows(i).col2, SOMESEQEUENCE.NEXTVAL );
END LOOP;
CLOSE c__events;
END;
我的问题是,到目前为止,我没有看到性能上有任何大的提升。根据我的阅读,它应该快 10 到 100 倍。
我是否错过了某个地方的瓶颈?
【问题讨论】:
-
对于 100,000 行,即使是批量插入也需要大约 300 (!) 秒
-
您的 SELECT 中有 ORDER BY 的原因吗?对 100,000 行进行排序可能相当昂贵,而且这似乎没有必要。此外,您的 %NOTFOUND 检查需要在您的 FORALL 之后进行 - 否则,如果您在最后一次迭代中获取少于 10,000 行,您将不会插入这些行。
-
谢谢!我将删除订单,但我认为它不会让我达到我正在寻找的速度......我将尝试获得 tkprof 分析并稍后更新。 %NOTFOUND 的好收获
-
您的目标表中有触发器吗?另外,如果您只是将数据从一个表复制到另一个表,您可以使用 SQL 语句而不是 PL/SQL 吗?
标签: oracle plsql query-optimization bulkinsert