Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有大数据集的SQL插入_Sql_Database_Oracle - Fatal编程技术网

具有大数据集的SQL插入

具有大数据集的SQL插入,sql,database,oracle,Sql,Database,Oracle,当运行“insert into table”之类的查询时,我们如何处理提交大小?也就是说,是否将另一个表中的所有记录插入到单个事务中,或者是否有方法设置提交大小 非常感谢 PS:我是第一次来这里,这个网站看起来很不错 在好的数据库中,这是一个原子语句,所以不,没有办法限制插入的记录数-这是一件好事 除非显式编码,否则无法处理提交大小。例如,您可以使用where循环,并编写一种方法来限制所选数据的数量。如果需要限制数据集,请将该限制构建到查询中 例如,用Microsoft SQL Server的说

当运行“insert into table”之类的查询时,我们如何处理提交大小?也就是说,是否将另一个表中的所有记录插入到单个事务中,或者是否有方法设置提交大小

非常感谢
PS:我是第一次来这里,这个网站看起来很不错

在好的数据库中,这是一个原子语句,所以不,没有办法限制插入的记录数-这是一件好事

除非显式编码,否则无法处理提交大小。例如,您可以使用where循环,并编写一种方法来限制所选数据的数量。

如果需要限制数据集,请将该限制构建到查询中

例如,用Microsoft SQL Server的说法,可以使用“
TOP
N
”确保查询只返回有限的行数

INSERT INTO thisTable
  SELECT TOP 100 * FROM anotherTable;

我之所以要这样做,是为了避免回滚段超出空间。另外,我希望看到结果定期填充到目标表中

我不想使用where循环,因为它可能会增加性能开销。不是吗


~Sri

我已经用各种语言编写了代码,主要是Java,来执行您所描述的批量插入。每次我这样做,主要是通过解析一些输入文件或类似的东西,我基本上只准备一个子集数据,从总量(通常是4000个左右的批次)中插入,并将该数据提供给我们的DAO层。所以它是按程序完成的。我们从来没有注意到这样做有任何真正的性能损失,我们正在处理数百万张唱片。如果要插入较大的数据集,无论您如何操作,该操作都将“花费一段时间”。

您是对的,您可能希望批量运行较大的插入。附加的链接显示了一种在SQL Server中执行此操作的方法,如果您使用不同的后端,您可以执行类似的操作,但确切的语法可能会有所不同。在这种情况下,循环是可以接受的

“我之所以要这样做,是为了避免回滚段的空间不足。此外,我还希望看到结果定期填充到目标表中。”

第一个问题只是正确调整撤消表空间的大小。由于撤消是对现有行的删除,因此不需要太多空间。相反,删除通常需要更多的空间,因为它必须有整个已删除行的副本才能重新插入以撤消它


第二,看看v$sql中处理的v$session_longops和/或rows_。在原始海报希望避免回滚空间问题的上下文中,答案非常简单。回滚段的大小应该与事务的大小相适应,而不是相反。事务完成时进行提交。

David Aldridge说得对,如果希望插入作为一个整体成功或失败,请根据最大事务调整回滚段的大小

一些备选方案:

如果您不关心是否能够回滚它(这就是该段的目的),您可以更改表并添加NOLOGGING子句。但这不是一个明智的举动,除非您正在加载一个报告表,其中删除所有旧行并加载新行,或者其他一些特殊情况


如果您对某些行被插入而其他行由于某种原因失败表示满意,那么可以添加对处理失败的支持,使用INSERT INTO将错误记录到语法。

您可能只想使索引不记录。这样,表数据是可恢复的,但如果恢复了表,则需要重建索引。索引维护可以创建大量的撤消操作

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。这比一次录制一张唱片要好


我不知道什么版本的Oracle支持窗口功能。

这是一个扩展注释,用于证明将索引设置为NOLOGGING无助于减少插入的撤消或重做

该手册暗示,通过减少撤消和重做,无日志索引可能有助于改进DML。由于NOLOGGING有助于表DML,因此它也有助于索引更改似乎是合乎逻辑的。但这个测试用例表明,将索引更改为NOLOGING对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;

但是对于大的插入,这通常是次优的。我不确定为什么这个答案会被否决,因为它是正确的。我和尼克都不明白。你应该在你的问题上加上“甲骨文”由于IIRC,回滚部分是Oracle的一项功能。我相信这个网站上的预期方法是,你应该用任何进一步的信息编辑你的原始问题,因为它可能会随着其他答案的投票而丢失。你能将此添加为对原始问题的修改吗?@sri这不是答案,这应该是对原始问题1的评论或编辑,因为这是一个非常缓慢的方法。对于一个100000条记录的表,您要访问“TableSelected”1000次,每次访问都可能是一次完整的表扫描……您假设它总是一次表扫描。好的,把数据放在临时表中。你最好的办法是什么?在这里看不到。对于新手,请尽量避免在问题中添加不必要的元素。使用注释部分(节俭地)进行相同的操作。:)逐位生成一个字节。不幸的是,只有当。@jonearles,从您链接的文档中,“此设置还确定是否记录针对索引的后续…直接路径插入操作。”您可以使用append提示获取直接路径插入。好的一点,我应该更仔细地阅读我的链接!但我仍然认为说NOLOGGING只适用于创建或重建索引是准确的。事实上,汤姆多次说同样的话。其他一些在线资源,以及我的简单测试,也同意NOLOGGING不会让人失望
--#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