程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle教程 >> ORACLE數據庫測試數據插入速度

ORACLE數據庫測試數據插入速度

編輯:Oracle教程

一,沒有優化的速度:Executed in 69.436 seconds

drop table t purge;
create table t(x int);
/*清空共享池,注意在生產環境中千萬不能做這步操作*/
alter system flush shared_pool;

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

下面查看下proc1插入100000記錄的執行時間
SQL> set timing on;
SQL> exec proc1;

PL/SQL procedure successfully completed

Executed in 69.436 seconds

/*我們可以通過下面的語句查看此存儲過程執行的具體步驟*/
select t.sql_text,t.sql_id,t.parse_calls,t.executions from v$sql t where sql_text like '%insert into t values%';

為了方便查看我用PL/SQL DEVELOPER 執行的上面語句,如下圖:

\

從上面可以看出,每個語句都只是解析了一次,執行了一次,一共解析了10萬次,也許你會問你上面只有7136行記錄啊,你怎麼說是解析了10萬次呢。我可以告訴你肯定是解析了10萬次,因為我的共享池空間不大,容納不小10萬條信息,根據FIFO 的原理你可以看出,現在我查出來的都是從92000多開始的SQL STATEMENT記錄。我們知道這些SQL語句都是相似的沒有必要解析10萬次,即每一條語句都解析一次。這個PROC1 沒有用綁定變量,這就是我們可以優化的地方。我們用綁定變量來重新測試下,下面的PROC2就只用解析一次就可以了,當然速度肯定會提高不少。

二,使用綁定變量優化後的速度:Executed in 26.505 seconds

drop table t purge;
create table t(x int);
/*清空共享池,注意在生產環境中千萬不能做這步操作*/
alter system flush shared_pool;

create or replace procedure proc2
as
begin
for i in 1 .. 100000
loop
execute immediate
'insert into t values(:x)' using i;
commit;
end loop;
end;
/

SQL> set timing on;
SQL> exec proc2;

PL/SQL procedure successfully completed

Executed in 26.505 seconds

從上面可以看出,時間基本上減少了一半。

/*我們可以通過下面的語句查看此存儲過程執行的具體步驟*/
select t.sql_text,t.sql_id,t.parse_calls,t.executions from v$sql t where sql_text like '%insert into t values%' order by 1;

\

從上面的執行情況可以知道,解析了一次,執行了10萬次。完全符合我們的猜想,所以速度大大提升了。

execute immediate是一種動態SQL的寫法,常用於表名字段名是變量,入參的情況,由於表名不知道,所以不能直接寫SQL ,所以要靠動態SQL語句傳人表名和字段名參數拼接成SQLSTATEMENT,有execute immediate調用執行。但是我的這個例子完全可以不需要動態的,可以用靜態的寫好。

三,用靜態改寫後的速度:Executed in 19.391 seconds

drop table t purge;
create table t(x int);
/*清空共享池,注意在生產環境中千萬不能做這步操作*/
alter system flush shared_pool;

create or replace procedure proc3
as
begin
for i in 1 .. 100000
loop
insert into t values(i);
commit;
end loop;
end;
/

SQL> set timing on;
SQL> exec proc3;

PL/SQL procedure successfully completed

Executed in 19.391 seconds

\

從上面可以看出,proc3也實現了綁定變量,而且動態的特點是執行過程中再解析,而靜態的SQL的特點是編譯的過程是解析好的,所以上面的PRARSE_CALLS是0。注意這個和上面一個圖比較,上面的時PARSE_CALLS 是1,而這個是0,所以靜態的少了一個執行的時候的解析過程。

我們可以看出上面的三個PROC都是一條語句就commit一次,我們完全沒有必要這樣做,我們可以一起提交。如下例: commit的時把log_buffer裡的信息通過LGWR寫到online redo log裡,觸發LGWR寫10萬次,而且我們知道LGWR寫的太頻繁了。

四,批量提交的速度:Executed in 11.42 seconds

drop table t purge;
create table t(x int);
/*清空共享池,注意在生產環境中千萬不能做這步操作*/
alter system flush shared_pool;
create or replace procedure proc4
as
begin
for i in 1 .. 100000
loop
insert into t values(i);
end loop;
commit;
end;
/

SQL> set timing on;
SQL> exec proc4;

PL/SQL procedure successfully completed

Executed in 11.42 seconds

可以看出我們用的時間更少了。

五,集合寫法的速度:Executed in 0.452 seconds

drop table t purge;
create table t(x int);
/*清空共享池,注意在生產環境中千萬不能做這步操作*/
alter system flush shared_pool;

/*下面的語句是由上面的一條一條的插入改為一整批的寫進data buffer區裡,所以比上面的快,批處理肯定比一個一個的執行快*/
insert into t select rownum from dual connect by level<=100000;

SQL> set timing on;
SQL> insert into t select rownum from dual connect by level<=100000;

100000 rows inserted

Executed in 0.452 seconds

這個是上面的前四種都是一條一條的插入的,我這個集合寫法是一整批地寫進到DATA BUFFER裡,所以比上面的四種情況要快的多。

六,用直接路徑寫法速度(100萬條記錄):Executed in 1.514 seconds
/*下面用直接路徑的方式來操作,速度會比上面更快,所謂直接路徑就是數據不經過database buffer,而是直接寫到磁盤,少了一步寫到數據緩沖區(database buffer)的動作*/
drop table t purge;
alter system flush shared_pool;
SQL> set timing on;
SQL> create table t as select rownum x from dual connect by level<=1000000;

Table created

Executed in 1.514 seconds

注意此時我插入的記錄數十上面的10倍,我是插入100萬條記錄只用了1.514 seconds.

注意:直接路徑的寫法比集合寫法快事因為,insert into select .... 的方式是將數據首先寫到data buffer裡,然後再刷到磁盤裡。而create as t 的方式跳過了數據緩沖區(data buffer), 直接寫進磁盤中,這種方式稱之為直接路徑讀寫方式。本來是先到內存,在到磁盤,更改為直接到磁盤,少了一個步驟,所以速度快了。

七,並行寫法的速度(100萬條記錄):Executed in 0.733 seconds

/*並行加直接路徑,而且是不寫日志的,所以速度比上面的更快*/
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<=100000;

SQL> set timing on;
SQL> create table t nologging parallel 4 as select rownum x from dual connect by level<=1000000;

Table created

Executed in 0.733 seconds

我上面只用了parallel 4,如果更多的話,還會更快!!!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved