比較加快sql語句的大批量插入數據,單車變摩托!


我們來比較一下下列SQL插入大量數據時的速度對比。

動態寫法->靜態寫法->批量插入寫法->集合寫法

1.

sqlplus scott/tiger

create table t(x int);

--將共享池清空

alter system flush shared_pool;

編寫一個簡單的存儲過程,實現將1到10萬的值插入t表的需求。

create or replace procedure proc1
as
begin
for i in 1..100000
loop
execute immediate
'insert into values('||i||')';
commit;
end loop;
end;
/

接下來

drop table t purge;
create table t(x int);
alter system flush shared_pool;
SCOTT@ PROD>set timing on
SCOTT@ PROD>exec proc1;

PL/SQL procedure successfully completed.

Elapsed: 00:00:46.30

SCOTT@ PROD>select count(*) from t;

COUNT(*)
----------
100000

2.利用綁定變量實現再次加速

SCOTT@ PROD>create or replace procedure proc2
2 as
3 begin
4 for i in 1..100000
5 loop
6 execute immediate
7 'insert into t values(:x)'using i;
8 commit;
9 end loop;
10 end;
11 /

接下來
SCOTT@ PROD>drop table t purge;
SCOTT@ PROD>create table t(x int);
SYS@ PROD>alter system flush shared_pool;
SCOTT@ PROD>exec proc2;

PL/SQL procedure successfully completed.

Elapsed: 00:00:10.97

SCOTT@ PROD>select count(*) from t;

COUNT(*)
----------
100000

對比時間加速了不少,這是因為第一種在共享池中每次執行插入語句有很多,而SQL_ID各自不同,每個語句都只是解析1次,執行1次解析了10萬次,而第二種加了綁定變量,10萬條語句可以被HASH成一個SQL_ID值,解析1次,執行10萬次,所以速度也就加快了。

注:細心的人會發想為什么會用到execute immediate,這是一種動態的SQL語句寫法,常用於表名字段名是變量,入參的情況,由於表名都不知道,所以當讓不能直接寫SQL語句了,所以要靠動態SQL語句根據傳入的表名參數,來拼成一條SQL語句,由execute immediate調用執行,但是這里顯然是多此一舉,直接insert into t values(i)完全可以,因為表名就是t.接下來然我們看看直接用后者的情況。

3.

create or replace procedure proc3

as

begin

for i in 1..100000

loop

insert into t values(i);

commit;

end loop;

end;

/

--這里要記得先預先執行一遍,將過程創建起來!

接下來:

drop table t purge;

create table t(x int);

alter system flush shared_pool;

set timing on

exec proc3;

Elapsed: 00:00:06.25

原因proc3也是實現了綁定變量,而動態SQL的特點是執行過程中再解析,而靜態SQL的特點是編譯的過程就解析好了。這也是提升速度的原因。

4.批量提交,再次加速(注意看commit與上面commit位置的不同)

create or replace procedure proc4

as

begin

for i in 1..100000

loop

insert into t values(i);

end loop;

commit;

end;

/

接下來:

drop table t purge;

create table t(x int);

set timing on

SCOTT@ PROD>exec proc4;

PL/SQL procedure successfully completed.

Elapsed: 00:00:01.69

5.集合的寫法,飛躍的提速

drop table purge;

create table t(x int);

alter system flush shared_pool;

set timing on

insert into t select rownum from dual connect by level<=100000;

99999 rows created.

Elapsed: 00:00:00.09

6.直接路徑方法加速

drop table t purge;

alter system flush shared_pool;

set timing on

create table t as select rownum x  from dual connect by level<=10000000;

用時:00:00:10.14(這里我有改為添加1000萬數據)

這里真正原因是insert into t select 的方式是將數據先寫到data buffer中,然后再刷到磁盤中,而create table t 的方式卻是跳過了數據緩沖區,直接寫進磁盤中,這種方式又稱直接路徑讀寫方式,因為原本是數據先到內存,再到磁盤,更改為直接到磁盤,少了個步驟,因而速度提升了許多。

直接路徑讀寫方式的缺點在於由於數據不經過數據緩沖區,所以在數據緩沖區中一定讀不到這些數據,因此一定會有物理讀,但是在很多時候,尤其是在海量數據需要遷移插入時,快速插入才是真正的第一目的,該表一般記錄巨大,data buffer 甚至還裝不下其十分之一,百分之一,這些共享內存的數據意義不大,這是我們一般會選擇直接路徑讀寫方式來完成海量數據的插入。

7.並行設置,無敵加速

drop table t purge;

alter system flush shared_pool;

set timing on

create table t nologging parallel 64 as select rownum x from dual connect by level<=10000000;

不過並行最大的特點就是占用了大多數CPU的資源,如果是一個並發環境,很多應用在跑,因為這個影響課別的應用,導致別的應用資源不足,將引起很多嚴重問題,所以要三思后行,連接清除該機器是否允許你這樣占用全部的資源。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM