我正在使用C#.NET 4.0应用程序,该应用程序使用ODP.NET 11.2.0.2.0和Oracle 11g数据库。该应用程序使用数据预加载一些查找表,并且由于大多数记录少于20条,因此脚本运行得非常快。但是,其中一个脚本有802条记录,插入记录需要248.671秒,这对于如此少量的数据而言似乎过多,而数据库通过大量数据进行快速操作。
所以我想知道,通过脚本插入数据的速度是否比编写脚本的当前方式更快?
正在插入的表定义如下:
CREATE TABLE FileIds
(
Id NUMERIC(38) NOT NULL
,Name NVARCHAR2(50) DEFAULT 'Unknown' NOT NULL
,FileTypeGroupId NUMERIC(38) NOT NULL
,CONSTRAINT FK_FileIds_FileTypeGroups FOREIGN KEY ( FileTypeGroupId ) REFERENCES FileTypeGroups ( Id )
)
要插入的脚本如下所示:
BEGIN
INSERT ALL
INTO FileIds ( Id, FileTypeGroupId ) VALUES (1152,5)
INTO FileIds ( Id, FileTypeGroupId ) VALUES (1197,10)
INTO FileIds ( Id, FileTypeGroupId ) VALUES (1200,6)
INTO FileIds ( Id, FileTypeGroupId ) VALUES (1143,3)
INTO FileIds ( Id, FileTypeGroupId ) VALUES (1189,9)
INTO FileIds ( Id, FileTypeGroupId ) VALUES (1109,7)
INTO FileIds ( Id, FileTypeGroupId ) VALUES (1166,4)
INTO FileIds ( Id, FileTypeGroupId ) VALUES (0,8)
INTO FileIds ( Id, FileTypeGroupId ) VALUES (1149,2)
INTO FileIds ( Id, FileTypeGroupId ) VALUES (1400,1)
INTO FileIds ( Id, FileTypeGroupId ) VALUES (1330,11)
INTO FileIds ( Id, FileTypeGroupId ) VALUES (1000,0)
-- 790 Records removed for example purposes.
SELECT * FROM DUAL;
COMMIT;
END;
外键中引用的FileTypeGroups表在加载FileIds表之前预先加载。没有与FileIds表关联的序列或触发器,但尚未为该表创建索引。
答案 0 :(得分:5)
<强>问题强>
对于某些类型的陈述,解析时间可能会呈指数级增长,尤其是INSERT ALL
。例如:
--Clear any cached statements, so we can consistently reproduce the problem.
alter system flush shared_pool;
alter session set sql_trace = true;
--100 rows
INSERT ALL
INTO FileIds(Id,FileTypeGroupId) VALUES(1, 1)
...
repeat 100 times
...
select * from dual;
--500 rows
INSERT ALL
INTO FileIds(Id,FileTypeGroupId) VALUES(1, 1)
...
repeat 500 times
...
select * from dual;
alter session set sql_trace = false;
通过tkprof运行跟踪文件,您可以看到大量行的解析时间显着增加。例如:
100行:
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.06 0.05 0 1 0 0
Execute 1 0.00 0.00 0 100 303 100
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.06 0.05 0 101 303 100
500行:
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 14.72 14.55 0 0 0 0
Execute 1 0.01 0.02 0 502 1518 500
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 14.74 14.58 0 502 1518 500
<强>解决方案强>
insert into ... select ... from dual union all ...
方法。它通常运行得更快,但解析性能也可能随着大小而显着降低。警告强>
不要从中学到错误的教训。如果您担心SQL性能,99%的情况下您最好将类似的东西组合在一起,而不是将它们分开。你正在以正确的方式做事,你只是遇到了一个奇怪的错误。 (我搜索了My Oracle Support,但找不到官方的错误。)