Oracle資料庫並行機制Parallel Execution

子知我非魚發表於2017-05-17


原文:http://blog.csdn.net/tianlesoftware/article/details/5854583


關於Oracle 的並行執行,Oracle 官方文件有詳細的說明:

                                Using Parallel Execution

http://download.oracle.com/docs/cd/E11882_01/server.112/e10837/parallel.htm#VLDBG010

This chapter covers tuning in a parallel execution environment and discusses the following topics:

·         Introduction to Parallel Execution

·         How Parallel Execution Works

·         Types of Parallelism

·         Initializing and Tuning Parameters for Parallel Execution

·         Tuning General Parameters for Parallel Execution

·         Monitoring Parallel Execution Performance

·         Miscellaneous Parallel Execution Tuning Tips

 

一.     並行(Parallel)和OLAP系統

並行的實現機制是: 首先,Oracle 會建立一個程式用於協調並行服務程式之間的資訊傳遞,這個協調程式將需要操作的資料集(比如表的資料塊)分割成很多部分,稱為並行處理單元,然後並行協調程式給每個並行程式分配一個資料單元。比如有四個並行服務程式,他們就會同時處理各自分配的單元,當一個並行服務程式處理完畢後,協調程式就會給它們分配另外的單元,如此反覆,直到表上的資料都處理完畢,最後協調程式負責將每個小的集合合併為一個大集合作為最終的執行結果,返回給使用者。

 

並行處理的機制實際上就是把一個要掃描的資料集分成很多小資料集,Oracle 會啟動幾個並行服務程式同時處理這些小資料集,最後將這些結果彙總,作為最終的處理結果返回給使用者。

 

這種資料並行處理方式在OLAP系統中非常有用,OLAP系統的表通常來說都是非常大,如果系統的CPU比較多,讓所有的CPU共同來處理這些資料,效果就會比序列執行要高的多。

 

然而對於OLTP系統,通常來講,並行並不合適,原因是OLTP系統上幾乎在所有的SQL操作中,資料訪問路勁基本上以索引訪問為主,並且返回結果集非常小,這樣的SQL 操作的處理速度一般非常快,不需要啟用並行。

 

 

二. 並行處理的機制

                當Oracle 資料庫啟動的時候,例項會根據初始化引數:

                                PARALLEL_MIN_SERVERS=n

                的值來預先分配n個並行服務程式,當一條SQL 被CBO判斷為需要並行執行時發出SQL的會話程式變成並行協助程式,它按照並行執行度的值來分配程式伺服器程式。

 

                首先協調程式會使用ORACLE 啟動時根據引數: parallel_min_servers=n的值啟動相應的並行服務程式,如果啟動的並行伺服器程式數不足以滿足並行度要求的並行服務程式數,則並行協調程式將額外啟動並行服務程式以提供更多的並行服務程式來滿足執行的需求。 然後星星協調程式將要處理的物件劃分成小資料片,分給並行服務程式處理;並行服務程式處理完畢後將結果傳送給並行協調程式,然後由並行協調程式將處理結果彙總併傳送給使用者。

 

                剛才講述的是一個並行處理的基本流程。 實際上,在一個並行執行的過程中,還存在著並行服務程式之間的通訊問題。

                在一個並行服務程式需要做兩件事情的時候,它會再啟用一個程式來配和當前的程式完成一個工作,比如這樣的一條SQL語句:

                Select * from employees order by last_name;

               

                假設employees表中last_name 列上沒有索引,並且並行度為4,此時並行協調程式會分配4個並行服務程式對錶employees進行全表掃描操作,因為需要對結果集進行排序,所以並行協調程式會額外啟用4個並行服務程式,用於處理4個程式傳送過來的資料,這新啟用的使用者處理傳遞過來資料的程式稱為父程式使用者傳出資料(最初的4個並行服務程式)成為子程式,這樣整個並行處理過程就啟用了8個並行服務程式。 其中每個單獨的並行服務程式的行為叫作並行的內部操作,而並行服務程式之間的資料交流叫做並行的互動操作。

                這也是有時我們發現並行服務程式數量是並行度的2倍,就是因為啟動了並行服務父程式操作的緣故。

 

 

三. 讀懂一個並行處理的執行計劃

 

CREATE TABLE emp2 AS SELECT * FROM employees;

ALTER TABLE emp2 PARALLEL 2;

 

EXPLAIN PLAN FOR

  SELECT SUM(salary) FROM emp2 GROUP BY department_id;

SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY());

 

--------------------------------------------------------------------------------------------------------

| Id  | Operation                | Name     | Rows  | Bytes | Cost (%CPU) |    TQ  |IN-OUT| PQ Distrib |

--------------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT         |          |   107 |  2782 |     3 (34)  |        |      |            |

|   1 |  PX COORDINATOR          |          |       |       |             |        |      |            |

|   2 |   PX SEND QC (RANDOM)    | :TQ10001 |   107 |  2782 |     3 (34)  |  Q1,01 | P->S | QC (RAND)  |

|   3 |    HASH GROUP BY         |          |   107 |  2782 |     3 (34)  |  Q1,01 | PCWP |            |

|   4 |     PX RECEIVE           |          |   107 |  2782 |     3 (34)  |  Q1,01 | PCWP |            |

|   5 |      PX SEND HASH        | :TQ10000 |   107 |  2782 |     3 (34)  |  Q1,00 | P->P | HASH       |

|   6 |       HASH GROUP BY      |          |   107 |  2782 |     3 (34)  |  Q1,00 | PCWP |            |

|   7 |        PX BLOCK ITERATOR |          |   107 |  2782 |     2 (0)   |  Q1,00 | PCWP |            |

|   8 |         TABLE ACCESS FULL| EMP2     |   107 |  2782 |     2 (0)   |  Q1,00 | PCWP |            |

--------------------------------------------------------------------------------------------------------

 

The table EMP2 is scanned in parallel by one set of slaves while the aggregation for the GROUP BY is done by the second set. The PX BLOCK ITERATOR row source represents the splitting up of the table EMP2 into pieces so as to divide the scan workload between the parallel scan slaves. The PX SEND and PX RECEIVE row sources represent the pipe that connects the two slave sets as rows flow up from the parallel scan, get repartitioned through the HASH table queue, and then read by and aggregated on the top slave set. The PX SEND QC row source represents the aggregated values being sent to the QC in random (RAND) order. The PX COORDINATOR row source represents the QC or Query Coordinator which controls and schedules the parallel plan appearing below it in the plan tree.

 

                上面這段文字是從Oracle 聯機文件上蕩下來的。

http://download.oracle.com/docs/cd/E11882_01/server.112/e10821/ex_plan.htm#PFGRF94687

 

通過執行計劃,我們來看一下它的執行步驟:

                (1)並行服務程式對EMP2表進行全表掃描。

                (2)並行服務程式以ITERATOR(迭代)方式訪問資料塊,也就是並行協調程式分給每個並行服務程式一個資料片,在這個資料片上,並行服務程式順序地訪問每個資料塊(Iterator),所有的並行服務程式將掃描的資料塊傳給另一組並行服務程式(父程式)用於做Hash Group操作。

                (3)並行服務父程式對子程式傳遞過來的資料做Hash Group操作。

                (4)並行服務程式(子程式)將處理完的資料傳送出去。

                (5)並行服務程式(父程式)接收到處理過的資料。

                (6)合併處理過的資料,按照隨即的順序發給並行協調程式(QC:Query Conordinator)。

                (7)並行協調程式將處理結果發給使用者。

 

當使用了並行執行,SQL的執行計劃中就會多出一列:in-out 該列幫助我們理解資料流的執行方法。 它的一些值的含義如下:

Parallel to SerialP->S: 表示一個並行操作傳送資料給一個序列操作,通常是並行incheng將資料傳送給並行排程程式。

Parallel to ParallelP->P):表示一個並行操作向另一個並行操作傳送資料,疆場是兩個從屬程式之間的資料交流。

Parallel Combined with parent(PCWP): 同一個從屬程式執行的並行操作,同時父操作也是並行的。

Parallel Combined with Child(PCWC): 同一個從屬程式執行的並行操作,子操作也是並行的。

Serial to ParallelS->P一個序列操作傳送資料給並行操作,如果select 部分是序列操作,就會出現這個情況。

 

 

四.並行執行等待事件

                在做並行執行方面的效能優化的時候,可能會遇到如下等待時間:

                                PX Deq Credit: send blkd

                這是一個有並行環境的資料庫中,從statspack 或者AWR中經常可以看到的等待事件。 在Oracle 9i 裡面, 這個等待時間被列入空閒等待。 關於等待時間參考:

                Oracle 常見的33個等待事件

                http://blog.csdn.net/tianlesoftware/archive/2010/08/12/5807800.aspx

 

一般來說空閒等待可以忽略它,但是實際上空閒等待也是需要關注的,因為一個空閒的等待,它反映的是另外的資源已經超負荷執行了。 基於這個原因,在Oracle 10g裡已經把PX Deq Credit: send blkd等待時間不在視為空閒等待,而是列入了Others 等待事件範圍。

 

PX Deq Credit: send blkd 等待事件的意思是: 當並行服務程式向並行協調程式QC(也可能是上一層的並行服務程式)傳送訊息時,同一時間只有一個並行服務程式可以向上層程式傳送訊息,這時候如果有其他的並行服務程式也要傳送訊息,就只能等待了。 知道獲得一個傳送訊息的信用資訊(Credit),這時候會觸發這個等待事件,這個等待事件的超時時間為2秒鐘。

 

                如果我們啟動了太多的並行程式,實際上系統資源(CPU)或者QC 無法即時處理並行服務傳送的資料,那麼等待將不可避免。 對於這種情況,我們就需要降低並行處理的並行度。

 

                當出現PX Deq Creditsend blkd等待的時間很長時,我們可以通過平均等待時間來判斷等待事件是不是下層的並行服務程式空閒造成的。該等待事件的超時時間是2秒,如果平均等待時間也差不多是2秒,就說明是下層的並行程式“無事所做”,處於空閒狀態。 如果和2秒的差距很大,就說明不是下層並行服務超時導致的空閒等待,而是並行服務之間的競爭導致的,因為這個平均等待事件非常短,說明並行服務程式在很短時間的等待之後就可以獲取資源來處理資料。

所以對於非下層的並行程式造成的等待,解決的方法就是降低每個並行執行的並行度,比如物件(表,索引)上預設的並行度或者查詢Hint 指定的並行度。

 

 

五. 並行執行的使用範圍

Oracle的並行技術在下面的場景中可以使用:

(1)       Parallel Query(並行查詢)

(2)       Parallel DDL(並行DDL操作,如建表,建索引等)

(3)       Parallel DML(並行DML操作,如insert,update,delete等)

 

5.1 並行查詢

                並行查詢可以在查詢語句,子查詢語句中使用,但是不可以使用在一個遠端引用的物件上(如DBLINK)。

 

                一個查詢能夠並行執行,需要滿足一下條件:

(1)       SQL語句中有Hint提示,比如Parallel 或者 Parallel_index.

(2)       SQL語句中引用的物件被設定了並行屬性。

(3)       多表關聯中,至少有一個表執行全表掃描(Full table scan)或者跨分割槽的Index range SCAN。

 

如: select  /*+parallel(t 4) * from t;

 

5.2 並行DDL 操作

 

5.2.1 表操作的並行執行

                以下表操作可以使用並行執行:

CREATE TABLE … AS SELECT

       ALTER TABLE … move partition

       Alter table … split partition

       Alter table … coalesce partition

 

DDL操作,我們可以通過trace 檔案來檢視它的執行過程。

 

示例:

 

檢視當前的trace 檔案:

/* Formatted on 2010/8/31 23:33:00 (QP5 v5.115.810.9015) */

SELECT      u_dump.VALUE

         || '/'

         || db_name.VALUE

         || '_ora_'

         || v$process.spid

         || NVL2 (v$process.traceid, '_' || v$process.traceid, NULL)

         || '.trc'

            "Trace File"

  FROM            v$parameter u_dump

               CROSS JOIN

                  v$parameter db_name

            CROSS JOIN

               v$process

         JOIN

            v$session

         ON v$process.addr = v$session.paddr

 WHERE       u_dump.name = 'user_dump_dest'

         AND db_name.name = 'db_name'

         AND v$session.audsid = SYS_CONTEXT ('userenv', 'sessionid');

 

Trace File

------------------------------------------------------------------------------

d:/app/administrator/diag/rdbms/orcl/orcl/trace/orcl_ora_5836.trc

d:/app/administrator/diag/rdbms/orcl/orcl/trace/orcl_ora_3048.trc

 

SQL> alter session set events '10046 trace name context forever,level 12';

會話已更改。

SQL> create table 懷寧 parallel 4 as select * from dba_objects;

表已建立。

SQL> alter session set events '10046 trace name context off' ;

會話已更改。

 

這裡用到了ORACLE的event 時間。 10046事件是用來跟蹤SQL語句的。開啟事件後,相關的資訊會寫道trace 檔案中,這也是之前我們檢視trace 檔名的原因。 關於event事件,參考我的blog

                Oracle 跟蹤事件 set event

                http://blog.csdn.net/tianlesoftware/archive/2009/12/13/4977827.aspx

 

有了trace檔案, 我們可以用tkprof 工具,來檢視trace 檔案的內容。 關於tkprof 工具介紹,參考blog:

                使用 Tkprof 分析 ORACLE 跟蹤檔案

                http://blog.csdn.net/tianlesoftware/archive/2010/05/29/5632003.aspx

 

 

進入trace 目錄,用tkprof命令生成txt 檔案,然後檢視txt 檔案。

d:/app/Administrator/diag/rdbms/orcl/orcl/trace>tkprof orcl_ora_3048.trc 安慶.txt sys=no

TKPROF: Release 11.2.0.1.0 - Development on 星期二 8月 31 23:45:25 2010

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

d:/app/Administrator/diag/rdbms/orcl/orcl/trace>

 

 

5.2.2 建立索引的並行執行

                建立索引時使用並行方式在系統資源充足的時候會使效能得到很大的提高,特別是在OLAP系統上對一些很大的表建立索引時更是如此。 以下的建立和更改索引的操作都可以使用並行:

                Create index

                Alter index … rebuild

                Alter index … rebuild partition

                Alter index … split partition

 

一個簡單的語法:create index t_ind on t(id) parallel 4;

 

監控這個過程和5.2.1 中表一樣,需要通過10046事件。 這裡就不多說了。

 

有關減少建立時間方法,參考blog:

                如何加快建 index 索引 的時間

                http://blog.csdn.net/tianlesoftware/archive/2010/07/11/5664019.aspx

 

 

總結:

使用並行方式,不論是建立表,修改表,建立索引,重建索引,他們的機制都是一樣的,那就是Oracle 給每個並行服務程式分配一塊空間,每個程式在自己的空間裡處理資料,最後將處理完畢的資料彙總,完成SQL的操作。

 

 

5.3 並行DML 操作

                Oracle 可以對DML操作使用並行執行,但是有很多限制。 如果我們要讓DML 操作使用並行執行,必須顯示地在會話裡執行如下命令:

                SQL> alter session enable parallel dml;

會話已更改。

 

                只有執行了這個操作,Oracle 才會對之後符合並行條件的DML操作並行執行,如果沒有這個設定,即使SQL中指定了並行執行,Oracle也會忽略它。

 

5.3.1 deleteupdatemerge 操作

                Oracle 對Delete,update,merge的操作限制在,只有操作的物件是分割槽表示,Oracle 才會啟動並行操作。原因在於,對於分割槽表,Oracle 會對每個分割槽啟用一個並行服務程式同時進行資料處理,這對於非分割槽表來說是沒有意義的。

 

5.3.2 Insert 的並行操作

                實際上只有對於insert into … select … 這樣的SQL語句啟用並行才有意義。 對於insert into .. values… 並行沒有意義,因為這條語句本身就是一個單條記錄的操作。

 

                Insert 並行常用的語法是:

                                Insert /*+parallel(t 2) */ into t select /*+parallel(t1 2) */ * from t1;

 

                這條SQL 語句中,可以讓兩個操作insert 和select 分別使用並行,這兩個並行是相互獨立,互補干涉的,也可以單獨使用其中的一個並行。

 

 

六. 並行執行的設定

 

6.1 並行相關的初始話引數

 

6.1.1 parallel_min_servers=n

                在初始化引數中設定了這個值,Oracle 在啟動的時候就會預先啟動N個並行服務程式,當SQL執行並行操作時,並行協調程式首先根據並行度的值,在當前已經啟動的並行服務中條用n個並行服務程式,當並行度大於n時,Oracle將啟動額外的並行服務程式以滿足並行度要求的並行服務程式數量。

 

6.1.2 parallel_max_servers=n

                如果並行度的值大於parallel_min_servers或者當前可用的並行服務程式不能滿足SQL的並行執行要求,Oracle將額外建立新的並行服務程式,當前例項總共啟動的並行服務程式不能超過這個引數的設定值。

 

6.1.3 parallel_adaptive_multi_user=true|false

                Oracle 10g R2下,並行執行預設是啟用的。 這個引數的預設值為true,它讓Oracle根據SQL執行時系統的負載情況,動態地調整SQL的並行度,以取得最好的SQL    執行效能。

 

6.1.4 parallel_min_percent

                這個引數指定並行執行時,申請並行服務程式的最小值,它是一個百分比,比如我們設定這個值為50. 當一個SQL需要申請20個並行程式時,如果當前並行服務程式不足,按照這個引數的要求,這個SQL比如申請到20*50%=10個並行服務程式,如果不能夠申請到這個數量的並行服務,SQL 將報出一個ORA-12827的錯誤。

                當這個值設為Null時,表示所有的SQL在做並行執行時,至少要獲得兩個並行服務程式。

 

 

6.2 並行度的設定

                並行度可以通過以下三種方式來設定:

(1)使用Hint 指定並行度。

(2)使用alter session force parallel 設定並行度。

(3)使用SQL中引用的表或者索引上設定的並行度,原則上Oracle 使用這些物件中並行度最高的那個值作為當前執行的並行度。

 

 

示例:

                SQL>Select /*+parallel(t 4) */ count(*) from t;

                SQL>Alter table t parallel 4;

                SQL>Alter session force parallel query parallel 4;

 

Oracle 預設並行度計算方式:

(1)Oracle 根據CPU的個數,RAC例項的個數以及引數parallel_threads_per_cpu的值,計算出一個並行度。

(2)對於並行訪問分割槽操作,取需要訪問的分割槽數為並行度。

 

並行度的優先順序別從高到低:

                Hint->alter session force parallel->表,索引上的設定-> 系統引數

 

 

實際上,並行只有才系統資源比較充足的情況下,才會取得很好的效能,如果系統負擔很重,不恰當的設定並行,反而會使效能大幅下降。

 

 

七. 直接載入

                在執行資料插入或者資料載入的時候,可以通過append hint的方式進行資料的直接載入。

 

insert SQL中使用APPEND,如:

                                Insert /*+append */ into t select * from t1;

               

還可以在SQL*LOADER裡面使用直接載入:

       Sqlldr userid=user/pwd control=load.ctl direct=true

 

Oracle 執行直接載入時,資料直接追加到資料段的最後,不需要花費時間在段中需找空間,資料不經過data buffer直接寫到資料檔案中,效率要比傳統的載入方式高。

 

示例:

SQL> create table t as select * from user_tables;

表已建立。

SQL> select segment_name,extent_id,bytes from user_extents where segment_name='T';

SEGMENT_NA  EXTENT_ID      BYTES

---------- ---------- ----------

T                   0      65536

T                   1      65536

T                   2      65536

T                   3      65536

T                   4      65536

 

這裡我們建立了一張表,分配了5extents

 

SQL> delete from t;

已刪除979行。

SQL> select segment_name,extent_id,bytes from user_extents where segment_name='T';

SEGMENT_NA  EXTENT_ID      BYTES

---------- ---------- ----------

T                   0      65536

T                   1      65536

T                   2      65536

T                   3      65536

T                   4      65536

 

這裡刪除了表裡的資料,但是查詢,依然佔據5extents。因為delete不會收縮表空間,不能降低高水位。

 

SQL> insert into t select * from user_tables;

已建立980行。

SQL> commit;

提交完成。

 

SQL> select segment_name,extent_id,bytes from user_extents where segment_name='T';

SEGMENT_NA  EXTENT_ID      BYTES

---------- ---------- ----------

T                   0      65536

T                   1      65536

T                   2      65536

T                   3      65536

T                   4      65536

 

用傳統方式插入,資料被分配到已有的空閒空間裡。

 

 

SQL> delete from t;

已刪除980行。

SQL> commit;

提交完成。

SQL> select segment_name,extent_id,bytes from user_extents where segment_name='T';

SEGMENT_NA  EXTENT_ID      BYTES

---------- ---------- ----------

T                   0      65536

T                   1      65536

T                   2      65536

T                   3      65536

T                   4      65536

 

刪除資料,用append直接插入看一下。

 

SQL> insert /*+append */ into t select * from user_tables;

已建立980行。

SQL> commit;

提交完成。

SQL> select segment_name,extent_id,bytes from user_extents where segment_name='T';

SEGMENT_NA  EXTENT_ID      BYTES

---------- ---------- ----------

T                   0      65536

T                   1      65536

T                   2      65536

T                   3      65536

T                   4      65536

T                   5      65536

T                   6      65536

T                   7      65536

T                   8      65536

T                   9      65536

已選擇10行。

 

從結果可以看出,直接載入方式時,雖然表中有很多空的資料塊,Oracle 仍然會額外的分配4個extent用於直接載入資料。

                直接載入的資料放在表的高水位(High water Mark:hwm)以上,當直接載入完成後,Oracle 將表的高水位線移到新加入的資料之後,這樣新的資料就可以被使用者使用了。

 

Oracle 高水位(HWM)

http://blog.csdn.net/tianlesoftware/archive/2009/10/22/4707900.aspx

 

 

7.1 直接載入和REDO

                直接載入在logging模式下,與傳統載入方式產生的redo 日誌差別不大,因為當一個表有logging屬性時,即使使用直接載入,所有改變的資料依然要產生redo,實際上是所有修改的資料塊全部記錄redo,以便於以後的恢復,這時候直接載入並沒有太大的優勢。

 

                直接載入最常見的是和nologging一起使用,這時候可以有效地減少redo 的生成量。 注意的是,在這種情況下,直接載入的資料塊是不產生redo的,只有一些其他改變的資料產生一些redo,比如表空間分配需要修改字典表或者修改段頭資料塊,這些修改會產生少量的redo。

 

                實際上,對於nologging 方式的直接載入,undo 的資料量也產生的很少,因為直接載入的資料並不會在回滾段中記錄,這些記錄位於高水位之上,在事務提交之前,對於其他使用者來說是不可見的,所以不需要產生undo,事務提交時,Oracle 將表的高水位線移到新的資料之後,如果事務回滾,只需要保持高水位線不動即可,就好像什麼都沒有發生一樣。

 

                注意,由於在nologging模式下,redo 不記錄資料修改的資訊,所以直接載入完後,需要立即進行相關的備份操作,因為這些資料沒有記錄在歸檔日誌中,一旦資料損壞,只能用備份來恢復,而不能使用歸檔恢復。

 

Logging模式下示例:

SQL> set autot trace stat;

SQL> insert /*+append */ into t select * from user_tables;

已建立980行。

統計資訊

----------------------------------------------------------

        132  recursive calls

         87  db block gets

       8967  consistent gets

          0  physical reads

     286572  redo size

        911  bytes sent via SQL*Net to client

       1017  bytes received via SQL*Net from client

          4  SQL*Net roundtrips to/from client

          2  sorts (memory)

          0  sorts (disk)

        980  rows processed

SQL> rollback;

回退已完成。

SQL> insert into t select * from user_tables;

已建立980行。

統計資訊

----------------------------------------------------------

          0  recursive calls

        144  db block gets

       9027  consistent gets

          0  physical reads

     267448  redo size

        927  bytes sent via SQL*Net to client

       1004  bytes received via SQL*Net from client

          4  SQL*Net roundtrips to/from client

          2  sorts (memory)

          0  sorts (disk)

        980  rows processed

 

Nologging模式下示例:

SQL> alter table t nologging;

表已更改。

SQL> insert into t select * from user_tables;

已建立980行。

統計資訊

----------------------------------------------------------

        239  recursive calls

        132  db block gets

       9061  consistent gets

          0  physical reads

     262896  redo size

        927  bytes sent via SQL*Net to client

       1004  bytes received via SQL*Net from client

          4  SQL*Net roundtrips to/from client

          7  sorts (memory)

          0  sorts (disk)

        980  rows processed

SQL> rollback;

回退已完成。

SQL> insert /*+append */ into t select * from user_tables;

已建立980行。

統計資訊

----------------------------------------------------------

          8  recursive calls

         40  db block gets

       8938  consistent gets

          0  physical reads

        340  redo size  -- redo 減少很多

        911  bytes sent via SQL*Net to client

       1017  bytes received via SQL*Net from client

          4  SQL*Net roundtrips to/from client

          2  sorts (memory)

          0  sorts (disk)

        980  rows processed

 

這部分內容也可參考Blog:

                Oracle DML NOLOGGING

http://blog.csdn.net/tianlesoftware/archive/2010/07/11/5701596.aspx

 

 

7.2 直接載入和索引

                如果直接載入的表上有索引,Oracle不會像載入資料的方式那樣來處理索引的資料,但是它同樣需要維護一個索引,這個成本很高,同時會生成很多的redo。

                所以當使用直接載入時,通常是針對一些資料量非常大的表。如果這些表存在索引,將會帶來很大的效能影響,這時可以考慮先將索引disable或者drop掉,等載入資料後,之後在重新建立索引。

 

nologging示例:

 

SQL> insert /*+append */ into t select * from user_tables;

已建立980行。

 

統計資訊

----------------------------------------------------------

          0  recursive calls

         40  db block gets

       8936  consistent gets

          0  physical reads

        384  redo size

        911  bytes sent via SQL*Net to client

       1017  bytes received via SQL*Net from client

          4  SQL*Net roundtrips to/from client

          2  sorts (memory)

          0  sorts (disk)

        980  rows processed

 

SQL> rollback;

回退已完成。

SQL> create index t_ind on t(table_name);

索引已建立。

SQL> insert /*+append */ into t select * from user_tables;

已建立980行。

 

統計資訊

----------------------------------------------------------

         40  recursive calls

        170  db block gets

       8955  consistent gets

          4  physical reads

     149424  redo size

        911  bytes sent via SQL*Net to client

       1017  bytes received via SQL*Net from client

          4  SQL*Net roundtrips to/from client

          3  sorts (memory)

          0  sorts (disk)

        980  rows processed

SQL> rollback;

回退已完成。

SQL> insert  into t select * from user_tables;

已建立980行。

 

統計資訊

----------------------------------------------------------

          8  recursive calls

        828  db block gets

       9037  consistent gets

          0  physical reads

     382832  redo size

        927  bytes sent via SQL*Net to client

       1005  bytes received via SQL*Net from client

          4  SQL*Net roundtrips to/from client

          2  sorts (memory)

          0  sorts (disk)

        980  rows processed

SQL> rollback;

回退已完成。

 

 

7.3 直接載入和並行

                直接載入可以和並行執行一同使用,這樣可以並行地向表中插入資料。 如:

               

SQL>alter session enable parallel dml;  -- 這裡必須顯示的申明

SQL>insert /*+append parallel(t,2) */ into t select * from t1;

SQL>insert /*+append */ into t select * from t1;

 

注:在對insert 使用並行時,Oracle自動使用直接載入的方式進行資料載入,所以在這種情況下append是可以省略的。

 

                當使用並行載入時,Oracle 會按照並行度啟動相應數量的並行服務程式,像序列執行的直接載入的方式一樣,每個並行服務程式都單獨分配額外的空間用於載入資料,實際上Oracle 為每個並行服務程式分配了一個臨時段,每個並行服務程式將資料首先載入到各自的臨時段上,當所有的並行程式執行完畢後,將各自的資料塊合併到一起,放到高水位之後,如果事務提交,則將高水位移到新載入的資料之後。

 

 

7.4 直接載入和SQL*LOADER

                在SQL*LOADER中也可以使用直接載入,它比傳統方式效率更高,因為它繞開了SQL的解析和資料緩衝區,直接將資料載入到資料檔案,這對OLAP或者資料倉儲系統非常有用。

 

指定載入:

                Sqlldr userid=user/pwd control=control.ctl direct=true

 

指定並行和載入:

                Sqlldr userid=user/pwd control=control.ctl direct=true parallel=true

 

 

SQL*LOADER直接載入對索引的影響:

(1)索引為非約束性,直接載入可以在載入完畢後維護索引的完整性。

(2)索引為約束性索引,比如主鍵,直接載入仍然會將資料載入入庫,但是會將索引置為unusable.

 

 

如果使用SQL*LOADER的並行直接載入選項,並且表上有索引,將導致載入失敗,這是我們可以在sqlloader中指定skip_index_maintenance=true, 來允許載入完成,但是索引狀態會變成unusable,需要手工rebuild.

 

關於SQL*LOADER的更多內容,參考blog:

                Oracle SQL Loader

                http://blog.csdn.net/tianlesoftware/archive/2009/10/16/4674063.aspx

 

 

 

 

整理自《讓Oracle 跑的更快》

------------------------------------------------------------------------------

Blog: http://blog.csdn.NET/tianlesoftware

網上資源: http://tianlesoftware.download.csdn.Net

相關視訊:http://blog.csdn.net/tianlesoftware/archive/2009/11/27/4886500.aspx

DBA1 群:62697716(滿); DBA2 群:62697977(滿)

DBA3 群:63306533;     聊天 群:40132017


相關文章