当运行像“插入表”这样的查询时,我们如何处理提交大小?即来自anotherTable的所有记录都插入到单个事务中,或者有没有办法设置提交大小?
非常感谢~Sri
PS:我是这里的第一个计时器,这个网站看起来非常好!
答案 0 :(得分:3)
在一个原子语句的好数据库中,所以不,没有办法限制插入的记录数 - 这是一件好事!
答案 1 :(得分:3)
在原始海报希望避免回滚空间问题的背景下,答案非常简单。回滚段的大小应该适合于交易的大小,而不是相反。您在交易完成时提交。
答案 2 :(得分:2)
我已经用各种语言(主要是Java)编写代码来执行像你描述的那样的批量插入。每次我这样做,主要是从解析一些输入文件或类似的东西,我基本上只准备从总量(通常批量4000左右)插入数据的子集,并将数据提供给我们的DAO层。所以它是以编程方式完成的。我们从来没有注意到这样做的任何真正的性能打击,我们处理了几百万条记录。如果您要插入大型数据集,则无论您如何操作,操作都会“花费一段时间”。
答案 3 :(得分:1)
除非您明确编码,否则无法处理提交大小。例如,您可以使用where循环,并编写一种方法来限制您选择的数据量。
答案 4 :(得分:1)
David Aldridge是对的,当您希望INSERT成功或失败时,根据最大事务调整回滚段的大小。
一些替代方案:
如果您不关心能够将其回滚(这就是该段的用途),您可以使用ALTER TABLE并添加 NOLOGGING 子句。但这不是一个明智之举,除非您正在加载一个报告表,在该表中删除所有旧行并加载新行或其他特殊情况。
如果您可以插入某些行而其他行由于某种原因而失败,那么使用 INSERT INTO LOG ERRORS INTO 语法添加对处理失败的支持
答案 5 :(得分:0)
如果您需要限制数据集,请在查询中构建该限制。
例如,在Microsoft SQL Server的说法中,您可以使用“TOP
N
”来确保查询仅返回有限数量的行。
INSERT INTO thisTable
SELECT TOP 100 * FROM anotherTable;
答案 6 :(得分:0)
我想这样做的原因是为了避免回滚段空间不足。另外,我希望定期在目标表中填充结果。
我不想使用where循环,因为它可能会增加性能开销。不是吗?
〜斯里兰卡
答案 7 :(得分:0)
您是对的,您可能希望批量运行大型插入。附加的链接显示了在SQL Server中执行此操作的方法,如果您使用的是不同的后端,则可以执行类似的操作,但确切的语法可能不同。这是循环可以接受的情况。
答案 8 :(得分:0)
“我之所以这样做,是为了避免回滚段空间不足。另外,我希望定期在目标表中填充结果。”
第一个问题只是正确调整撤消表空间的大小。由于撤消是对现有行的删除,因此不需要大量空间。相反,删除通常需要更多空间,因为它必须有一个整个已删除行的副本才能重新插入它以撤消它。
对于第二个,请查看v $ session_longops和/或v $ sql中的rows_processed
答案 9 :(得分:0)
INSERT INTO TableInserted
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (ORDER BY ID) AS RowNumber
FROM TableSelected
) X
WHERE RowNumber BETWEEN 101 AND 200
你可以很容易地将上面的内容包装成while循环,用变量替换101和200。这比一次做1条记录要好。
我不知道哪些版本的Oracle支持窗口函数。
答案 10 :(得分:0)
这是一个扩展注释,用于证明设置NOLOGGING的索引不有助于减少INSERT的UNDO或REDO。
手册暗示NOLOGGING索引可以通过减少UNDO和REDO来帮助改进DML。由于NOLOGGING帮助表DML,它似乎也有助于INDEX更改。但是这个测试用例表明将索引更改为NOLOGGING对INSERT语句没有影响。
drop table table_no_index;
drop table table_w_log_index;
drop table table_w_nolog_index;
--#0: Before
select name, value from v$mystat natural join v$statname where display_name in ('undo change vector size', 'redo size') order by 1;
--#1: NOLOGGING table with no index. This is the best case scenario.
create table table_no_index(a number) nologging;
insert /*+ append */ into table_no_index select level from dual connect by level <= 100000;
commit;
select name, value from v$mystat natural join v$statname where display_name in ('undo change vector size', 'redo size') order by 1;
--#2: NOLOGGING table with LOGGING index. This should generate REDO and UNDO.
create table table_w_log_index(a number) nologging;
create index table_w_log_index_idx on table_w_log_index(a);
insert /*+ append */ into table_w_log_index select level from dual connect by level <= 100000;
commit;
select name, value from v$mystat natural join v$statname where display_name in ('undo change vector size', 'redo size') order by 1;
--#3: NOLOGGING table with NOLOGGING index. Does this generate as much REDO and UNDO as previous step?
create table table_w_nolog_index(a number) nologging;
create index table_w_nolog_index_idx on table_w_nolog_index(a) nologging;
insert /*+ append */ into table_w_nolog_index select level from dual connect by level <= 100000;
commit;
select name, value from v$mystat natural join v$statname where display_name in ('undo change vector size', 'redo size') order by 1;
以下是统计信息查询的结果。这些数字是会议的累积数字。测试用例#2和#3在UNDO和REDO中具有相同的增加。
--#0: BEFORE: Very little redo or undo since session just started.
redo size 35,436
undo change vector size 10,120
--#1: NOLOGGING table, no index: Very little redo or undo.
redo size 88,460
undo change vector size 21,772
--#2: NOLOGGING table, LOGGING index: Large amount of redo and undo.
redo size 6,895,100
undo change vector size 3,180,920
--#3: NOLOGGING table, NOLOGGING index: Large amount of redo and undo.
redo size 13,736,036
undo change vector size 6,354,032
答案 11 :(得分:-1)
您可能只想制作索引NOLOGGING。这样表数据是可恢复的,但如果恢复表,则需要重建索引。索引维护可以创建大量撤消。