往表中插入大量資料的方法(一)
往表中插入大量資料的方法(一)
下面這個表是根據all_objects 表的結構構造的。用來模擬大量的資料。
SQL> select count(*) from allobjects;
COUNT(*)
----------
3375996
Elapsed: 00:00:07.71
建立兩張與allobjcts 結構相同的表。
SQL> edit
Wrote file afiedt.buf
1 create table alltest01 as select * from allobjects
2* where 1=2
SQL> /
Table created.
Elapsed: 00:00:00.06
SQL> edit
Wrote file afiedt.buf
1 create table alltest02 as select * from allobjects
2* where 1=2
SQL> /
Table created.
Elapsed: 00:00:00.08
使用傳統的insert 語句往alltest01 插入大量的資料。
SQL> insert into alltest01 select * from allobjects;
3375996 rows created.
Elapsed: 00:01:12.60
使用insert append 方式往alltest02 插入大量的資料。
SQL> insert /*+ append */ into alltest02 select * from allobjects;
3375996 rows created.
Elapsed: 00:00:53.78
透過上述的兩條insert 語句我們可以明顯的發現效能上面的差別。傳統的
insert 方式比insert append 方式慢了19秒左右,兩者不在同一個數量級上。
貌似insert append 方式在插入資料方面很有效能優勢。但是除了效能方面
的優勢,存在以下的一些限制:
一、在commit或者rollback前當前不能對錶進行查詢,和執行DML語句。
其他會話中可以進行查詢,但是看到的是insert append 以前的資料,並且
其他會話中執行的DML 語句會被阻塞。另外一個時間點只能有一個會話對
指定的表發起insert append.
SQL> select count(*) from alltest02;
select count(*) from alltest02
*
ERROR at line 1:
ORA-12838: 無法在並行模式下修改之後讀/修改物件
Elapsed: 00:00:00.04
SQL> delete from alltest02;
delete from alltest02
*
ERROR at line 1:
ORA-12838: 無法在並行模式下修改之後讀/修改物件
Elapsed: 00:00:00.02
SQL> update alltest02
2 set object_id = 1
3 /
update alltest02
*
ERROR at line 1:
ORA-12838: 無法在並行模式下修改之後讀/修改物件
Elapsed: 00:00:00.01
SQL> insert into alltest02 select * from allobjects;
insert into alltest02 select * from allobjects
*
ERROR at line 1:
ORA-12838: 無法在並行模式下修改之後讀/修改物件
Elapsed: 00:00:00.52
在另一個會話中執行select 語句。查詢結果是表中記錄為零,因為這個會話
看到的是insert append 以前的資料。
SQL> select count(*) from alltest02;
COUNT(*)
----------
0
二、使用insert append 方式插入資料的時候,將會使用HWM之上的空白塊,
如果要插入的表中HWM以下有很多沒有使用的空間的話,將會導致
儲存空間的浪費,所以說小資料量的插入沒有必要使用insert append 方式,
插入的表最好空的。有一種說法是如果要插入的表格是空白的,或者已經被
truncate 過,使用傳統的insert 和insert append 插入資料的方式hwm 是相同的
但是我個人認為是不相同的insert append 方式還是需要消耗更多的儲存空間。
因為在insert append 方式下hwm 推進的時候,總有一部分空間不能夠利用。
SQL> analyze table alltest01 estimate statistics;
Table analyzed.
Elapsed: 00:00:11.71
SQL> column segment_name format a20
SQL> select segment_name,blocks,bytes/1024 as "Size[KB]"
2 from user_segments
3 where segment_name = 'ALLTEST01';
SEGMENT_NAME BLOCKS Size[KB]
-------------------- ---------- ----------
ALLTEST01 48128 385024
Elapsed: 00:00:00.07
SQL> select empty_blocks
2 from user_tables
3 where table_name = 'ALLTEST01';
EMPTY_BLOCKS
------------
179
Elapsed: 00:00:00.12
SQL> analyze table alltest02 estimate statistics;
Table analyzed.
Elapsed: 00:00:09.36
SQL> select segment_name,blocks,bytes/1024 as "Size[KB]"
2 from user_segments
3 where segment_name = 'ALLTEST02';
SEGMENT_NAME BLOCKS Size[KB]
-------------------- ---------- ----------
ALLTEST02 49152 393216
Elapsed: 00:00:00.01
SQL> select empty_blocks
2 from user_tables
3 where table_name = 'ALLTEST02';
EMPTY_BLOCKS
------------
1012
Elapsed: 00:00:00.00
alltest01 的hwm = 48128 - 179 - 1 =47948
alltest02 的 hwm = 49152 - 1012 -1 = 48139
可見使用insert append 方式插入資料的表alltest02 需要更多的儲存空間。
三、如果插入的表中存在外來鍵約束,將會使用傳統的insert 方式。
下面先來構造一個外來鍵存在的情況。
SQL> create table emp_01 as select employee_id,first_name,last_name
2 from hr.employees;
Table created.
Elapsed: 00:00:00.12
SQL> alter table emp_01 add constraint emp_01_pk primary key (employee_id);
Table altered.
Elapsed: 00:00:00.59
SQL> create table emp_02 as select employee_id,department_id,salary
2 from hr.employees;
Table created.
Elapsed: 00:00:00.08
SQL> alter table emp_02 add constraint emp_02_fk foreign key (employee_id)
2 references emp_01 (employee_id);
Table altered.
Elapsed: 00:00:00.52
使用insert append 方式來插入資料,結果插入完成以後可以查詢,說明有外來鍵存在的
情況下insert append 方式將會自動轉化為傳統的insert 方式。如果在這種情況下確實
想要使用isnert append 方式,可以先disable constraint。
SQL> insert /*+append*/ into emp_02 select employee_id,department_id,salary
2 from hr.employees;
107 rows created.
Elapsed: 00:00:00.12
SQL> select count(*) from emp_02;
COUNT(*)
----------
214
Elapsed: 00:00:00.07
四、並不是所以的表都可以使用insert append 方式插入資料,比如不支援物件型別,
堆組織表等。
小結:使用insert append 雖然可以帶來插入資料效能上面的優勢,但是也存在諸多的
缺點和限制,需要綜合全面考慮。建議在插入大資料量和剛建立的表或者truncate 以後
的表中使用。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26110315/viewspace-723285/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 往表中插入大量的資料的方法(二)
- 迅速插入大量測試資料的方法
- 插入大量資料速度慢的解決方法:批量插入
- Firedac 在資料表中插入BLOB資料的方法
- Oracle 插入大量資料Oracle
- 【永春】往Sqlserver插入資料包錯SQLServer
- 關於PHP往mysql資料庫中批次插入資料例項教程PHPMySql資料庫
- YII2 一次性往資料庫插入多行資料資料庫
- MySQL大量資料插入各種方法效能分析與比較MySql
- 使用Mybatis批量插入大量資料的實踐MyBatis
- mysql從一張表中取出資料插入到另一張表MySql
- sql server 2000 一個表的資料插入到三個相關聯表中,一條一條的插入SQLServer
- 向表中插入大批量資料
- vage的delete大量資料方法delete
- mysql資料表插入資料後,獲取自增欄位值的方法MySql
- 前腳剛往資料庫插入資料,後腳就查不出來?資料庫
- laravel實現100w大量資料插入資料庫Laravel資料庫
- Android 資料庫 大量插入 事務開啟Android資料庫
- Oracle插入Blob資料的方法Oracle
- SAP HANA Cloud 學習教程之二: 如何往SAP BTP 上 HANA Cloud 資料庫表裡插入資料Cloud資料庫
- Mysql資料庫建立儲存過程實現往資料表中新增欄位的方法MySql資料庫儲存過程
- oracle 匿名儲存過程插入大量測試資料Oracle儲存過程
- zt_vage的delete大量資料方法delete
- oracle快速向表中插入記錄方法Oracle
- hive將查詢資料插入表中某欄位無資料Hive
- Python實現http介面請求資料後,往RabbitMQ裡面插入資料PythonHTTPMQ
- 一個表單中的資料新增到不同的資料表中
- MySQL(四) 資料表的插入、更新、刪除資料MySql
- 資料庫mysql插入異常 漢字無法插入方法,設定 建表的字元資料庫MySql字元
- 順序表有序插入資料
- 分庫分表插入資料
- 大表資料插入批量提交
- mongodb資料庫中插入資料MongoDB資料庫
- 小程式處理大量資料列表的方法
- 向資料庫中插入一條新的資料,並返回新增資料的ID資料庫
- SQL Server 2005中插入XML資料的三種方法SQLServerXML
- Oracle批次插入測試資料的方法Oracle
- Delete大量資料後,回收表空間delete