我必须在Oracle数据库表中插入大约100万行,如下所示:
create table ID_NO_APPROVAL_TEST
(
ID NUMBER(10) not null
primary key,
REASON_ID NUMBER(10) not null,
TAXCODE VARCHAR2(30) not null,
STATUS NUMBER(1),
CREATE_DATE DATE default SYSDATE not null,
USER_CREATE VARCHAR2(100) not null
)
具有以下值
values(ID_SEQ.NEXTVAL,1,'xxxxxxxxxxxx2',1,sysdate,'abcxyz');
values(ID_SEQ.NEXTVAL,5,'xxxxxxxxxxxx3',1,sysdate,'abcxyz');
values(ID_SEQ.NEXTVAL,3,'xxxxxxxxxxxx3',1,sysdate,'abcxyz');
values(ID_SEQ.NEXTVAL,4,'xxxxxxxxxxxx5',1,sysdate,'abcxyz');
.....
解决此问题的最佳方法是什么?
我尝试下面的声明与10千行:
insert /*+ APPEND*/
into ID_NO_APPROVAL_TEST(ID, reason_id, TAXCODE, status, create_date, USER_CREATE)
select GET_ID_NO_APPROVAL_ID_TEST_SEQ, 275978, '100100939', 1,sysdate,'DUYNQ7' from dual
union select GET_ID_NO_APPROVAL_ID_TEST_SEQ, 1,'xxxxxxxxxxxx2',1,sysdate,'abcxyz' from dual
union select GET_ID_NO_APPROVAL_ID_TEST_SEQ, 4,'xxxxxxxxxxxx3',1,sysdate,'abcxyz') from dual
union select GET_ID_NO_APPROVAL_ID_TEST_SEQ, 7,'xxxxxxxxxxxx3',1,sysdate,'abcxyz' from dual
....
但我花了两分钟才说完这句话
2条答案
按热度按时间qyyhg6bp1#
INSERT VALUES用于单行。您需要一个包含大量行的行集,其中源是数据库中的另一个表。为此,使用INSERT SELECT:
这可以通过增加ID_SEQ序列该高速缓存设置并启用并行dml来加速(假设您在具有CPU容量的多核数据库服务器上运行):
cwdobuhd2#
减少每个SQL语句中运行的行数,性能将大大提高。
构建大型SQL语句效果很好,但是构建 * 巨大 * 的SQL语句可能会导致问题。具体来说,
INSERT
语句中的几乎所有性能时间都用于解析SQL。要验证这一点,请运行完全相同的语句两次,由于该语句已经被解析并缓存在内存中,因此运行时间几乎为零。或者,您可以跟踪语句并查看解析时间,就像我在this answer中所做的那样。运行100万个独立的语句将花费很长时间,但是运行100万个合并在一起的语句也将花费很长时间。最佳选择取决于您的Oracle版本。在10 g或更低的情况下,我的目标是100。在19 c中,使用您的表和示例数据,1000工作得很好。使用您的表和示例数据在我的数据库上的运行时间,请参见下表。请注意,这些值在某个点之后不会线性增加。
理想情况下,您可以直接从另一个表插入这些数据,或者使用SQL*Loader、JDBC批处理等工具。但这并不总是可能的,只要注意每条语句的大小,用一个SQL脚本插入100万行是很好的。由于只有100万行,您无需担心并行性、
UNION ALL
而不是UNION
、直接路径写入、序列缓存等问题。正确地调整INSERT
批处理的大小可以解决99%的问题;别担心剩下的1%。