对于Sybase IQ来说,往表中“插入/装入”数据从功能上说可以有如下方法:
(1) 使用LOAD TABLE语句把文本文件中的数据装载到IQ的表中
(2) 使用INSERT INTO SELECT/SELECT INTO FROM/INSERT LOATION把一个表中的记录写入另一个表中
(3) INSERT INTO VALUES又叫做单条INSERT/即一次插入一条记录
(4) 使用Sybase Open Client提供的bcp in
这几种方法功能上类似,但是在性能上的表现却有很大不同(特别是在插入数据量比较大时)。一般来说,性能表现是按照上面所给出方法的序号顺序依次变慢。即(1)是最快的方法,(4)是最慢的方法。特别是(4)最好不使用,当记录数大于几千时应严禁使用这种方法。
在这篇博文中我举一个方法(3)的例子,这个例子来自于我支持的一个项目。该项目有一个存储过程,在测试时发现执行的速度比较慢,特别是在多并发情况下就更严重。出于保密的考虑,这里只给出优化前该存储过程的部分经修改的片段:
--原存储过程代码片段
......
set rseString=startValue;
while(rseString <= endValue) loop
set sqlstr='insert into #temp11 values(''' || rseString || ''')';
execute immediate sqlstr;
call proc_other(rseString,param2,param3,...);
if rseString is null then
return 0
end if
end loop
......
大家注意上面代码片段中的那两行蓝色的代码,该代码使用了insert into values方法,即单条insert方法。这种方法在Sybase IQ中执行,大概的速度是2~100行/秒。如果该循环次数较多,比如几百、几千次甚至更多,那么执行速度就会比较慢。找到原因了,那么如何优化它呢?如果把单条insert改为“成批”insert,即方法(2)的INSERT SELECT方法就可以解决问题了。下面是优化后的存储过程代码:
......
set rseString=startValue;
set sqlstr=' insert into #temp11 ';
set i = 1;
while(rseString <= endValue) loop
if (i = 1) then
set sqlstr= sqlstr || ' select ' || rseString || ' ' ;
else
set sqlstr= sqlstr || ' union all select ' || rseString ;
end if ;
call proc_other(rseString,param2,param3,...);
if rseString is null then
execute immediate sqlstr;
return 0
end if
set i = i+1;
end loop
execute immediate sqlstr;
......
上面的代码可能有点复杂,我举一个简化的例子以说明问题:
--假设往test11表中写入四条记录,采用单条insert方法
insert into test11 value(‘aaaaa’);
insert into test11 value(‘bbbbb’);
insert into test11 value(‘ccccc’);
insert into test11 value(‘ddddd’);
--我们知道这种方法的效率不高,改为批量insert会提升性能
insert into test11
select 'aaaaa'
union all
select 'bbbbb'
union all
select 'ccccc'
union all
select 'ddddd';
如果大家理解了上面的这个简单例子的原理,那么对于那个用户存储过程修改的代码就好理解了。
阅读(8186) | 评论(0) | 转发(0) |