APPEND (direct path) - redo size
I am sure, I might be missing something obvious. I am under the impression that DIRECT PATH loads (such as inserts with APPEND hint )would generate less redo. But, not sure why I am seeing this...
Regular Insert (Not direct path):
====================
SQL> insert into c2 Select * from dba_objects where rownum < 301;
300 rows created.
Statistics
10 recursive calls
74 db block gets
353 consistent gets
1 physical reads
*31044 redo size*
821 bytes sent via SQL*Net to client
752 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
300 rows processed
Direct Path Insert
===========
SQL> insert /*+ APPEND */ into c2 Select * from dba_objects where rownum < 301;
300 rows created.
Statistics
8 recursive calls
13 db block gets
346 consistent gets
1 physical reads
*39048 redo size*
809 bytes sent via SQL*Net to client
770 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
300 rows processed
Not sure, why am I seeing more redo being generated with DIRECT PATH .... either I am missing something obvious or got the DIRECT PATH load completely wrong...would really appreciate any help with this.
Hello,
Check out this thread:
[http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:3224814814761]
Additionally, if you were to switch off logging at the table level, before the INSERT, you should see a (further) reduction in redo:
ALTER TABLE your_table NOLOGGING;
Similar Messages
-
Insert /*+ Append */ and direct-path INSERT
Hi Guys
Does insert /*+ Append */ into hint cause Oracle 10G to use direct-path INSERT?
and if insert /*+ Append */ into hint does cause Oracle to use direct-path INSERT, does insert /*+ Append */ is subject to the same restrictions as direct-path such as "The target table cannot have any triggers or referential integrity constraints defined on it."
ThanksDear,
Here below a simple example showing the effet of existing trigger on the append hint
mhouri@mhouri> select * from v$version where rownum=1;
BANNER
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
mhouri@mhouri> create table b as select * from all_objects where 1 = 2;
Table créée.
mhouri@mhouri> insert /*+ append */ into b
2 select * from all_objects;
70986 ligne(s) créée(s).
mhouri@mhouri> select * from b;
select * from b
ERREUR à la ligne 1 :
ORA-12838: impossible de lire/modifier un objet après modification en parallèle
mhouri@mhouri> rollback;
Annulation (rollback) effectuée.The direct path took place as far as I can't select from the table before I commit
mhouri@mhouri> create trigger b_trg before insert on b
2 for each row
3 begin
4 null;
5 end;
6 /
Déclencheur créé.
mhouri@mhouri> insert /*+ append */ into b
2 select * from all_objects;
70987 ligne(s) créée(s).
424 ligne(s) sélectionnée(s).
mhouri@mhouri> select count(1) from b;
COUNT(1)
70987 While in the presence of this trigger on the table, the append hint has been silently ignored by Oracle. The fact that I can select from the table immediately afte the insert has finished is the indication that the table has not be inserted using direct path load
Best Regards
Mohamed Houri -
Oracle direct path read IO size
Hello!
I am confused a little with IO size. I am running 11.2.0.3 on Oracle Linux x64 6.2. Block_size=8K, MULTIBOCK_READ_COUNT=128
Database is Single Instance and is using ASM grid. ASM AU =1M
As a test I am running a simple query against large table with 1.5Bln rows.
select /*+ PARALLEL (STOCK_DAY 10) */ count(*) from stock_day where cstast='NA'
STAT #140582923121480 id=1 cnt=0 pid=0 pos=1 obj=0 op='SORT AGGREGATE (cr=0 pr=0 pw=0 time=0 us)'
STAT #140582923121480 id=2 cnt=0 pid=1 pos=1 obj=0 op='PX COORDINATOR (cr=0 pr=0 pw=0 time=0 us)'
STAT #140582923121480 id=3 cnt=0 pid=2 pos=1 obj=0 op='PX SEND QC (RANDOM) :TQ10000 (cr=0 pr=0 pw=0 time=0 us)'
STAT #140582923121480 id=4 cnt=0 pid=3 pos=1 obj=0 op='SORT AGGREGATE (cr=0 pr=0 pw=0 time=27 us)'
STAT #140582923121480 id=5 cnt=2301843 pid=4 pos=1 obj=0 op='PX PARTITION LIST ALL PARTITION: 1 762 (cr=68020 pr=68393 pw=0 time=29346414 us cost=303766 size=669864369 card=223288123)'
STAT #140582923121480 id=6 cnt=2301843 pid=5 pos=1 obj=1464816 op='TABLE ACCESS FULL STOCK_DAY PARTITION: 1 762 (cr=68020 pr=68393 pw=0 time=24376609 us cost=303766 size=669864369 card=223288123)'
when I am trying to measure disk io statistics with iostat it shows that Oracle is issuing a 32K direct path read requests to ASM LUNs. Why? Why not 1M?
Thank you in advance!
Regards,
Kirill
Edited by: Kirill.Boyko on Jan 31, 2013 12:53 PMThis is a kind of histogram for one parallel session wait events
select session_state,event,p3,count(1) from V$active_session_history ash where ash.session_id=1904 and ash.session_serial#=24381
group by session_state,event,p3
order by session_state,event,p3
session
state event P3 COUNT
ON CPU 5 1
ON CPU 9 8
ON CPU 15 1
ON CPU 115 10
ON CPU 123 1
ON CPU 124 2
ON CPU 126 23
ON CPU 128 77
ON CPU 512 1
WAITING direct path read 5 2
WAITING direct path read 8 2
WAITING direct path read 9 7
WAITING direct path read 15 3
WAITING direct path read 67 1
WAITING direct path read 101 1
WAITING direct path read 115 18
WAITING direct path read 124 5
WAITING direct path read 126 35
WAITING direct path read 127 1
WAITING direct path read 128 97
in fact as you can see almost all direct path reads are done with io size > 900K. Total size of information read by process~160M
strace shows a lot of calls to read function. If we divide 160M/78000 reads we will get about 2K per request which is strange
% time seconds usecs/call calls errors syscall
98.61 0.212144 3 78356 read
0.93 0.002000 32 63 58 semtimedop
0.29 0.000624 208 3 munmap
0.12 0.000263 0 7407 gettimeofday
according to iostat we see that we are reading from each LUN with requests of 32K
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util
xvda 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
xvdb 4.00 0.00 2946.00 1.00 92.01 0.00 63.94 90.60 30.93 0.33 96.00
xvde 1.00 0.00 2466.00 0.00 77.00 0.00 63.95 49.84 20.64 0.33 80.90
xvdf 5.00 0.00 2694.00 1.00 84.15 0.01 63.95 69.68 25.37 0.32 87.20
xvdg 2.00 0.00 2798.00 0.00 87.41 0.00 63.98 91.95 33.81 0.35 97.40
xvdj 3.00 0.00 2676.00 1.00 83.45 0.03 63.87 38.83 14.72 0.31 82.10
xvdk 4.00 0.00 2951.00 0.00 92.14 0.00 63.95 100.21 32.42 0.31 91.00
xvdl 3.00 0.00 2735.00 1.00 85.45 0.03 63.98 56.04 21.14 0.32 86.50
Why linux is splitting Oracle requests and how to avoid that?
Regards,
Kirill -
Huge long time direct path read temp, but pga size is enough, one block p3
Hi Gurus,
Can you please kindly provide some points on my below questions. thanks
my env
select * from v$version;
BANNER
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
OS: Linux 4 2.6.39-100.5.1.el5uek
session operation: update a partition which have 4 partitions and total 16G
session trace info:
the session keep at active status and waiting for below wait event for more than 70 hours, and os iostats and cpu are almost idle on most time.
WAIT #8: nam='direct path read temp' ela= 7615 file number=202 first dba=105072 block cnt=1 obj#=104719 tim=1344850223569499
WAIT #8: nam='direct path read temp' ela= 5989 file number=202 first dba=85264 block cnt=1 obj#=104719 tim=1344850392833257
WAIT #8: nam='direct path read temp' ela= 319 file number=202 first dba=85248 block cnt=1 obj#=104719 tim=1344850399563184
WAIT #8: nam='direct path read temp' ela= 358 file number=202 first dba=85232 block cnt=1 obj#=104719 tim=1344850406016899
WAIT #8: nam='direct path read temp' ela= 349 file number=202 first dba=85216 block cnt=1 obj#=104719 tim=1344850413023792
WAIT #8: nam='direct path read temp' ela= 7975 file number=202 first dba=85200 block cnt=1 obj#=104719 tim=1344850419495645
WAIT #8: nam='direct path read temp' ela= 331 file number=202 first dba=85184 block cnt=1 obj#=104719 tim=1344850426233450
WAIT #8: nam='direct path read temp' ela= 2641 file number=202 first dba=82880 block cnt=1 obj#=104719 tim=1344850432699800
pgastat:
NAME VALUE/1024/1024 UNIT
aggregate PGA target parameter 18432 bytes
aggregate PGA auto target 16523.1475 bytes
global memory bound 1024 bytes
total PGA inuse 75.7246094 bytes
total PGA allocated 162.411133 bytes
maximum PGA allocated 514.130859 bytes
total freeable PGA memory 64.625 bytes
PGA memory freed back to OS 40425.1875 bytes
total PGA used for auto workareas 2.75195313 bytes
maximum PGA used for auto workareas 270.407227 bytes
total PGA used for manual workareas 0 bytes
NAME VALUE/1024/1024 UNIT
maximum PGA used for manual workareas 24.5429688 bytes
bytes processed 110558.951 bytes
extra bytes read/written 15021.2559 bytes
Most operation in PGA via query on V$SQL_WORKAREA_ACTIVE
IDX maintainenance (sort)
My questions:
1. why 'direct path read temp' just read one block every time, my understanding is this event can read one block and multiple blocks at one read call, why it keep read one block in my session?
2. my pga size is big enough, why this operation can not be treated with in PGA memory, instead of read block from disk into temp tablespace?
Thanks for you inputs.
Roy951241 wrote:
since the session(which was from hard code application) is completed.First of all, you showed wait events from sql trace in the first post. Is the tracing was disabled in the latest execution?
>
I just generated the AWR for that period, as get long elapsed time SQL as following
Elapsed Time (s) Executions Elapsed Time per Exec (s) %Total %CPU %IO SQL Id
3,075.35 0 85.10 91.03 8.68 duhz2wtduz709
524.11 1 524.11 14.50 99.29 0.30 3cpa9fxny9j35
so I get execution plan as below for these two SQL,
select * from table(dbms_xplan.display_awr('&v_sql_id')); duhz2wtduz709
PLAN_TABLE_OUTPUT
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | UPDATE STATEMENT | | | | 4 (100)| |
| 1 | UPDATE | WORK_PAY_LINE | | | | |
| 2 | INDEX RANGE SCAN| WORK_PAY_LINE | 1 | 37 | 3 (0)| 00:00:01 |
Note
- automatic DOP: Computed Degree of Parallelism is 1 because of parallel thresholdI am not sure the why elapsed time in AWR is different with time in execution plan. Column "Time" in an execution plan is estimated time. In this execution plan Oracle expects to get 1 row, estimated time is 1 sec.
So, you need to check why estimated cardinality is such low, check statistics on the table WORK_PAY_LINE.
You update 10Gb from 16Gb table via Index Range Scan, it looks inefficient here by two reasons:
1. when a table updated via Index Range Scan optimized index maintenance is used. As a result some amount (significant in your case) of workareas is required. Required size depends on size and number of updated indexes and "global memory bound", 1Gb in your case.
2. if required table buffers will not be found in the cache it will be read from disk by single block reads. If you would use Full Table Scan then buffers for update most likely will be found in the cache because before it read by multiblock reads during Full Table Scan.
Figures from your AWR indicate, that only ~ 9% the session waited for I/O and 91% it worked and used CPU
Elapsed Time (s) Executions Elapsed Time per Exec (s) %Total %CPU %IO SQL Id
3,075.35 0 85.10 91.03 8.68 duhz2wtduz709 This amount of CPU time partially required for UPDATE 10Gb of data, partially for sorting during optimized index maintenance.
I would propose to use Table Full Scan here.
Also you can play around and create fake trigger on update, it will make impossible to use optimized index maintenance, usual index maintenance will be used. As a result you can check the same update with the same execution plan (with Index Range Scan) but without optimized index maintenance and "direct path .. temp" wait events.
Alexander Anokhin
http://alexanderanokhin.wordpress.com/ -
Direct Path Insert into temporary table
Hi,
I made the following experiment (temp_idtable is a temp table with a single column id, V_PstSigLink is a complex View):
14:24:28 SQL> insert into temp_idtable select id from V_PstSigLink;
17084 Zeilen wurden erstellt. (in english: rows inswerted)
Statistiken
24 recursive calls
52718 db block gets
38305 consistent gets
16 physical reads
4860544 redo size
629 bytes sent via SQL*Net to client
553 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
4 sorts (memory)
0 sorts (disk)
17084 rows processed
14:24:41 SQL> commit;
Transaktion mit COMMIT abgeschlossen.
14:25:29 SQL> insert /*+ APPEND*/into temp_idtable select id from V_PstSigLink;
17084 Zeilen wurden erstellt. (in english: rows inswerted)
Statistiken
1778 recursive calls
775 db block gets
38847 consistent gets
40 physical reads
427408 redo size
613 bytes sent via SQL*Net to client
565 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
27 sorts (memory)
0 sorts (disk)
17084 rows processed
As you can see, with /*+ APPEND*/ there will be much less REDO generated.
How can it be?
1. /*+ APPEND*/ only doesn't mean that there shouldn't be REDO generated, does it? For that one has to declare the table with NOLOGGING.
2. In the doc there is a statement that for temp. tables there is no REDO log generated, just UNDO (and REDO only for UNDO).
Where is the difference coming from?
If I use Direct Path (APPEND) for a temp table, where will be the table populated - in the Buufer Cache or directly in a temporary segment on the disk?
BalazsHi John,
I'm a little confused about your statement " Oracle does not cache data blocks until they are read from a table.". I wanted to make a little experiment with KEEP Buffer Cache to see weather I can 'pin' the content of a temp table. But before getting to pin I realized an interesting behavior. Please see this sqlplus log:
SQL> create global temporary table temp_ins(id NUMBER);
Table created.
SQL> insert into temp_ins values (1);
1 row created.
SQL> insert into temp_ins values (2);
1 row created.
SQL> insert into temp_ins values (3);
1 row created.
SQL> set autotrace on explain statistics;
SQL> select * from temp_ins;
ID
1
2
3
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (FULL) OF 'TEMP_INS'
Statistics
0 recursive calls
0 db block gets
4 consistent gets
0 physical reads
0 redo size
416 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
3 rows processed
SQL>
I realized exectly the opposit of your statement! Oracle apparently cached the content of the temp table before it read from it!! Could you please explain why? Now I'm going to try it with a normal table...
Balazs -
제품 : ORACLE SERVER
작성날짜 : 1998-11-27
매우 많은 양의 데이타를 빠른 시간 내에 load하고자하는 경우 direct path load를
사용할 수 있다. 여기에서 이러한 direct path load의 자세한 개념 및 사용방법,
사용 시 고려해야 할 점 등을 설명한다.
1. conventional path load
일반적인 sql*loader를 이용한 방법은 존재하는 table에 datafile 내의 data를
SQL의 INSERT command를 이용하여 insert시킨다. 이렇게 SQL command를
이용하기 때문에 각각의 데이타를 위한 insert command가 생성되어 parsing되는
과정이 필요하며, 먼저 bind array buffer (data block buffer) 내에 insert되는
데이타를 입력시킨 후 이것을 disk에 write하게 된다.
conventional path load를 사용하여야 하는 경우는 다음과 같다.
--- load 중에 table을 index를 이용하여 access하여야 하는 경우
direct load중에는 index가 'direct load state'가 되어 사용이 불가능하다.
--- load 중에 index를 사용하지 않고 table을 update나 insert등을 수행해야
하는 경우
direct load 중에는 table에 exclusive write(X) lock을 건다.
--- SQL*NET을 통해 load를 수행해야 하는 경우
--- clustered table에 load하여야 하는 경우
--- index가 걸려 있는 큰 table에 적은 수의 데이타를 load하고자 할 때
--- referential이나 check integrity가 정의되어 있는 큰 table에
load하고자 할 때
--- data field에 SQL function을 사용하여 load하고자 할 때
2. direct path load의 수행 원리
Direct Path Loads는 다음과 같은 특징들로 인하여 매우 많은 양의 데이타를
빠른 시간에 load하고자 할 때 이용하는 것이 바람직하다.
(1) SQL INSERT 문장을 generate하여 수행하지 않는다.
(2) memory 내의 bind array buffer를 이용하지 않고 database block의
format과 같은 data
block을 memory에 만들어 데이타를 넣은 후 그대로 disk에 write한다.
memory 내의 block buffer와 disk의 block은 그 format이 다르다.
(3) load 시작 시에 table에 lock을 걸고 load가 끝나면 release시킨다.
(4) table의 HWM (High Water Mark) 윗 부분의 block에 data를 load한다.
HWM는 table에 data가 insert됨에 따라 계속 늘어나고 truncate 외에는
줄어들게 하지 못한다.
그러므로, 항상 완전히 빈 새로운 block을 할당받아 data를 입력시키게 된다.
(5) instance failure가 발생하여도 redo log file을 필요로 하지 않는다.
(6) UNDO information을 발생시키지 않는다.
즉 rollback segment를 사용하지 않는다.
(7) OS에서 asynchronous I/O가 가능하다면, 복수개의 buffer에 의해서 동시에
data를 읽어서 buffer에 write하면서 buffer에서 disk로 write할 수 있다.
(8) parallel option을 이용하면 더욱 성능을 향상시킬 수 있다.
3. direct path load의 사용방법 및 options
direct path load를 사용하기 위한 view들은 다음 script에 포함어 있으며,
미리 sys user로 수행되어야 한다. 단 이 script는 catalog.sql에 포함되어 있어,
db 구성 시에 이미 수행되어진다.
@$ORACLE_HOME/rdbms/admin/catldr.sql
direct path load를 사용하기 위해서는 일반적인 sqlload 명령문에 DIRECT=TRUE를
포함시키기만 하면 된다. 다음과 같이 기술하면 된다.
sqlload username/password control=loadtest.ctl direct=true
이 direct path load를 사용 시에 고려할 만한 추가적인 option 및 control file
내에 기술 가능한 clause들을 살펴본다.
(1) ROWS = n
conventional path load에서 rows는 default가 64이며, rows에 지정된 갯수
만큼의 row가 load되면 commit이 발생한다. 이와 비슷하게 direct load
path에서는 rows option을 이용하여 data save를 이루며, data save가 발생하면
data는 기존 table에 포함되어 입력된 data를 잃지 않게 된다.
단 이 때 direct path load는 모든 data가 load된 다음에야 index가
구성되므로 data save가 발생하여도 index는 여전히 direct load state로
사용하지 못하게 된다.
direct path load에서 이 rows의 default값은 unlimited이며, 지정된 값이
database block을 채우지 못하면 block을 완전히 채우는 값으로 올림하여,
partial block이 생성되지 않도록 한다.
(2) PIECED clause
control file내에 column_spec datatype_spec PIECED 순으로 기술하는
것으로서 direct path load에만 유효하다. LONG type과 같이 하나의 data가
maximum buffer size보다 큰 경우 하나의 data를 여러번에 나누어 load하는
것이다. 이 option은 table의 맨 마지막 field
하나에만 적용가능하며, index column인 경우에는 사용할 수 없다.
그리고 load도중 data에 문제가 있는 경우 현재 load되는 data의 잘린 부분만
bad file에 기록되게 된다. 왜냐하면 이전 조각은 이미 datafile에 기록되어
buffer에는 남아있지 않기 때문이다.
(3) READBUFFERS = n (default is 4)
만약 매우 큰 data가 마지막 field가 아니거나 index의 한 부분인 경우
PIECED option을 사용할 수 없다. 이러한 경우 buffer size를 증가시켜야
하는데 이것은 readbuffers option을 이용하면 된다. default buffer갯수는
4개이며, 만약 data load중 ORA-2374(No more slots for read buffer
queue) message가 나타나면, buffer갯수가 부족한 것이므로 늘려주도록 한다.
단 일반적으로는 이 option을 이용하여 값을 늘린다하더라도 system
overhead만 증가하고 performance의 향상은 기대하기 어렵다.
4. direct path load에서의 index 처리
direct path load에서 인덱스를 생성하는 절차는 다음과 같다.
(1) data가 table에 load된다.
(2) load된 data의 key 부분이 temporary segment에 copy되어 sort된다.
(3) 기존에 존재하던 index와 (2)에 의해서 정렬된 key가 merge된다.
(4) (3)에 의해서 새로운 index가 만들어진다.
기존에 존재하던 index와 temporary segment, 그리고 새로 만들어지는 index가
merge가 완전히 끝날 때까지 모두 존재한다.
(5) old index와 temporary segment는 지워진다.
이와 같은 절차에 반해 conventional path load는 data가 insert될 때마다 한
row 씩 index에 첨가된다. 그러므로 temporary storage space는 필요하지 않지만
direct path load에 비해 index 생성 시간도 느리고, index tree의 balancing도
떨어지게 된다.
index생성 시 필요한 temporary space는 다음과 같은 공식에 의해 예측되어질 수
있다.
1.3 * key_storage
key_storage = (number_of_rows) * (10 + sum_of_column_sizes +
number_of_columns)
여기에서 1.3은 평균적으로 sort 시에 추가적으로 필요한 space를 위한 값이며,
전체 data가 완전히 순서가 거꾸로 된 경우에는 2, 전체가 미리 정렬된 경우라면
1을 적용하면 된다.
--- SINGLEROW clause
이와 같이 direct path load에서 index 생성 시 space를 많이 차지하는 문제점
때문에 resource가 부족한 경우에는 SINGLEROW option을 사용할 수 있다.
이 option은 controlfile 내에 다음과 같은 형태로 기술하며, direct path
load에만 사용 가능하다.
into tables table_name [sorted indexes...] singlerow
이 option을 사용하면 전체 data가 load된 뒤에 index가 구성되는 것이 아니라
data가 load됨에 따라 data 각각이 바로 index에 추가된다.
이 option은 기존에 미리 index가 존재하는 경우 index를 생성하는 동안
merge를 위해 space를 추가적으로 필요로 하는 것을 막고자 하는 것이므로
INSERT 시에는 사용하지 않고, APPEND시에만 사용하도록 하고 있다.
실제 새로 load할 data 보다 기존 table이 20배 이상 클 때 사용하도록 권하고
있다.
direct path load는 rollback information을 기록하지 않지만, 이 singlerow
option을 사용하면 insert되는 index에 대해 undo 정보를 rollback segment에
기록하게 된다.
그러나, 중간에 instance failure가 발생하면 data는 data save까지는 보존
되지만 index는 여전히 direct load state로 사용할 수 없게 된다.
--- Direct Load State
만약 direct path load가 성공적으로 끝나지 않으면 index는 direct load
state로 된다.
이 index를 통해 조회하고자 하면 다음과 같은 오류가 발생한다.
ORA-01502 : index 'SCOTT.DEPT_PK' is in direct load state.
index가 direct load state로 되는 원인을 구체적으로 살펴보면 다음과 같다.
(1) index가 생성되는 과정에서 space가 부족한 경우
(2) SORTED INDEXES clause가 사용되었으나, 실제 data는 정렬되어 있지 않은
경우
이러한 경우 data는 모두 load가 되고, index만이 direct load state로 된다.
(3) index 생성 도중 instance failure가 발생한 경우
(4) unique index가 지정되어 있는 컬럼에 중복된 data가 load되는 경우
특정 index가 direct load state인지를 확인하는 방법은 다음과 같다.
select index_name, status
from user_indexes
where table_name = TABLE_NAME';
만약 index가 direct load state로 나타나면 그 index는 drop하고 재생성
하여야만 사용할 수 있다. 단, direct load 중에는 모든 index가 direct
load state로 되었다가 load가 성공적으로 끝나면 자동으로 valid로 변경된다.
--- Pre-sorting (SORTED INDEX)
direct load 시 index구성을 위해서 정렬하는 시간을 줄이기 위해 미리 index
column에 대해서 data를 정렬하여 load시킬 수 있다. 이 때 control file 내에
SORTED INDEXES option을 다음과 같이 정의한다.
이 option은 direct path load 시에만 유효하며, 복수 개의 index에 대해서
지정가능하다.
into table table_name SORTED INDEXES (index_names_with_blank)
만약, 기존의 index가 이미 존재한다면, 새로운 key를 일시적으로 저장할 만큼
의 temporary storage가 필요하며, 기존 index가 없는 경우였다면, 이러한
temporary space도 필요하지 않다.
이와 같이 direct path load 시에 index 구성 시에는 기존 데이타가 있는 table에
load하는 경우 space도 추가적으로 들고, load가 완전히 성공적으로 끝나지 않으면
index를 재생성하여야 하므로, 일반적으로 direct path load 전에 미리 table의
index를 제거한 후 load가 모두 끝난 후 재생성하도록 한다.
5. Recovery
direct load는 기존 segment중간에 data를 insert하는 것이 아니라 완전히
새로운 block을 할당받아 정확히 write가 끝난 다음 해당 segment에 포함되기
때문에 instance failure시에는 redo log정보를 필요로 하지 않는다. 그러나
default로 direct load는 redo log에 입력되는 data를 기록하는데 이것은 media
recovery를 위한 것이다. 그러므로 archive log mode가 아니면 direct load에
생성된 redo log 정보는 불필요하게 되므로 NOARCHIVELOG mode시에는 항상
control file내에 UNRECOVERABLE이라는 option을 사용하여 redo log에 redo entry를 기록하지 않도록 한다.
data가 redo log 정보 없이 instance failure시에 data save까지는 보호되는데
반해 index는 무조건 direct load state가 되어 재생성하여야 한다. 그리고 data save이후의 load하고자 하는 table에 할당되었던 extent는 load된 data가
user에게 보여지지는 않지만 extent가 free space로 release되지는 않는다.
6. Integrity Constraints & Triggers
direct path load중 not null, unique, primary key constraint는 enable
상태로 존재한다. not null은 insert시에 check되고 unique는 load후 index를
구성하는 시점에 check된다.
그러나 check constraint와 referential constraint는 load가 시작되면서
disable상태로 된다. 전체 데이타가 load되고 난 후 이렇게 disable된
constraints를 enable시키려면 control file내에 REENABLE이라는 option을
지정하여야 한다. 이 reenable option은 각 constraint마다 지정할 수는 없으며
control file에 한번 지정하면 전체 integrity/check constraint에 영향을
미치게 된다. 만약 reenable되는 과정에서 constraint를 위배하는 data가
발견되면 해당 constraint는 enable되지 못하고 disabled status로 남게 되며,
이렇게 위배된 data를 확인하기 위해서는 reenable clause에 exceptions option을 다음과 같이 추가하면 된다.
reenable [exceptions table_name]
이 때 table_name은 $ORACLE_HOME/rdbms/admin/utlexcpt.sql을 다른
directory로copy하여 table이름을 exceptions가 아닌 다른 이름으로 만들어 수행시키면 된다.
insert trigger도 integrity/check constraint와 같이 direct load가 시작하는
시점에 disable되며, load가 끝나면 자동으로 enable된다. 단 enable되고 나서도
load에 의해 입력된 data에 대해 trigger가 fire되지는 않는다. -
Direct-Path with (No)Archivelog and recovery
Hi,
In a datawarehouse environment, our database is in NOARCHIVELOG. When we do a Insert /*+ APPEND */ on a table withLOGGING attribute, a miniminal redo log is generated.
We want to switch the database in ARCHIVELOG mode, and change the attribute of the table to NOLOGGING .
My question is, does instance recovery will work ?
I made a matrix of the effect of a crash while a direct-path Insert operation :
Database mode Table mode Instance recovery Media recovery
NOARCHIVELOG LOGGING OK NOT OK
ARCHIVELOG LOGGING OK OK
ARCHIVELOG NOLOGGING OK NOT OK
Do you agree with this matrix ?
RegardsYes instance recovery will work regardless of direct-path and nologgging usage.
Here is an example with Oracle XE on Windows (database runs in ARCHIVELOG mode and FORCE_LOGGING is not set):
c:\tmp>rman target /
Recovery Manager: Release 11.2.0.2.0 - Production on Jeu. Janv. 12 20:05:32 2012
Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.
connected to target database: XE (DBID=2642463371)
RMAN> report unrecoverable;
using target database control file instead of recovery catalog
Report of files that need backup due to unrecoverable operations
File Type of Backup Required Name
RMAN> exit
Recovery Manager complete.
c:\tmp>sqlplus xxx/xxx @nolog.sql
SQL*Plus: Release 11.2.0.2.0 Production on Jeu. Janv. 12 20:05:48 2012
Copyright (c) 1982, 2010, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Express Edition Release 11.2.0.2.0 - Production
SQL> select log_mode, force_logging from v$database;
LOG_MODE FOR
ARCHIVELOG NO
SQL> drop table tnl purge;
Table dropped.
SQL> create table tnl(x int) nologging tablespace users;
Table created.
SQL> insert /*+ APPEND */ into tnl select object_id from all_objects;
17971 rows created.
SQL> commit;
Commit complete.
SQL> connect / as sysdba
Connected.
SQL> startup force
ORACLE instance started.
Total System Global Area 1071333376 bytes
Fixed Size 1388352 bytes
Variable Size 658505920 bytes
Database Buffers 406847488 bytes
Redo Buffers 4591616 bytes
Database mounted.
Database opened.
SQL> exit
Disconnected from Oracle Database 11g Express Edition Release 11.2.0.2.0 - Production
c:\tmp>rman target /
Recovery Manager: Release 11.2.0.2.0 - Production on Jeu. Janv. 12 20:07:34 2012
Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.
connected to target database: XE (DBID=2642463371)
RMAN> report unrecoverable;
using target database control file instead of recovery catalog
Report of files that need backup due to unrecoverable operations
File Type of Backup Required Name
4 full or incremental C:\ORACLEXE\APP\ORACLE\ORADATA\XE\USERS.DBF
RMAN> exit
Recovery Manager complete.
c:\tmp>Edited by: P. Forstmann on 12 janv. 2012 20:08 -
Serial table scan with direct path read compared to db file scattered read
Hi,
The environment
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit
8K block size
db_file_multiblock_read_count is 128
show sga
Total System Global Area 1.6702E+10 bytes
Fixed Size 2219952 bytes
Variable Size 7918846032 bytes
Database Buffers 8724152320 bytes
Redo Buffers 57090048 bytes
16GB of SGA with 8GB of db buffer cache.
-- database is built on Solid State Disks
-- SQL trace and wait events
DBMS_MONITOR.SESSION_TRACE_ENABLE ( waits=>true )
-- The underlying table is called tdash. It has 1.7 Million rows based on data in all_objects. NO index
TABLE_NAME Rows Table Size/MB Used/MB Free/MB
TDASH 1,729,204 15,242 15,186 56
TABLE_NAME Allocated blocks Empty blocks Average space/KB Free list blocks
TDASH 1,943,823 7,153 805 0
Objectives
To show that when serial scans are performed on database built on Solid State Disks (SSD) compared to Magnetic disks (HDD), the performance gain is far less compared to random reads with index scans on SSD compared to HDD
Approach
We want to read the first 100 rows of tdash table randomly into buffer, taking account of wait events and wait times generated. The idea is that on SSD the wait times will be better compared to HDD but not that much given the serial nature of table scans.
The code used
ALTER SESSION SET TRACEFILE_IDENTIFIER = 'test_with_tdash_ssdtester_noindex';
DECLARE
type array is table of tdash%ROWTYPE index by binary_integer;
l_data array;
l_rec tdash%rowtype;
BEGIN
SELECT
a.*
,RPAD('*',4000,'*') AS PADDING1
,RPAD('*',4000,'*') AS PADDING2
BULK COLLECT INTO
l_data
FROM ALL_OBJECTS a;
DBMS_MONITOR.SESSION_TRACE_ENABLE ( waits=>true );
FOR rs IN 1 .. 100
LOOP
BEGIN
SELECT * INTO l_rec FROM tdash WHERE object_id = l_data(rs).object_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
END LOOP;
END;
/Server is rebooted prior to any tests
Whern run as default, the optimizer (although some attribute this to the execution engine) chooses direct path read into PGA in preference to db file scattered read.
With this choice it takes 6,520 seconds to complete the query. The results are shown below
SQL ID: 78kxqdhk1ubvq
Plan Hash: 1148949653
SELECT *
FROM
TDASH WHERE OBJECT_ID = :B1
call count cpu elapsed disk query current rows
Parse 1 0.01 0.00 2 47 0 0
Execute 100 0.00 0.00 1 51 0 0
Fetch 100 10.88 6519.89 194142802 194831012 0 100
total 201 10.90 6519.90 194142805 194831110 0 100
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 96 (SSDTESTER) (recursive depth: 1)
Rows Row Source Operation
1 TABLE ACCESS FULL TDASH (cr=1948310 pr=1941430 pw=0 time=0 us cost=526908 size=8091 card=1)
Rows Execution Plan
0 SELECT STATEMENT MODE: ALL_ROWS
1 TABLE ACCESS MODE: ANALYZED (FULL) OF 'TDASH' (TABLE)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
Disk file operations I/O 3 0.00 0.00
db file sequential read 2 0.00 0.00
direct path read 1517504 0.05 6199.93
asynch descriptor resize 196 0.00 0.00
DECLARE
type array is table of tdash%ROWTYPE index by binary_integer;
l_data array;
l_rec tdash%rowtype;
BEGIN
SELECT
a.*
,RPAD('*',4000,'*') AS PADDING1
,RPAD('*',4000,'*') AS PADDING2
BULK COLLECT INTO
l_data
FROM ALL_OBJECTS a;
DBMS_MONITOR.SESSION_TRACE_ENABLE ( waits=>true );
FOR rs IN 1 .. 100
LOOP
BEGIN
SELECT * INTO l_rec FROM tdash WHERE object_id = l_data(rs).object_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
END LOOP;
END;
call count cpu elapsed disk query current rows
Parse 0 0.00 0.00 0 0 0 0
Execute 1 3.84 4.03 320 48666 0 1
Fetch 0 0.00 0.00 0 0 0 0
total 1 3.84 4.03 320 48666 0 1
Misses in library cache during parse: 0
Misses in library cache during execute: 1
Optimizer mode: ALL_ROWS
Parsing user id: 96 (SSDTESTER)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 1 0.00 0.00
SQL*Net message from client 1 0.00 0.00
SQL ID: 9babjv8yq8ru3
Plan Hash: 0
BEGIN DBMS_OUTPUT.GET_LINES(:LINES, :NUMLINES); END;
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 1
Fetch 0 0.00 0.00 0 0 0 0
total 2 0.00 0.00 0 0 0 1
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 96 (SSDTESTER)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 1 0.00 0.00
SQL*Net message from client 1 0.00 0.00
OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0
Execute 2 3.84 4.03 320 48666 0 2
Fetch 0 0.00 0.00 0 0 0 0
total 3 3.84 4.03 320 48666 0 2
Misses in library cache during parse: 0
Misses in library cache during execute: 1
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 2 0.00 0.00
SQL*Net message from client 2 0.00 0.00
log file sync 1 0.00 0.00
OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
Parse 9 0.01 0.00 2 47 0 0
Execute 129 0.01 0.00 1 52 2 1
Fetch 140 10.88 6519.89 194142805 194831110 0 130
total 278 10.91 6519.91 194142808 194831209 2 131
Misses in library cache during parse: 9
Misses in library cache during execute: 8
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
db file sequential read 5 0.00 0.00
Disk file operations I/O 3 0.00 0.00
direct path read 1517504 0.05 6199.93
asynch descriptor resize 196 0.00 0.00
102 user SQL statements in session.
29 internal SQL statements in session.
131 SQL statements in session.
1 statement EXPLAINed in this session.
Trace file: mydb_ora_16394_test_with_tdash_ssdtester_noindex.trc
Trace file compatibility: 11.1.0.7
Sort options: default
1 session in tracefile.
102 user SQL statements in trace file.
29 internal SQL statements in trace file.
131 SQL statements in trace file.
11 unique SQL statements in trace file.
1 SQL statements EXPLAINed using schema:
ssdtester.plan_table
Schema was specified.
Table was created.
Table was dropped.
1531657 lines in trace file.
6520 elapsed seconds in trace file.I then force the query not to use direct path read by invoking
ALTER SESSION SET EVENTS '10949 trace name context forever, level 1' -- No Direct path read ;In this case the optimizer uses db file scattered read predominantly and the query takes 4,299 seconds to finish which is around 34% faster than using direct path read (default).
The report is shown below
SQL ID: 78kxqdhk1ubvq
Plan Hash: 1148949653
SELECT *
FROM
TDASH WHERE OBJECT_ID = :B1
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 2 47 0 0
Execute 100 0.00 0.00 2 51 0 0
Fetch 100 143.44 4298.87 110348670 194490912 0 100
total 201 143.45 4298.88 110348674 194491010 0 100
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 96 (SSDTESTER) (recursive depth: 1)
Rows Row Source Operation
1 TABLE ACCESS FULL TDASH (cr=1944909 pr=1941430 pw=0 time=0 us cost=526908 size=8091 card=1)
Rows Execution Plan
0 SELECT STATEMENT MODE: ALL_ROWS
1 TABLE ACCESS MODE: ANALYZED (FULL) OF 'TDASH' (TABLE)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
Disk file operations I/O 3 0.00 0.00
db file sequential read 129759 0.01 17.50
db file scattered read 1218651 0.05 3770.02
latch: object queue header operation 2 0.00 0.00
DECLARE
type array is table of tdash%ROWTYPE index by binary_integer;
l_data array;
l_rec tdash%rowtype;
BEGIN
SELECT
a.*
,RPAD('*',4000,'*') AS PADDING1
,RPAD('*',4000,'*') AS PADDING2
BULK COLLECT INTO
l_data
FROM ALL_OBJECTS a;
DBMS_MONITOR.SESSION_TRACE_ENABLE ( waits=>true );
FOR rs IN 1 .. 100
LOOP
BEGIN
SELECT * INTO l_rec FROM tdash WHERE object_id = l_data(rs).object_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
END LOOP;
END;
call count cpu elapsed disk query current rows
Parse 0 0.00 0.00 0 0 0 0
Execute 1 3.92 4.07 319 48625 0 1
Fetch 0 0.00 0.00 0 0 0 0
total 1 3.92 4.07 319 48625 0 1
Misses in library cache during parse: 0
Misses in library cache during execute: 1
Optimizer mode: ALL_ROWS
Parsing user id: 96 (SSDTESTER)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 1 0.00 0.00
SQL*Net message from client 1 0.00 0.00
SQL ID: 9babjv8yq8ru3
Plan Hash: 0
BEGIN DBMS_OUTPUT.GET_LINES(:LINES, :NUMLINES); END;
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 1
Fetch 0 0.00 0.00 0 0 0 0
total 2 0.00 0.00 0 0 0 1
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 96 (SSDTESTER)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 1 0.00 0.00
SQL*Net message from client 1 0.00 0.00
OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0
Execute 2 3.92 4.07 319 48625 0 2
Fetch 0 0.00 0.00 0 0 0 0
total 3 3.92 4.07 319 48625 0 2
Misses in library cache during parse: 0
Misses in library cache during execute: 1
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 2 0.00 0.00
SQL*Net message from client 2 0.00 0.00
log file sync 1 0.00 0.00
OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS
call count cpu elapsed disk query current rows
Parse 9 0.01 0.00 2 47 0 0
Execute 129 0.00 0.00 2 52 2 1
Fetch 140 143.44 4298.87 110348674 194491010 0 130
total 278 143.46 4298.88 110348678 194491109 2 131
Misses in library cache during parse: 9
Misses in library cache during execute: 8
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
db file sequential read 129763 0.01 17.50
Disk file operations I/O 3 0.00 0.00
db file scattered read 1218651 0.05 3770.02
latch: object queue header operation 2 0.00 0.00
102 user SQL statements in session.
29 internal SQL statements in session.
131 SQL statements in session.
1 statement EXPLAINed in this session.
Trace file: mydb_ora_26796_test_with_tdash_ssdtester_noindex_NDPR.trc
Trace file compatibility: 11.1.0.7
Sort options: default
1 session in tracefile.
102 user SQL statements in trace file.
29 internal SQL statements in trace file.
131 SQL statements in trace file.
11 unique SQL statements in trace file.
1 SQL statements EXPLAINed using schema:
ssdtester.plan_table
Schema was specified.
Table was created.
Table was dropped.
1357958 lines in trace file.
4299 elapsed seconds in trace file.I note that there are 1,517,504 waits with direct path read with total time of nearly 6,200 seconds. In comparison with no direct path read, there are 1,218,651 db file scattered read waits with total wait time of 3,770 seconds. My understanding is that direct path read can use single or multi-block read into the PGA. However db file scattered reads do multi-block read into multiple discontinuous SGA buffers. So it is possible given the higher number of direct path waits that the optimizer cannot do multi-block reads (contigious buffers within PGA) and hence has to revert to single blocks reads which results in more calls and more waits?.
Appreciate any advise and apologies for being long winded.
Thanks,
MichHi Charles,
I am doing your tests for t1 table using my server.
Just to clarify my environment is:
I did the whole of this test on my server. My server has I7-980 HEX core processor with 24GB of RAM and 1 TB of HDD SATA II for test/scratch backup and archive. The operating system is RHES 5.2 64-bit installed on a 120GB OCZ Vertex 3 Series SATA III 2.5-inch Solid State Drive.
Oracle version installed was 11g Enterprise Edition Release 11.2.0.1.0 -64bit. The binaries were created on HDD. Oracle itself was configured with 16GB of SGA, of which 7.5GB was allocated to Variable Size and 8GB to Database Buffers.
For Oracle tablespaces including SYS, SYSTEM, SYSAUX, TEMPORARY, UNDO and redo logs, I used file systems on 240GB OCZ Vertex 3 Series SATA III 2.5-inch Solid State Drive. With 4K Random Read at 53,500 IOPS and 4K Random Write at 56,000 IOPS (manufacturer’s figures), this drive is probably one of the fastest commodity SSDs using NAND flash memory with Multi-Level Cell (MLC). Now my T1 table created as per your script and has the following rows and blocks (8k block size)
SELECT
NUM_ROWS,
BLOCKS
FROM
USER_TABLES
WHERE
TABLE_NAME='T1';
NUM_ROWS BLOCKS
12000000 178952which is pretty identical to yours.
Then I run the query as brelow
set timing on
ALTER SESSION SET TRACEFILE_IDENTIFIER = 'test_bed_T1';
ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT FOREVER, LEVEL 8';
SELECT
COUNT(*)
FROM
T1
WHERE
RN=1;
which gives
COUNT(*)
60000
Elapsed: 00:00:05.29
tkprof output shows
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.02 5.28 178292 178299 0 1
total 4 0.02 5.28 178292 178299 0 1
Compared to yours:
Fetch 2 0.60 4.10 178493 178498 0 1
It appears to me that my CPU utilisation is by order of magnitude better but my elapsed time is worse!
Now the way I see it elapsed time = CPU time + wait time. Further down I have
Rows Row Source Operation
1 SORT AGGREGATE (cr=178299 pr=178292 pw=0 time=0 us)
60000 TABLE ACCESS FULL T1 (cr=178299 pr=178292 pw=0 time=42216 us cost=48697 size=240000 card=60000)
Rows Execution Plan
0 SELECT STATEMENT MODE: ALL_ROWS
1 SORT (AGGREGATE)
60000 TABLE ACCESS MODE: ANALYZED (FULL) OF 'T1' (TABLE)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 3 0.00 0.00
SQL*Net message from client 3 0.00 0.00
Disk file operations I/O 3 0.00 0.00
direct path read 1405 0.00 4.68
Your direct path reads are
direct path read 1404 0.01 3.40Which indicates to me you have faster disks compared to mine, whereas it sounds like my CPU is faster than yours.
With db file scattered read I get
Elapsed: 00:00:06.95
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 1.22 6.93 178293 178315 0 1
total 4 1.22 6.94 178293 178315 0 1
Rows Row Source Operation
1 SORT AGGREGATE (cr=178315 pr=178293 pw=0 time=0 us)
60000 TABLE ACCESS FULL T1 (cr=178315 pr=178293 pw=0 time=41832 us cost=48697 size=240000 card=60000)
Rows Execution Plan
0 SELECT STATEMENT MODE: ALL_ROWS
1 SORT (AGGREGATE)
60000 TABLE ACCESS MODE: ANALYZED (FULL) OF 'T1' (TABLE)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 2 0.00 0.00
Disk file operations I/O 3 0.00 0.00
db file sequential read 1 0.00 0.00
db file scattered read 1414 0.00 5.36
SQL*Net message from client 2 0.00 0.00
compared to your
db file scattered read 1415 0.00 4.16On the face of it with this test mine shows 21% improvement with direct path read compared to db scattered file read. So now I can go back to re-visit my original test results:
First default with direct path read
call count cpu elapsed disk query current rows
Parse 1 0.01 0.00 2 47 0 0
Execute 100 0.00 0.00 1 51 0 0
Fetch 100 10.88 6519.89 194142802 194831012 0 100
total 201 10.90 6519.90 194142805 194831110 0 100
CPU ~ 11 sec, elapsed ~ 6520 sec
wait stats
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
direct path read 1517504 0.05 6199.93
roughly 0.004 sec for each I/ONow with db scattered file read I get
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 2 47 0 0
Execute 100 0.00 0.00 2 51 0 0
Fetch 100 143.44 4298.87 110348670 194490912 0 100
total 201 143.45 4298.88 110348674 194491010 0 100
CPU ~ 143 sec, elapsed ~ 4299 sec
and waits:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
db file sequential read 129759 0.01 17.50
db file scattered read 1218651 0.05 3770.02
roughly 17.5/129759 = .00013 sec for single block I/O and 3770.02/1218651 = .0030 for multi-block I/ONow my theory is that the improvements comes from the large buffer cache (8320MB) inducing it to do some read aheads (async pre-fetch). Read aheads are like quasi logical I/Os and they will be cheaper compared to physical I/O. When there is large buffer cache and read aheads can be done then using buffer cache is a better choice than PGA?
Regards,
Mich -
External Table and Direct path load
Hi,
I was just playing with Oracle sql loader and external table features. few things which i ovserved are that data loading through direct path method of sqlloader is much faster and takes much less hard disk space than what external table method takes. here are my stats which i found while data loading:
For Direct Path: -
# OF RECORDS.............TIME...................SOURCE FILE SIZE...................DATAFILE SIZE(.dbf)
478849..........................00:00:43.53...................108,638 KB...................142,088 KB
957697..........................00:01:08.81...................217,365 KB...................258,568 KB
1915393..........................00:02:54.43...................434,729 KB...................509,448 KB
For External Table: -
# OF RECORDS..........TIME...................SOURCE FILE SIZE...................DATAFILE SIZE(.dbf)
478849..........................00:02:51.03...................108,638 KB...................966,408 KB
957697..........................00:08:05.32...................217,365 KB...................1,930,248 KB
1915393..........................00:17:16.31...................434,729 KB...................3,860,488 KB
1915393..........................00:23:17.05...................434,729 KB...................3,927,048 KB
(With PARALLEL)
i used same files for testing and all other conditions are similar also. In my case datafile is autoextendable, hence, as par requirement its size is automatically increased and hard disk space is reduced thus.The issue is that, is this an expected behaviour? and why in case of external tables such a large hard disk space is used when compared to direct path method? Performance of external table load is also very bad when compared to direct path load.
one more thing is that while using external table load with PARALLEL option, ideally, it should take less time. But what i actually get is more than what the time was without PARALLEL option.
In both the cases i am loading data from the same file to the same table (once using direct path and once using external table). before every fresh loading i truncate my internal table into which data was loaded.
any views??
Deep
Message was edited by:
DeepThanx to all for your suggestions.
John, my scripts are as follows:
for external table:
CREATE TABLE LOG_TBL_LOAD
(COL1 CHAR(20), COL2 CHAR(2), COL3 CHAR(20), COL4 CHAR(400),
COL5 CHAR(20), COL6 CHAR(400), COL7 CHAR(20), COL8 CHAR(20),
COL9 CHAR(400), COL10 CHAR(400))
ORGANIZATION EXTERNAL
(TYPE ORACLE_LOADER
DEFAULT DIRECTORY EXT_TAB_DIR
ACCESS PARAMETERS
(RECORDS DELIMITED BY NEWLINE
FIELDS TERMINATED BY WHITESPACE OPTIONALLY ENCLOSED BY '"' MISSING FIELD VALUES ARE NULL
LOCATION ('LOGZ3.DAT')
REJECT LIMIT 10;
for loading i did:
INSERT INTO LOG_TBL (COL1, COL2, COL3, COL4,COL5, COL6,
COL7, COL8, COL9, COL10)
(SELECT COL1, COL2, COL3, COL4, COL5, COL6, COL7, COL8,
COL9, COL10 FROM LOG_TBL_load_1);
for direct path my control file is like this:
OPTIONS (
DIRECT = TRUE
LOAD DATA
INFILE 'F:\DATAFILES\LOGZ3.DAT' "str '\n'"
INTO TABLE LOG_TBL
APPEND
FIELDS TERMINATED BY WHITESPACE OPTIONALLY ENCLOSED BY '"'
(COL1 CHAR(20),
COL2 CHAR(2),
COL3 CHAR(20),
COL4 CHAR(400),
COL5 CHAR(20),
COL6 CHAR(400),
COL7 CHAR(20),
COL8 CHAR(20),
COL9 CHAR(400),
COL10 CHAR(400))
and ya, i have used same table in both the situations. after loading once i used to truncate my table, LOG_TBL. i used the same source file, LOGZ3.DAT.
my tablespace USERS is loaclly managed.
thanks -
Hi,
I am trying to load data using SQL Loader Direct Path. One of the tables has a REC_UPD_DT column which is of timestamp datatype. The table was created with default value of SYSTIMESTAMP on this column. However when I load the table, the REC_UPD_DT is null due to the behavior(bypasses the sqlfunctions, etc) of the Direct Path method.
What is the way out to achieve my objective?
I do not want to use the conventional path since that is proven to be slow for my case.
Thanks in advance
PavinHi,
My apologies for not providing requested information before. Here are the scripts:
I am testing from my windows m/c.
Database version: 10.2.0.3
Table creation script:
CREATE TABLE TXN_DEFAULT
(MAPPER_Q_ID NUMBER(1,0) NOT NULL,
TRANSACTION_SEQUENCE NUMBER(10,0) NOT NULL,
RECORD_COUNT NUMBER(4,0),
STATUS VARCHAR2(1 CHAR),
USER_ID VARCHAR2(20 CHAR),
USER_IP_ADDRESS VARCHAR2(35 CHAR),
REC_UPD_DT TIMESTAMP (6) DEFAULT SYSTIMESTAMP
Loader Control file script:
OPTIONS (DIRECT=TRUE)
load data
CHARACTERSET WE8ROMAN8
into table TXN_DEFAULT
append
FIELDS TERMINATED BY ' '
trailing nullcols
MAPPER_Q_ID,
TRANSACTION_SEQUENCE,
RECORD_COUNT,
STATUS,
USER_ID,
USER_IP_ADDRESS,
REC_UPD_DT
Sample Dat file contents:
0 251939112 3 N chowdsr 10.222.79.20
1 251939113 140 N zhuanre 146.222.52.176
2 251939114 41 N sombupo 146.222.187.155
0 251939116 75 N BaseAdmin 146.222.4.246
Log File contents:
SQL*Loader: Release 10.2.0.1.0 - Production on Mon Dec 7 13:22:23 2009
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Control File: Control.ctl
Character Set WE8ROMAN8 specified for all input.
Data File: Control.dat
Bad File: Control.bad
Discard File: none specified
(Allow all discards)
Number to load: ALL
Number to skip: 0
Errors allowed: 50
Continuation: none specified
Path used: Direct
Table TXN_DEFAULT, loaded from every logical record.
Insert option in effect for this table: APPEND
TRAILING NULLCOLS option in effect
Column Name Position Len Term Encl Datatype
MAPPER_Q_ID FIRST * WHT CHARACTER
TRANSACTION_SEQUENCE NEXT * WHT CHARACTER
RECORD_COUNT NEXT * WHT CHARACTER
STATUS NEXT * WHT CHARACTER
USER_ID NEXT * WHT CHARACTER
USER_IP_ADDRESS NEXT * WHT CHARACTER
REC_UPD_DT NEXT * WHT CHARACTER
Table TXN_DEFAULT:
4 Rows successfully loaded.
0 Rows not loaded due to data errors.
0 Rows not loaded because all WHEN clauses were failed.
0 Rows not loaded because all fields were null.
Bind array size not used in direct path.
Column array rows : 5000
Stream buffer bytes: 256000
Read buffer bytes: 1048576
Total logical records skipped: 0
Total logical records read: 4
Total logical records rejected: 0
Total logical records discarded: 0
Total stream buffers loaded by SQL*Loader main thread: 1
Total stream buffers loaded by SQL*Loader load thread: 0
Run began on Mon Dec 07 13:22:23 2009
Run ended on Mon Dec 07 13:22:23 2009
Elapsed time was: 00:00:00.75
CPU time was: 00:00:00.08
If I run using Conventional path, the REC_UPD_DT is populated with the a systimestamp value. However, this column values are null when I use the Direct path. Log files have no errors. What is the way out to achieve my objective?
Thanks in advance.
- Pavin -
Archive log / nologging/ direct path insert
Could you please confirm if following are true or correct me if my understanding is wrong:
1 ) Archive log mode and LOGGING is needed to deal with media recovery; it was not needed for instance recovery.
2) IF insert is in NO APPEND mode , redo is generated even if table is in nologging mode and database is in noachive log mode. This redo is needed for instance recovery.
3) Direct path insert skips undo generation and may skip redo generation if the object is in nologging mode.
Thanks.
In case if it is relevant , I am using Oracle 11.2.0.3.1) Yes, Archive logs are needed for media recovery.
2 and 3) Even if the table is in nologging mode , it generates little bit of redo for index maintenance and dictionary data. Upon a restart from a failure - Oracle will read the online redo logs and replay any transaction it finds in there. That is the "roll forward" bit. The binary redo information is used to replay everything that did not get written to the datafiles. This replay included regenerating the UNDO information (UNDO is protected by redo).
After the redo has been applied, the database is typically available for use now - and the rollback phase begins. For any transaction that was being processed when the instance failed - we need to undo its changes, roll it back. We do that by processing the undo for all uncommitted transactions.
The database is now fully recovered.
Also read he following link
http://docs.oracle.com/cd/B19306_01/server.102/b14220/startup.htm
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:5280714813869 -
Hi,
I am using following insert statement on my forms application to do direct path insert.
insert into /*+append*/ abc select * from xyz;
as redo is not generated if you do direct path insert but in above case redo is generating for the above insert statement.
I then created a procedure test_insert as below
create procedure test_insert is
begin
insert into /*+append*/ abc select * from xyz;
end;
i then replaced the insert statement with above procedure on form and after that redo for the insert statement stopped.
i was wondering if we could use append hint for direct path insert on forms?My point, though, is that if you're doing your hourly load into a separate table and building the index(es) on that table before moving the partition into the partitioned table, there is no risk of doing anything to screw up the partitioned table. It's also a very handy way to ensure that your load process doesn't interfere with your production data.
If i have understood your point right, what about the space required ( tablespaces and the indexes). Trust me, my table at source gets populated @ over 230 MIL records /day. If i have a temp table, i will have to maintain hourly partitions/indexes/tablespaces for the temp table to hold so much data, isn't it? And, the data i move (say today's data) will be used by the user only after 4 days (because it is available in the source). We have provisioned our user interface to connect to 2 databases, one with 5 days of data (incl. sysdate) and the other one is a archive DB that holds 45 days worth of data.
</>
I wouldn't expect that a direct path load into a single partition of a partitioned table would invalidate local indexes on other partitions, but since I'd never do a direct path load into a single partition of a partitioned table, I've not tested this to make sure.
No problem, if i try this out i will share it in the forum. </>Thanks -
Hi,
I have the query below:
with D_FLO_PTN as (SELECT *
FROM FLO_PTN
WHERE FLO_PTN.ID_ETU IN (SELECT id_etu
FROM music_adm.adm_users_rights
WHERE user_name = UPPER ('SALG_CB'))
OR FLO_PTN.PDTETU IN
(SELECT id_pdtetu
FROM music_adm.adm_users_rights
WHERE user_name = UPPER ('SALG_CB'))
OR EXISTS
(SELECT 1
FROM music_adm.adm_users_rights
WHERE id_etu = 0
AND id_pdtetu = '0'
AND user_name = UPPER ('SALG_CB'))),
D_FAI_VIS as (SELECT *
FROM FAI_VIS
WHERE FAI_VIS.ID_ETU IN (SELECT id_etu
FROM music_adm.adm_users_rights
WHERE user_name = UPPER ('SALG_CB'))
OR FAI_VIS.PDTETU IN
(SELECT id_pdtetu
FROM music_adm.adm_users_rights
WHERE user_name = UPPER ('SALG_CB'))
OR EXISTS
(SELECT 1
FROM music_adm.adm_users_rights
WHERE id_etu = 0
AND id_pdtetu = '0'
AND user_name = UPPER ('SALG_CB'))),
d_dim_etu as (SELECT *
FROM DIM_ETU
WHERE DIM_ETU.ID_ETU IN (SELECT id_etu
FROM music_adm.adm_users_rights
WHERE user_name = UPPER ('SALG_CB'))
OR DIM_ETU.PDTETU IN
(SELECT id_pdtetu
FROM music_adm.adm_users_rights
WHERE user_name = UPPER ('SALG_CB'))
OR EXISTS
(SELECT 1
FROM music_adm.adm_users_rights
WHERE id_etu = 0
AND id_pdtetu = '0'
AND user_name = UPPER ('SALG_CB')))
SELECT TRIM (TO_CHAR (D_FLO_PTN.PTNNUMETU, '00000')),
FLO_ITM.FMLNOMPAP,
FLO_ITM.ITMNOMPAP,
FLO_ITM.ITMVALCHR,
FLO_ITM.ITMVALNUM,
D_FAI_VIS.VISCOD,
TRIM (TO_CHAR (D_FLO_PTN.NBRCEN, '0000')),
TRIM (TO_CHAR (D_FAI_VIS.ID_ETU, '000')) || '-'
|| TRIM(TO_CHAR (
SUBSTR (D_FAI_VIS.ID_PTN,
1,
LENGTH (D_FAI_VIS.ID_PTN) - 5),
'00000'
|| '-'
|| D_FAI_VIS.VISCOD,
D_DIM_ETU.NUMETU,
D_FLO_PTN.LIBPAY,
FLO_ITM.ITMVALNUM,
D_FAI_VIS.VISDATTXT,
FLO_ITM.ITMVALNUM,
FLO_ITM.FMLKEYVAL
FROM
D_FLO_PTN,
FLO_ITM,
D_FAI_VIS,
D_DIM_ETU
WHERE (FLO_ITM.ID_VIS = D_FAI_VIS.ID_VIS)
AND (D_FLO_PTN.ID_PTN = D_FAI_VIS.ID_PTN)
AND (D_DIM_ETU.ID_ETU = D_FLO_PTN.ID_ETU)
AND ( D_DIM_ETU.NUMETU IN ('CL2-38093-011')
AND FLO_ITM.FMLNOMPAP IN ('MMS')
AND (D_FLO_PTN.INDSLC = 'YES')
AND TRIM (TO_CHAR (D_FLO_PTN.PTNNUMETU, '00000')) IN
(SELECT TRIM (
TO_CHAR (D_FLO_PTN.PTNNUMETU, '00000')
FROM D_FLO_PTN,
FLO_ITM,
D_FAI_VIS
WHERE (FLO_ITM.ID_VIS = D_FAI_VIS.ID_VIS)
AND (D_FLO_PTN.ID_PTN = D_FAI_VIS.ID_PTN)
AND ( FLO_ITM.ITMNOMPAP IN ('TMMS_D')
AND FLO_ITM.ITMVALNUM <= 20
AND D_FAI_VIS.VISCOD IN ('ASSE'))))2 things I don't understand
- almost LIO ~ PIO but I have 2.5GB for the buffer cache
- redo size, I know about delayed block cleanout
but the second execution should return redo size =0 no ?
I am the only user on the database
11.2.0.1
1st execution
1879 recursive calls
332 db block gets
250090 consistent gets
248221 physical reads
1804 redo size
631470 bytes sent via SQL*Net to client
14706 bytes received via SQL*Net from client
1090 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
16329 rows processed
2nd execution
1879 recursive calls
332 db block gets
250423 consistent gets
248220 physical reads
1732 redo size
1149536 bytes sent via SQL*Net to client
14706 bytes received via SQL*Net from client
1090 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
16329 rows processeduser12045475 wrote:
2 things I don't understand
- almost LIO ~ PIO but I have 2.5GB for the buffer cache
- redo size, I know about delayed block cleanout
but the second execution should return redo size =0 no ?
I am the only user on the database
11.2.0.1
2nd execution
1879 recursive calls
332 db block gets
250423 consistent gets
248220 physical reads
1732 redo size
1149536 bytes sent via SQL*Net to client
14706 bytes received via SQL*Net from client
1090 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
16329 rows processed
Given the amount of work you're doing, the actual redo generated is not worth worrying about other than for reasons of curiosity.
LIO ~ PIO often indicates table scans or index fast full scans - and on 11.2 such scans can use serial direct reads; this would be sufficient to answer both your questions:
a) On direct path reads the blocks are read into the PGA, not the buffer cache, so you have to re-read them on the second execution
b) On direct path read you can do cleanout and generate redo, but the blocks are not in the cache so they don't get written back to the database, so you repeat the cleanout. (A small variation in redo could indicate some cleanout taking place on space management blocks which, I think, will go through the cache).
Regards
Jonathan Lewis -
A lot of messages "direct path write temp" and "direct path read temp"
Hello, all
Please, understand me, what is going on in my system (DB: Oracle database 11.2.0.3, OS: Windows 2008 R2).
In AWR report (1 hour) I see next:
Foreground Wait Events
Avg
%Time Total Wait wait Waits % DB
Event Waits -outs Time (s) (ms) /txn time
direct path write temp 132,627 0 1,056 8 0.8 21.7
direct path read temp 308,969 0 565 2 2.0 11.6
log file sync 19,228 0 241 13 0.1 5.0
direct path write 17,698 0 135 8 0.1 2.8
db file sequential read 21,149 0 94 4 0.1 1.9
SQL*Net message from dblin 59 0 5 86 0.0 .1
Segments by Direct Physical Reads DB/Inst: SGRE/sgre Snaps: 1039-1040
-> Total Direct Physical Reads: 392,273
-> Captured Segments account for 94.7% of Total
Tablespace Subobject Obj. Direct
Owner Name Object Name Name Type Reads %Total
** MISSING TEMP ** TRANSIENT: 437734 MISSING ** UNDEF 38,290 9.76
DBSNMP TEMP MGMT_TEMPT_SQL TABLE 38,242 9.75
** MISSING TEMP ** TRANSIENT: 438784 MISSING ** UNDEF 37,790 9.63
** MISSING TEMP ** TRANSIENT: 437312 MISSING ** UNDEF 37,661 9.60
** MISSING TEMP ** TRANSIENT: 439257 MISSING ** UNDEF 37,477 9.55Some selects:
SELECT S.sid,
T.blocks * TBS.block_size / 1024 / 1024 mb_used, T.tablespace, T.SEGTYPE
FROM v$sort_usage T, v$session S, v$sqlarea Q, dba_tablespaces TBS
WHERE T.session_addr = S.saddr
AND T.sqladdr = Q.address (+)
AND T.tablespace = TBS.tablespace_name
AND S.sid = 732
ORDER BY S.username, S.sid;
SID MB_USED TABLESPACE SEGTYPE
732 2 TEMP LOB_DATA
732 1 TEMP INDEX
732 1 TEMP DATA
732 1 TEMP INDEX
732 1 TEMP DATA
732 1 TEMP INDEX
732 1 TEMP DATA
732 1 TEMP INDEX
732 1 TEMP INDEX
732 1 TEMP DATA
732 1 TEMP INDEX
732 1 TEMP INDEX
732 1 TEMP DATA
732 1 TEMP INDEX
732 1 TEMP INDEX
732 1 TEMP DATA
732 1 TEMP INDEX
732 1 TEMP INDEX
732 1 TEMP DATA
732 1 TEMP INDEX
732 1 TEMP INDEX
732 1 TEMP DATA
732 1 TEMP INDEX
732 1 TEMP INDEX
732 1 TEMP DATA
732 1 TEMP INDEX
732 1 TEMP INDEX
732 1 TEMP DATA
732 1 TEMP INDEX
732 1 TEMP LOB_INDEX
select st.sid, sn.name, st.VALUE
from V$statname sn, v$sesstat st
where st.STATISTIC# = sn.STATISTIC#
and (sn.name like 'sorts%')
and st.sid in (select sid from v$session_wait where event like '%direct path write temp%')
order by st.sid
SID NAME VALUE
732 sorts (memory) 591408
732 sorts (rows) 102126
732 sorts (disk) 0Why I do not see any disk sorts? If TEMP is used for no sort operations, then for which operations?
How I can see that? How can I decrease direct path write temp without tuning SQL?
Additional information:
PGA_AGGREGATE_TARGET is set to big value - 6GB (3GB enough due to advisory recommendation)
Please, help.
Regards, user12103911.user12103911 wrote:
SELECT optimal_count, round(optimal_count*100/total, 2) optimal_perc,
onepass_count, round(onepass_count*100/total, 2) onepass_perc,
multipass_count, round(multipass_count*100/total, 2) multipass_perc
FROM
(SELECT decode(sum(total_executions), 0, 1, sum(total_executions)) total,
sum(OPTIMAL_EXECUTIONS) optimal_count,
sum(ONEPASS_EXECUTIONS) onepass_count,
sum(MULTIPASSES_EXECUTIONS) multipass_count
FROM v$sql_workarea_histogram);
OPTIMAL_COUNT OPTIMAL_PERC ONEPASS_COUNT ONEPASS_PERC MULTIPASS_COUNT MULTIPASS_PERC
13150685 100 0 0 0 0No n-pass executions.That's a pretty convincing display - given that your AWR manages to NAME an object that is in the TEMP tablespace, an obvious point to follow up is global temporary tables. If you have any declared as "on commit preserve" (duration = 'SYS$SESSION') then you could have code which does "insert /*+ append */ into gtt", and if you then query this in parallel (or - since you're on 11.2.0.3 - the data volume is large enough) Oracle could choose to do direct path writes to load the GTT and direct path reads to read it back.
Regards
Jonathan Lewis -
Query Tuning (sequential read + direct path read/write temp)
Following query takes nearly 10 minutes under 10.2.0.2 on WIN2K3 to execute but I am sure there would be an alternate to tune it further.
Major waits are 'db file sequential read' and 'direct path read temp' in addition to 'direct path write temp'
Increasing/tuning the work_area_policy/sort_area_size would help? moving the tables to faster disk would reduce PIO causing sequential read, query re-writing would prove to be helpful?.
Below is the tkprof:
SELECT
P.PER_ID
, CL.DESCR
, P.ENG_NAME
, P.ARA_NAME
, P.NATION
, P.ADDR
, ('Mob:' || NVL(P.MOB, '') || ', Home:' || NVL(P.HOME, '') || ', Bus.:' || NVL(P.BUS, '') || ', Fax:' || NVL(P.FAX, '')) PHONE
, SUM(CASE
WHEN FT.FT_TYPE_FLG IN ('BS','BX','AD','AX') THEN FT.CUR_AMT
ELSE 0
END) BILL
, SUM(CASE
WHEN FT.FT_TYPE_FLG IN ('PS','PX') THEN FT.CUR_AMT * -1
ELSE 0
END) PAY
, SUM(FT.CUR_AMT) DUE
, SUM(CASE
WHEN FT.FREEZE_DTTM > '03-JUN-08' THEN
CASE WHEN FT.FT_TYPE_FLG IN ('PS','PX') THEN FT.CUR_AMT * -1
ELSE 0
END
ELSE 0
END) PAY_02JUN
FROM
CI_FT FT
, CI_SA SA
, CI_ACCT_CHAR AC
, CI_CUST_CL_L CL
, CI_ACCT A
, CI_ACCT_PER AP
SELECT
P.PER_ID
, (P.CITY || ', ' || P.STATE || ',' || P.COUNTRY) ADDR
, MAX(DECODE(PP.PHONE_TYPE_CD, 'MOB ', PP.PHONE)) MOB
, MAX(DECODE(PP.PHONE_TYPE_CD, 'BUSN ', PP.PHONE)) BUS
, MAX(DECODE(PP.PHONE_TYPE_CD, 'HOME ', PP.PHONE)) HOME
, MAX(DECODE(PP.PHONE_TYPE_CD, 'FAX ', PP.PHONE)) FAX
, MAX(DECODE(PN.NAME_TYPE_FLG, 'PRIM', PN.ENTITY_NAME)) ENG_NAME
, MAX(DECODE(PN.NAME_TYPE_FLG, 'ALT ', PN.ENTITY_NAME)) ARA_NAME
, MAX(DECODE(PC.CHAR_TYPE_CD, 'NATION ', PC.CHAR_VAL)) NATION
FROM
CI_PER P
, CI_PER_PHONE PP
, CI_PER_NAME PN
, CI_PER_CHAR PC
WHERE
P.PER_ID = PP.PER_ID (+)
AND P.PER_ID = PN.PER_ID (+)
AND P.PER_ID = PC.PER_ID (+)
GROUP BY
P.PER_ID
, (P.CITY || ', ' || P.STATE || ',' || P.COUNTRY)
) P
WHERE
P.PER_ID = AP.PER_ID
AND AP.ACCT_ID = AC.ACCT_ID
AND AP.ACCT_ID = SA.ACCT_ID
AND AP.MAIN_CUST_SW = 'Y'
AND A.ACCT_ID = SA.ACCT_ID
AND A.ACCT_ID = AP.ACCT_ID
AND AC.CHAR_TYPE_CD = 'ACCTYPE'
AND AC.CHAR_VAL IN ('UOS', 'DEFAULT')
AND AC.ACCT_ID = SA.ACCT_ID
AND CL.LANGUAGE_CD = 'ENG'
AND A.ACCT_ID = AC.ACCT_ID
AND A.CUST_CL_CD = CL.CUST_CL_CD
AND SA.SA_ID = FT.SA_ID
AND FT.FREEZE_DTTM IS NOT NULL
GROUP BY
P.PER_ID
, CL.DESCR
, P.ENG_NAME
, P.ARA_NAME
, P.NATION
, P.ADDR
, ('Mob:' || NVL(P.MOB, '') || ', Home:' || NVL(P.HOME, '') || ', Bus.:' || NVL(P.BUS, '') || ', Fax:' || NVL(P.FAX, ''))
HAVING
SUM(FT.CUR_AMT) > 0
call count cpu elapsed disk query current rows
Parse 1 0.64 0.64 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 304 353.09 430.04 21720 52997832 0 4543
total 306 353.73 430.69 21720 52997832 0 4543
Misses in library cache during parse: 1
Optimizer mode: CHOOSE
Parsing user id: 79 (CISADM)
Rows Row Source Operation
4543 FILTER (cr=52997832 pr=21720 pw=10311 time=430019418 us)
5412 HASH GROUP BY (cr=52997832 pr=21720 pw=10311 time=430015729 us)
199471 VIEW (cr=52997832 pr=21720 pw=10311 time=423392346 us)
199471 HASH GROUP BY (cr=52997832 pr=21720 pw=10311 time=423192867 us)
4013304 TABLE ACCESS BY INDEX ROWID CI_FT (cr=52997832 pr=11409 pw=0 time=140469508 us)
17717785 NESTED LOOPS (cr=49295470 pr=8987 pw=0 time=407554071 us)
13704480 NESTED LOOPS (cr=21818135 pr=7655 pw=0 time=287797921 us)
2782119 NESTED LOOPS OUTER (cr=3915432 pr=2950 pw=0 time=38953485 us)
571492 NESTED LOOPS OUTER (cr=2545763 pr=2711 pw=0 time=7433194 us)
286061 NESTED LOOPS OUTER (cr=2253263 pr=2671 pw=0 time=26607373 us)
123411 NESTED LOOPS (cr=1989056 pr=2642 pw=0 time=22711194 us)
123411 NESTED LOOPS (cr=1864959 pr=2642 pw=0 time=20860026 us)
123411 NESTED LOOPS (cr=1494040 pr=1754 pw=0 time=15553373 us)
243088 NESTED LOOPS (cr=29540 pr=1754 pw=0 time=10213331 us)
13227 TABLE ACCESS FULL CI_PER (cr=251 pr=49 pw=0 time=43331 us)
243088 INDEX RANGE SCAN XM150S1 (cr=29289 pr=1705 pw=0 time=6178159 us)(object id 97173)
123411 INLIST ITERATOR (cr=1464500 pr=0 pw=0 time=7220251 us)
123411 INDEX RANGE SCAN CM064S0 (cr=1464500 pr=0 pw=0 time=5631936 us)(object id 108631)
123411 TABLE ACCESS BY INDEX ROWID CI_ACCT (cr=370919 pr=888 pw=0 time=7241286 us)
123411 INDEX UNIQUE SCAN XM148P0 (cr=247508 pr=0 pw=0 time=1198649 us)(object id 97147)
123411 TABLE ACCESS BY INDEX ROWID CI_CUST_CL_L (cr=124097 pr=0 pw=0 time=1391837 us)
123411 INDEX UNIQUE SCAN XC523P0 (cr=686 pr=0 pw=0 time=595005 us)(object id 97745)
283749 TABLE ACCESS BY INDEX ROWID CI_PER_PHONE (cr=264207 pr=29 pw=0 time=3549713 us)
283749 INDEX RANGE SCAN XM172P0 (cr=125886 pr=4 pw=0 time=1307395 us)(object id 98733)
571492 INDEX RANGE SCAN XM171S2 (cr=292500 pr=40 pw=0 time=2976807 us)(object id 98728)
2777066 TABLE ACCESS BY INDEX ROWID CI_PER_CHAR (cr=1369669 pr=239 pw=0 time=23084761 us)
2777066 INDEX RANGE SCAN XM168P0 (cr=596156 pr=53 pw=0 time=7394319 us)(object id 98719)
13704480 TABLE ACCESS BY INDEX ROWID CI_SA (cr=17902703 pr=4705 pw=0 time=163320548 us)
13704480 INDEX RANGE SCAN XM199S1 (cr=5688247 pr=104 pw=0 time=51063061 us)(object id 98973)
4013304 INDEX RANGE SCAN CM112S1 (cr=27477335 pr=1332 pw=0 time=124063022 us)(object id 116797)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 304 0.00 0.00
db file sequential read 11366 0.34 65.63
direct path write temp 1473 0.06 2.91
latch: cache buffers chains 17 0.00 0.00
db file scattered read 7 0.01 0.03
read by other session 2 0.00 0.00
direct path read temp 1473 0.03 6.85
SQL*Net message from client 304 0.02 2.74
SQL*Net more data to client 292 0.00 0.00
********************************************************************************Luckys
I've just realised that I mis-read part of your plan:
199471 HASH GROUP BY (cr=52997832 pr=21720 pw=10311 time=423192867 us)
4013304 TABLE ACCESS BY INDEX ROWID CI_FT (cr=52997832 pr=11409 pw=0 time=140469508 us)
17717785 NESTED LOOPS (cr=49295470 pr=8987 pw=0 time=407554071 us)The time component for a line is the time it supplies, plus the sum of the time from its direct descendents.
In this case I looked at the HASH GROUP BY and TABLE ACCESS and got a difference of about 283 seconds. In fact I should have taken more notice of the other lines in the plan - comparing the HASH GROUP BY with the NESTED LOOP for a difference of about 16 seconds and assuming that the time in the TABLE ACCESS line was not to be trusted. (See http://jonathanlewis.wordpress.com/2007/04/26/heisenberg/ for a couple of comments on the timing issue).
So the grouping is responsible for relatively little of the excess time - most of the time goes into the nested loop.
I shall be using the Hints as advised, when we say we
have to "rewrite the query"
given the current context excluding the HINTS, what
exactly should I be
considering in terms of query rewrite, what
additional intelligence I can add to the
query in question so that CBO produces a different
plan.
The main consideration is what the query is supposed to report. Compare this with the way the optimizer is running the query and see if it makes sense.
When are talking about high intermediate rows
processing are we referring to this
section of the plan?;
4013304 TABLE ACCESS BY INDEX ROWID CI_FT
(cr=52997832 pr=11409 pw=0 time=140469508 us)
17717785 NESTED LOOPS (cr=49295470 pr=8987
pw=0 time=407554071 us)
13704480 NESTED LOOPS (cr=21818135 pr=7655
pw=0 time=287797921 us)
2782119 NESTED LOOPS OUTER (cr=3915432
pr=2950 pw=0 time=38953485 us)
2777066 TABLE ACCESS BY INDEX ROWID
CI_PER_CHAR (cr=1369669 pr=239 pw=0 time=23084761
us)
2777066 INDEX RANGE SCAN XM168P0 (cr=596156
pr=53 pw=0 time=7394319 us)(object id 98719)
13704480 TABLE ACCESS BY INDEX ROWID CI_SA
(cr=17902703 pr=4705 pw=0 time=163320548 us)
13704480 INDEX RANGE SCAN XM199S1
(cr=5688247 pr=104 pw=0 time=51063061 us)(object id
98973)
4013304 INDEX RANGE SCAN CM112S1 (cr=27477335
pr=1332 pw=0 time=124063022 us)(object id 116797)
Correct - one of the nested loops returns 2.78M rows - but as you run the next join you end up collecting 13.7M entires from the next index and table. That step is responsible for quite a lot of your work and time (as is the following step where you USE the 13.7M rows to probe the next index/table combination). If the optimizer had not grown the data set by merging the P view earlier on, the data sizes would be significantly smaller at that point.
Your inline view looks as if it is trying to turn rows into columns (the max(decode()) trick) - which is why I think it might be a good idea to stop Oracle from merging the view. So, as I suggested, look at the query withouth that bit of complexity and work out a sensible way to walk through the tables - bearing in mind the statistics below and the available indexes, and the amount of data your predicates identify at each stage.
Moreover tables have been analyzed:
CI_ACCT 243068
CI_ACCT_CHAR 222320
CI_ACCT_PER 242971
CI_FT 794510
CI_PER 13227
CI_PER_CHAR 42555
CI_PER_PHONE 18488
CI_SA 1082301
Parameters:
optimizer_features_enable string 10.2.0.2
optimizer_index_caching integer 100
optimizer_index_cost_adj integer 1
Unless you've been given strict instructions by a 3rd-part supplier, those settings for the optimizer_index_caching and optimizer_index_cost_adj are particularly bad - especially in 10g. With those settings, the optimizer is quite likely to choose stupid plans with excessive use of indexes - and pick the wrong index while doing it.
It's not appropriate to fiddle with system parameters to address one query - but at some stage you need to rethink your entire set of parameter settings to do things the 10g way. See this note from the Optimizer Group: http://www.oracle.com/technology/products/bi/db/10g/pdf/twp_bidw_optimizer_10gr2_0208.pdf
Regards
Jonathan Lewis
http://jonathanlewis.wordpress.com
http://www.jlcomp.demon.co.uk
"The greatest enemy of knowledge is not ignorance,
it is the illusion of knowledge." Stephen Hawking.
Maybe you are looking for
-
How can I get an SD version of a movie that was a digital copy from a Blu-Ray purchase?
I have several Disney Blu-Rays that came with digital copies. I followed the instructions for linking a Disney Movies Anywhere account with iTunes, and redeemed the codes. The movies show up on my "Purchased" page in iTunes, but only as an HD vers
-
Backing up iTunes Library to New External Hard Drive
I need to move the location of my itunes library as my external hard drive has become full. I have been backing up my "computer" (i.e. internal hard drive) and the itunes library stored on the external hard drive with TM. Once I move the library, I w
-
Load Multiple Tables (schemas) from same XML file
Hi, This is first time i am working XML files. I have one XML file with two tables (schema). I need to load those two tables into two different Target tables. This is the startegy to choose tables. <Entry type="full"> --Table 1 <Entry type="short">--
-
Mail not send my e-mail. Error inside!
"Error This message could not be delivered and will remain in your Outbox until it can be delivered. The connection to the server "smtp.mac.com" on port 25 timed out." Thats what happens, how do I fix it. Right now I'm on trial membership if that has
-
I need to play iMovie on dvd player
I've created my movie on iMovie, saved it to disc. When I put it in a DVD player, it wouldn't play. What else do I need to do?