15 April, 2011

Standby Databases (aka "DataGuard") -1

(before I return to my series on Deterministic functions ........... )


UPDATE March 2017:  See my new series on SingleInstance DataGuard for RAC, beginning here.

This week I have had two sets of questions about standby databases -- what a coincidence ! The last time I really worked with a Standby was in 8.1.7 -- without the DataGuard "backport" from 9i. (and, before that, in 7.0). All of a sudden, I have had questions about 10g and 11 DG.

Anyways, since I had started "exploring" 11.2 DG (skipping over 9i and 10g) a few days ago, and had setup a DG environment in my VM, here are some entries from the Standby's alert.log :
Fri Apr 15 22:32:52 2011
RFS[12]: Assigned to RFS process 3778
RFS[12]: Identified database type as 'physical standby': Client is LGWR SYNC pid 2576
Primary database is in MAXIMUM AVAILABILITY mode
Standby controlfile consistent with primary
Standby controlfile consistent with primary
RFS[12]: No standby redo logfiles selected (reason:7)
Errors in file /home/oracle/app/oracle/diag/rdbms/stdby/stdby/trace/stdby_rfs_3778.trc:
ORA-16086: Redo data cannot be written to the standby redo log
Fri Apr 15 22:33:14 2011
RFS[13]: Assigned to RFS process 3790
RFS[13]: Identified database type as 'physical standby': Client is ARCH pid 2658
Fri Apr 15 22:33:34 2011
RFS[14]: Assigned to RFS process 3792
RFS[14]: Identified database type as 'physical standby': Client is ARCH pid 2645
RFS[14]: Opened log for thread 1 sequence 30 dbid 159971472 branch 748133139
Archived Log entry 24 added for thread 1 sequence 30 rlc 748133139 ID 0x988c490 dest 2:
Fri Apr 15 22:33:54 2011
RFS[15]: Assigned to RFS process 3794
RFS[15]: Identified database type as 'physical standby': Client is ARCH pid 2658
Fri Apr 15 22:34:20 2011
RFS[16]: Assigned to RFS process 3806
RFS[16]: Identified database type as 'physical standby': Client is LGWR SYNC pid 2576
Primary database is in MAXIMUM AVAILABILITY mode
Standby controlfile consistent with primary
Standby controlfile consistent with primary
RFS[16]: No standby redo logfiles selected (reason:7)
Errors in file /home/oracle/app/oracle/diag/rdbms/stdby/stdby/trace/stdby_rfs_3806.trc:
ORA-16086: Redo data cannot be written to the standby redo log
Fri Apr 15 22:34:41 2011
RFS[17]: Assigned to RFS process 3810
RFS[17]: Identified database type as 'physical standby': Client is ARCH pid 2658 

For the present, I am ignoring the ORA-16086 "errors" -- because I haven't followed the "advice" to create Standby Redo Logs (why make things too complicated, eh ?).

Here's what I have on my Primary :
SQL> select dest_id, max(sequence#) from v$archived_log group by dest_id;

   DEST_ID MAX(SEQUENCE#)
---------- --------------
         1             32
         2             32

SQL>
SQL> select * from v$archive_gap;

no rows selected

SQL>   

That looks fine to me. Right ? No Gap.

I am also ignoring these errors on my Standby (heh ! this is a "play and learn" environment !)
Fatal NI connect error 12537, connecting to:
 (LOCAL=NO)

  VERSION INFORMATION:
        TNS for Linux: Version 11.2.0.1.0 - Production
        Oracle Bequeath NT Protocol Adapter for Linux: Version 11.2.0.1.0 - Production
        TCP/IP NT Protocol Adapter for Linux: Version 11.2.0.1.0 - Production
  Time: 15-APR-2011 22:39:14
  Tracing not turned on.
  Tns error struct:
    ns main err code: 12537
    
TNS-12537: TNS:connection closed
    ns secondary err code: 12560
    nt main err code: 0
    nt secondary err code: 0
    nt OS err code: 0
opiodr aborting process unknown ospid (3905) as a result of ORA-609 



What is the point of this blog post ? ......... All in due course.

.
.
.
.
.
.
.



Next, I shutdown my primary :
SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> 


While the primary shutdown is proceeding, it "flags" these errors :
Fri Apr 15 22:39:35 2011
ARC3: Archival disabled due to shutdown: 1014
Shutting down archive processes
Archiving is disabled
Archive process shutdown avoided: 0 active
Errors in file /home/oracle/app/oracle/diag/rdbms/prod/prod/trace/prod_arc3_2660.trc:
ORA-01014: ORACLE shutdown in progress
Errors in file /home/oracle/app/oracle/diag/rdbms/prod/prod/trace/prod_arc3_2660.trc:
ORA-01014: ORACLE shutdown in progress
Errors in file /home/oracle/app/oracle/diag/rdbms/prod/prod/trace/prod_arc3_2660.trc:
ORA-01014: ORACLE shutdown in progress
Errors in file /home/oracle/app/oracle/diag/rdbms/prod/prod/trace/prod_arc3_2660.trc:
ORA-01014: ORACLE shutdown in progress
Errors in file /home/oracle/app/oracle/diag/rdbms/prod/prod/trace/prod_arc3_2660.trc:
ORA-01014: ORACLE shutdown in progress
Errors in file /home/oracle/app/oracle/diag/rdbms/prod/prod/trace/prod_arc3_2660.trc:
ORA-01014: ORACLE shutdown in progress
Master background archival failure: 1014
ARCH shutting down
ARC3: Archival stopped 


I then re-start the primary and, in due course, see these messages in the primary alert.log :
Fri Apr 15 22:44:05 2011
ARC0 started with pid=21, OS id=4137 
ARC0: Archival started
LGWR: STARTING ARCH PROCESSES COMPLETE
ARC0: STARTING ARCH PROCESSES
LGWR: Primary database is in MAXIMUM AVAILABILITY mode
LGWR: Destination LOG_ARCHIVE_DEST_1 is not serviced by LGWR
Fri Apr 15 22:44:06 2011
ARC2 started with pid=20, OS id=4150 
Fri Apr 15 22:44:06 2011
ARC3 started with pid=23, OS id=4152 
Fri Apr 15 22:44:06 2011
ARC1 started with pid=22, OS id=4148 
Fri Apr 15 22:44:07 2011
NSS2 started with pid=24, OS id=4156 
ARC1: Archival started
ARC2: Archival started
ARC3: Archival started
ARC0: STARTING ARCH PROCESSES COMPLETE
ARC0: Becoming the 'no FAL' ARCH
ARC0: Becoming the 'no SRL' ARCH
ARC1: Becoming the heartbeat ARCH 
Fri Apr 15 22:44:36 2011
ORA-16198: LGWR received timedout error from KSR
Errors in file /home/oracle/app/oracle/diag/rdbms/prod/prod/trace/prod_lgwr_4066.trc:
ORA-16198: Timeout incurred on internal channel during remote archival
LGWR: Error 16198 verifying archivelog destination LOG_ARCHIVE_DEST_2
Destination LOG_ARCHIVE_DEST_2 is UNSYNCHRONIZED
LGWR: Continuing...
Thread 1 advanced to log sequence 36 (thread open)
Thread 1 opened at log sequence 36
  Current log# 3 seq# 36 mem# 0: /addtl/oracle/oradata/PROD/onlinelog/o1_mf_3_6t3jnv7s_.log
  Current log# 3 seq# 36 mem# 1: /addtl/oracle/flash_recovery_area/PROD/onlinelog/o1_mf_3_6t3jnxcg_.log
Successful open of redo thread 1 


I then :
SQL> alter system switch logfile;

System altered.

SQL>  

and see :
Fri Apr 15 22:45:38 2011
NSS2 started with pid=29, OS id=4225 
Fri Apr 15 22:46:07 2011
ORA-16198: LGWR received timedout error from KSR
Errors in file /home/oracle/app/oracle/diag/rdbms/prod/prod/trace/prod_lgwr_4066.trc:
ORA-16198: Timeout incurred on internal channel during remote archival
Error 16198 for archive log file 1 to 'stdby'
LGWR: Failed to archive log 1 thread 1 sequence 37 (16198)
Thread 1 advanced to log sequence 37 (LGWR switch)
  Current log# 1 seq# 37 mem# 0: /addtl/oracle/oradata/PROD/onlinelog/o1_mf_1_6t3jnm57_.log
  Current log# 1 seq# 37 mem# 1: /addtl/oracle/flash_recovery_area/PROD/onlinelog/o1_mf_1_6t3jnn4d_.log
Fri Apr 15 22:46:13 2011
Archived Log entry 56 added for thread 1 sequence 36 ID 0x988c490 dest 1: 


Soon, I will learn how to perform "maintenance" on the primary with the standby shutdown.

.
.

Returning to this thread ....
I perform recovery on the standby :
SQL> shutdown
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount
ORACLE instance started.

Total System Global Area  836976640 bytes
Fixed Size                  1339740 bytes
Variable Size             494931620 bytes
Database Buffers          335544320 bytes
Redo Buffers                5160960 bytes
Database mounted.
SQL> !pwd
/home/oracle/app/oracle/diag/rdbms/stdby/stdby/trace

SQL> recover automatic standby database;
ORA-00279: change 857509 generated at 04/15/2011 22:47:47 needed for thread 1
ORA-00289: suggestion :
/addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_38_%u_.arc
ORA-00280: change 857509 for thread 1 is in sequence #38
ORA-00278: log file
'/addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_38_%u_.ar
c' no longer needed for this recovery
ORA-00308: cannot open archived log
'/addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_38_%u_.ar
c'
ORA-27037: unable to obtain file status
Linux Error: 2: No such file or directory
Additional information: 3


Specify log: {=suggested | filename | AUTO | CANCEL} 


and monitor it from the stdby alert.log :
Fri Apr 15 22:52:11 2011
ALTER DATABASE RECOVER  automatic standby database  
Media Recovery Start
Serial Media Recovery started
Managed Standby Recovery not using Real Time Apply
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_11/o1_mf_1_10_6t66l9o7_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_11/o1_mf_1_11_6t66kp40_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_11/o1_mf_1_12_6t66nrbs_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_11/o1_mf_1_13_6t66htwv_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_11/o1_mf_1_14_6t66pmn5_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_11/o1_mf_1_15_6t66odb9_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_11/o1_mf_1_16_6t66tj5m_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_11/o1_mf_1_17_6t66svwc_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_11/o1_mf_1_18_6t678fyd_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_11/o1_mf_1_19_6t67cbgg_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_11/o1_mf_1_20_6t67bq2d_.arc
Fri Apr 15 22:52:21 2011
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_11/o1_mf_1_21_6t67ftgj_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_11/o1_mf_1_22_6t687w1g_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_11/o1_mf_1_23_6t687w19_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_11/o1_mf_1_24_6t688qdf_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_11/o1_mf_1_25_6t689byn_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_26_6tjol0jr_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_27_6tjokddr_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_28_6tjonl8w_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_29_6tjoq9v5_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_30_6tjosydp_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_31_6tjowowv_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_32_6tjoyvg2_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_33_6tjp21o3_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_34_6tjpppjj_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_35_6tjpopc6_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_36_6tjpqch2_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_37_6tjprmmt_.arc
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_38_%u_.arc
Errors with log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_15/o1_mf_1_38_%u_.arc
ORA-279 signalled during: ALTER DATABASE RECOVER  automatic standby database  ... 


So far so good .....

.
.
.
Updates to this "voyage of discovery" to follow ....

.
.
UPDATE : Adding a Standby Redo Log on the Standby :
SQL> recover managed standby database disconnect from session;
Media recovery complete.
SQL> recover managed standby database cancel;
Media recovery complete.
SQL> select group#, status, bytes/1048576 from v$log;

    GROUP# STATUS           BYTES/1048576
---------- ---------------- -------------
         1 CLEARING_CURRENT            50
         3 CLEARING                    50
         2 CLEARING                    50

SQL> select group#, status, bytes/1048576 from v$standby_log;

no rows selected

SQL> alter database add standby logfile size 50M;

Database altered.

SQL> select group#, status, bytes/1048576 from v$standby_log;

    GROUP# STATUS     BYTES/1048576
---------- ---------- -------------
         4 UNASSIGNED            50

SQL> recover managed standby database disconnect from session;
Media recovery complete.
SQL> 


following which the messages are :
Sat Apr 16 13:16:16 2011
ALTER DATABASE RECOVER  managed standby database disconnect from session  
Attempt to start background Managed Standby Recovery process (stdby)
Sat Apr 16 13:16:16 2011
MRP0 started with pid=27, OS id=4392 
MRP0: Background Managed Standby Recovery process started (stdby)
Serial Media Recovery started
Managed Standby Recovery not using Real Time Apply
Waiting for all non-current ORLs to be archived...
All non-current ORLs have been archived.
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_16/o1_mf_1_74_6tl9j689_.arc
Media Recovery Waiting for thread 1 sequence 75
Completed: ALTER DATABASE RECOVER  managed standby database disconnect from session  
Sat Apr 16 13:16:34 2011
ALTER DATABASE RECOVER  managed standby database cancel  
Sat Apr 16 13:16:35 2011
MRP0: Background Media Recovery cancelled with status 16037
Errors in file /home/oracle/app/oracle/diag/rdbms/stdby/stdby/trace/stdby_mrp0_4392.trc:
ORA-16037: user requested cancel of managed recovery operation
Recovery interrupted!
Errors in file /home/oracle/app/oracle/diag/rdbms/stdby/stdby/trace/stdby_mrp0_4392.trc:
ORA-16037: user requested cancel of managed recovery operation
MRP0: Background Media Recovery process shutdown (stdby)
Waiting for MRP0 pid 4392 to terminate
Managed Standby Recovery Canceled (stdby)
Completed: ALTER DATABASE RECOVER  managed standby database cancel  
Sat Apr 16 13:16:40 2011
RFS[94]: Assigned to RFS process 4394
RFS[94]: Identified database type as 'physical standby': Client is LGWR SYNC pid 3274
Primary database is in MAXIMUM AVAILABILITY mode
Standby controlfile consistent with primary
Standby controlfile consistent with primary
RFS[94]: No standby redo logfiles selected (reason:7)
Errors in file /home/oracle/app/oracle/diag/rdbms/stdby/stdby/trace/stdby_rfs_4394.trc:
ORA-16086: Redo data cannot be written to the standby redo log
Sat Apr 16 13:17:02 2011
RFS[95]: Assigned to RFS process 4415
RFS[95]: Identified database type as 'physical standby': Client is ARCH pid 3349
Sat Apr 16 13:17:22 2011
RFS[96]: Assigned to RFS process 4417
RFS[96]: Identified database type as 'physical standby': Client is ARCH pid 3363
RFS[96]: Opened log for thread 1 sequence 75 dbid 159971472 branch 748133139
Archived Log entry 69 added for thread 1 sequence 75 rlc 748133139 ID 0x988c490 dest 2:
Sat Apr 16 13:17:39 2011
alter database add standby logfile size 50M
Completed: alter database add standby logfile size 50M
Sat Apr 16 13:17:42 2011
RFS[97]: Assigned to RFS process 4421
RFS[97]: Identified database type as 'physical standby': Client is ARCH pid 3349
Sat Apr 16 13:18:03 2011
ALTER DATABASE RECOVER  managed standby database disconnect from session  
Attempt to start background Managed Standby Recovery process (stdby)
Sat Apr 16 13:18:03 2011
MRP0 started with pid=28, OS id=4433 
MRP0: Background Managed Standby Recovery process started (stdby)
Sat Apr 16 13:18:08 2011
RFS[98]: Assigned to RFS process 4431
RFS[98]: Identified database type as 'physical standby': Client is LGWR SYNC pid 3274
Primary database is in MAXIMUM AVAILABILITY mode
Standby controlfile consistent with primary
Standby controlfile consistent with primary
RFS[98]: Selected log 4 for thread 1 sequence 77 dbid 159971472 branch 748133139
Serial Media Recovery started
Managed Standby Recovery not using Real Time Apply
Waiting for all non-current ORLs to be archived...
All non-current ORLs have been archived.
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_16/o1_mf_1_75_6tl9m2fl_.arc
Media Recovery Waiting for thread 1 sequence 76
Completed: ALTER DATABASE RECOVER  managed standby database disconnect from session  
Sat Apr 16 13:18:29 2011
RFS[99]: Assigned to RFS process 4435
RFS[99]: Identified database type as 'physical standby': Client is ARCH pid 3363
RFS[99]: No standby redo logfiles of size 81 blocks available
RFS[99]: Opened log for thread 1 sequence 76 dbid 159971472 branch 748133139
Archived Log entry 70 added for thread 1 sequence 76 rlc 748133139 ID 0x988c490 dest 2:
Sat Apr 16 13:18:34 2011
Media Recovery Log /addtl/oracle/flash_recovery_area/STDBY/archivelog/2011_04_16/o1_mf_1_76_6tl9o5bb_.arc
Media Recovery Waiting for thread 1 sequence 77 (in transit) 



So, now my Standby Database does have a Standby Redo Log.
Note : I was able to work without a Standby Redo Log but I had almost no transactions generating Redo.

.
.
.

10 April, 2011

DETERMINISTIC Functions -- 2

Following up on my previous post, I now take up a Deterministic Function defined on a date column.

First, I setup the test data :


SQL> create or replace function ten_days_ago_date(date_in date) return date     DETERMINISTIC
2 as
3 deducted_date date;
4 begin
5 select date_in - 10 into deducted_date from dual;
6 return deducted_date;
7 end;
8 /

Function created.

SQL>
SQL>
SQL> drop table my_objects purge;

Table dropped.

SQL>
SQL> create table my_objects (obj_id number , obj_name varchar2(30), created date);

Table created.

SQL>

SQL> insert into my_objects
2 select object_id, object_name,created
3 from dba_objects
4 where owner in ('HEMANT','SCOTT')
5 /

19 rows created.

SQL>
I now have 19 rows and will be applying a DETERMINISTIC function to the date column "created" when I query the table.



SQL> exec dbms_session.session_trace_enable;

PL/SQL procedure successfully completed.

SQL> select obj_id, created, ten_days_ago_date(created)
2 from my_objects
3 order by created
4 /

OBJ_ID CREATED TEN_DAYS_
---------- --------- ---------
73180 13-AUG-09 03-AUG-09
73179 13-AUG-09 03-AUG-09
73181 13-AUG-09 03-AUG-09
73182 13-AUG-09 03-AUG-09
73183 13-AUG-09 03-AUG-09
73184 13-AUG-09 03-AUG-09
82749 06-JUL-10 26-JUN-10
82748 06-JUL-10 26-JUN-10
82751 06-JUL-10 26-JUN-10
85339 14-OCT-10 04-OCT-10
85340 14-OCT-10 04-OCT-10
85341 14-OCT-10 04-OCT-10
85344 05-FEB-11 26-JAN-11
85346 05-FEB-11 26-JAN-11
85429 05-APR-11 26-MAR-11
85434 09-APR-11 30-MAR-11
85439 09-APR-11 30-MAR-11
85444 09-APR-11 30-MAR-11
85451 09-APR-11 30-MAR-11

19 rows selected.

SQL> exec dbms_session.session_trace_disable;

PL/SQL procedure successfully completed.

SQL>
I have 6 rows with the date '13-AUG-09', 3 of '06-JUL-10', 3 of '14-OCT-10', 3 of '05-FEB-11' and 4 of '09-APR-11'.

Let's see what the tkprof show :
select obj_id, created, ten_days_ago_date(created)
from my_objects
order by created

call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.02 0.23 0 1 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 3 0.01 0.02 0 7 0 19
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 5 0.04 0.25 0 8 0 19

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 184

Rows Row Source Operation
------- ---------------------------------------------------
19 SORT ORDER BY (cr=7 pr=0 pw=0 time=0 us cost=4 size=418 card=19)
19 TABLE ACCESS FULL MY_OBJECTS (cr=7 pr=0 pw=0 time=576 us cost=3 size=418 card=19)


SQL ID: 7dq8qm13md0cf
Plan Hash: 1388734953
SELECT :B1 - 10
FROM
DUAL


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 12 0.00 0.00 0 0 0 0
Fetch 12 0.00 0.00 0 0 0 12
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 25 0.00 0.00 0 0 0 12

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 184 (recursive depth: 1)

Rows Row Source Operation
------- ---------------------------------------------------
1 FAST DUAL (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)

There are 19 rows with 5 distinct dates but the function was executed 12 times ! Isn't there a mismatch ? Should the function have been executed 19 times or 5 times ?

.
.
.









But wait ..... a DATE datatype in Oracle captures Hours:Minutes:Seconds besides Day:Month:Year. Therefore, two rows with the "Date" '09-APR-11' may not necessarily have really the same Date Value stored in the database !

I rerun the query but also print the Hours:Minutes:Seconds and capture the Binds in the trace file.
SQL> exec dbms_session.session_trace_enable(waits=>TRUE, binds=>TRUE);

PL/SQL procedure successfully completed.

SQL> select obj_id, created, ten_days_ago_date(created), to_char(created,'DD-MON-RR HH24:MI:SS')
2 from my_objects
3 order by created
4 /


OBJ_ID CREATED TEN_DAYS_ TO_CHAR(CREATED,'DD-MON-RRH
---------- --------- --------- ---------------------------
73180 13-AUG-09 03-AUG-09 13-AUG-09 23:35:45
73179 13-AUG-09 03-AUG-09 13-AUG-09 23:35:45
73181 13-AUG-09 03-AUG-09 13-AUG-09 23:35:45
73182 13-AUG-09 03-AUG-09 13-AUG-09 23:35:45
73183 13-AUG-09 03-AUG-09 13-AUG-09 23:35:45
73184 13-AUG-09 03-AUG-09 13-AUG-09 23:35:45
82749 06-JUL-10 26-JUN-10 06-JUL-10 14:28:11
82748 06-JUL-10 26-JUN-10 06-JUL-10 14:28:11
82751 06-JUL-10 26-JUN-10 06-JUL-10 14:28:11
85339 14-OCT-10 04-OCT-10 14-OCT-10 01:27:25
85340 14-OCT-10 04-OCT-10 14-OCT-10 01:40:57
85341 14-OCT-10 04-OCT-10 14-OCT-10 02:18:35
85344 05-FEB-11 26-JAN-11 05-FEB-11 08:04:52
85346 05-FEB-11 26-JAN-11 05-FEB-11 08:18:05
85429 05-APR-11 26-MAR-11 05-APR-11 07:43:23
85434 09-APR-11 30-MAR-11 09-APR-11 08:12:42
85439 09-APR-11 30-MAR-11 09-APR-11 08:39:13
85444 09-APR-11 30-MAR-11 09-APR-11 21:28:01
85451 09-APR-11 30-MAR-11 09-APR-11 21:58:17

19 rows selected.

SQL> exec dbms_session.session_trace_disable;

PL/SQL procedure successfully completed.

SQL>


Here's the tkprof output :
SQL ID: 7dq8qm13md0cf
Plan Hash: 1388734953
SELECT :B1 - 10
FROM
DUAL


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 12 0.00 0.00 0 0 0 0
Fetch 12 0.00 0.00 0 0 0 12
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 25 0.00 0.00 0 0 0 12

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 184 (recursive depth: 1)

Rows Row Source Operation
------- ---------------------------------------------------
1 FAST DUAL (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)


If I look at the raw trace file, however, I can find the points of execution :
=====================
PARSING IN CURSOR #2 len=25 dep=1 uid=184 oct=3 lid=184 tim=1302411557311398 hv=1194754446 ad='2d7c4228' sqlid='7dq8qm13md0cf'
SELECT :B1 - 10 FROM DUAL
END OF STMT
PARSE #2:c=0,e=309,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1388734953,tim=1302411557311362
BINDS #2:
Bind#0
oacdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=206001 frm=00 csi=00 siz=8 off=0
kxsbbbfp=006a49a8 bln=07 avl=07 flg=09
value="8/13/2009 23:35:45"
EXEC #2:c=0,e=554,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1388734953,tim=1302411557312312
FETCH #2:c=1000,e=369,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=1,plh=1388734953,tim=1302411557312847
STAT #2 id=1 cnt=1 pid=0 pos=1 obj=0 op='FAST DUAL (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
CLOSE #2:c=0,e=32,dep=1,type=3,tim=1302411557313358

=====================
PARSING IN CURSOR #2 len=25 dep=1 uid=184 oct=3 lid=184 tim=1302411557314018 hv=1194754446 ad='2d7c4228' sqlid='7dq8qm13md0cf'
SELECT :B1 - 10 FROM DUAL
END OF STMT
BINDS #2:
Bind#0
oacdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=206001 frm=00 csi=00 siz=8 off=0
kxsbbbfp=006a49a8 bln=07 avl=07 flg=09
value="7/6/2010 14:28:11"
EXEC #2:c=0,e=467,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1388734953,tim=1302411557314344
FETCH #2:c=0,e=223,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=1,plh=1388734953,tim=1302411557314745
CLOSE #2:c=0,e=9,dep=1,type=3,tim=1302411557314880

=====================
PARSING IN CURSOR #2 len=25 dep=1 uid=184 oct=3 lid=184 tim=1302411557315047 hv=1194754446 ad='2d7c4228' sqlid='7dq8qm13md0cf'
SELECT :B1 - 10 FROM DUAL
END OF STMT
BINDS #2:
Bind#0
oacdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=206001 frm=00 csi=00 siz=8 off=0
kxsbbbfp=006a49a8 bln=07 avl=07 flg=09
value="10/14/2010 1:27:25"
EXEC #2:c=0,e=349,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1388734953,tim=1302411557315361
FETCH #2:c=0,e=35,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=1,plh=1388734953,tim=1302411557315478
CLOSE #2:c=0,e=13,dep=1,type=3,tim=1302411557315639

=====================
PARSING IN CURSOR #2 len=25 dep=1 uid=184 oct=3 lid=184 tim=1302411557315868 hv=1194754446 ad='2d7c4228' sqlid='7dq8qm13md0cf'
SELECT :B1 - 10 FROM DUAL
END OF STMT
BINDS #2:
Bind#0
oacdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=206001 frm=00 csi=00 siz=8 off=0
kxsbbbfp=006a49a8 bln=07 avl=07 flg=09
value="10/14/2010 1:40:57"
EXEC #2:c=0,e=331,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1388734953,tim=1302411557316162
FETCH #2:c=0,e=132,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=1,plh=1388734953,tim=1302411557316371
CLOSE #2:c=0,e=8,dep=1,type=3,tim=1302411557316486

=====================
PARSING IN CURSOR #2 len=25 dep=1 uid=184 oct=3 lid=184 tim=1302411557316780 hv=1194754446 ad='2d7c4228' sqlid='7dq8qm13md0cf'
SELECT :B1 - 10 FROM DUAL
END OF STMT
BINDS #2:
Bind#0
oacdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=206001 frm=00 csi=00 siz=8 off=0
kxsbbbfp=006a49a8 bln=07 avl=07 flg=09
value="10/14/2010 2:18:35"
EXEC #2:c=0,e=360,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1388734953,tim=1302411557317077
FETCH #2:c=0,e=37,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=1,plh=1388734953,tim=1302411557317208
CLOSE #2:c=0,e=7,dep=1,type=3,tim=1302411557317284

=====================
PARSING IN CURSOR #2 len=25 dep=1 uid=184 oct=3 lid=184 tim=1302411557317405 hv=1194754446 ad='2d7c4228' sqlid='7dq8qm13md0cf'
SELECT :B1 - 10 FROM DUAL
END OF STMT
BINDS #2:
Bind#0
oacdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=206001 frm=00 csi=00 siz=8 off=0
kxsbbbfp=006a49a8 bln=07 avl=07 flg=09
value="2/5/2011 8:4:52"
EXEC #2:c=1999,e=1239,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1388734953,tim=1302411557318621
FETCH #2:c=0,e=229,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=1,plh=1388734953,tim=1302411557318947
CLOSE #2:c=0,e=8,dep=1,type=3,tim=1302411557319086

=====================
PARSING IN CURSOR #2 len=25 dep=1 uid=184 oct=3 lid=184 tim=1302411557319365 hv=1194754446 ad='2d7c4228' sqlid='7dq8qm13md0cf'
SELECT :B1 - 10 FROM DUAL
END OF STMT
BINDS #2:
Bind#0
oacdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=206001 frm=00 csi=00 siz=8 off=0
kxsbbbfp=006a49a8 bln=07 avl=07 flg=09
value="2/5/2011 8:18:5"
EXEC #2:c=1000,e=323,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1388734953,tim=1302411557319637
FETCH #2:c=0,e=216,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=1,plh=1388734953,tim=1302411557320053
CLOSE #2:c=0,e=31,dep=1,type=3,tim=1302411557320250

=====================
PARSING IN CURSOR #2 len=25 dep=1 uid=184 oct=3 lid=184 tim=1302411557321372 hv=1194754446 ad='2d7c4228' sqlid='7dq8qm13md0cf'
SELECT :B1 - 10 FROM DUAL
END OF STMT
BINDS #2:
Bind#0
oacdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=206001 frm=00 csi=00 siz=8 off=0
kxsbbbfp=006a49a8 bln=07 avl=07 flg=09
value="4/5/2011 7:43:23"
EXEC #2:c=1000,e=479,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1388734953,tim=1302411557321641
FETCH #2:c=0,e=233,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=1,plh=1388734953,tim=1302411557322107
CLOSE #2:c=0,e=32,dep=1,type=3,tim=1302411557322321
=====================
PARSING IN CURSOR #2 len=25 dep=1 uid=184 oct=3 lid=184 tim=1302411557323024 hv=1194754446 ad='2d7c4228' sqlid='7dq8qm13md0cf'
SELECT :B1 - 10 FROM DUAL
END OF STMT
BINDS #2:
Bind#0
oacdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=206001 frm=00 csi=00 siz=8 off=0
kxsbbbfp=006a49a8 bln=07 avl=07 flg=09
value="4/9/2011 21:28:1"
EXEC #2:c=0,e=264,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1388734953,tim=1302411557323236
FETCH #2:c=0,e=145,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=1,plh=1388734953,tim=1302411557323463
CLOSE #2:c=0,e=79,dep=1,type=3,tim=1302411557323718

=====================
PARSING IN CURSOR #2 len=25 dep=1 uid=184 oct=3 lid=184 tim=1302411557323946 hv=1194754446 ad='2d7c4228' sqlid='7dq8qm13md0cf'
SELECT :B1 - 10 FROM DUAL
END OF STMT
BINDS #2:
Bind#0
oacdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=206001 frm=00 csi=00 siz=8 off=0
kxsbbbfp=006a49a8 bln=07 avl=07 flg=09
value="4/9/2011 8:39:13"
EXEC #2:c=0,e=209,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1388734953,tim=1302411557324117
FETCH #2:c=0,e=35,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=1,plh=1388734953,tim=1302411557324221
CLOSE #2:c=0,e=38,dep=1,type=3,tim=1302411557324259
=====================
PARSING IN CURSOR #2 len=25 dep=1 uid=184 oct=3 lid=184 tim=1302411557324448 hv=1194754446 ad='2d7c4228' sqlid='7dq8qm13md0cf'
SELECT :B1 - 10 FROM DUAL
END OF STMT
BINDS #2:
Bind#0
oacdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=206001 frm=00 csi=00 siz=8 off=0
kxsbbbfp=006a49a8 bln=07 avl=07 flg=09
value="4/9/2011 8:12:42"
EXEC #2:c=1000,e=305,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1388734953,tim=1302411557324717
FETCH #2:c=0,e=45,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=1,plh=1388734953,tim=1302411557325018
CLOSE #2:c=0,e=8,dep=1,type=3,tim=1302411557325106

=====================
PARSING IN CURSOR #2 len=25 dep=1 uid=184 oct=3 lid=184 tim=1302411557325243 hv=1194754446 ad='2d7c4228' sqlid='7dq8qm13md0cf'
SELECT :B1 - 10 FROM DUAL
END OF STMT
BINDS #2:
Bind#0
oacdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=206001 frm=00 csi=00 siz=8 off=0
kxsbbbfp=006a49a8 bln=07 avl=07 flg=09
value="4/9/2011 21:58:17"
EXEC #2:c=0,e=201,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1388734953,tim=1302411557325415
FETCH #2:c=0,e=28,p=0,cr=0,cu=0,mis=0,r=1,dep=1,og=1,plh=1388734953,tim=1302411557325493
CLOSE #2:c=0,e=149,dep=1,type=3,tim=1302411557334524
That adds up to 12 executions. One execution afresh each time the retrieved value changes. Note : The sequence of values that appear in the trace file isn't exactly the same as that in the SQL output. The trace file shows how the function is applied to each row fetched *before* the rows are sorted. The function is applied before the ORDER BY is applied.

.
.
.

05 April, 2011

DETERMINISTIC Functions

In my opinion, DETERMINISTIC functions are not very well explained. Some DBAs and Developers know that a Function must be DETERMINISTIC if it is to be used to create a Function Based Index. Also, common understanding is that a Function can be DETERMINISTIC if it is guaranteed to return always return the same output value if the input value supplied is not changed.

Some explanation is in the documentation on the CREATE FUNCTION command.
"Indicates that the function returns the same result value whenever it is called with the same values for its parameters."

Yet, how does Oracle optimise the execution of a DETERMINISTIC function ? The documentation says "When the database encounters a deterministic function in one of these contexts, it attempts to use previously calculated results when possible rather than reexecuting the function."

Jonathan Lewis has also explored DETERMINSTIC functions here.

I decided to run my own tests here. I created a DETERMINISTIC function and had it executed once for each row in a 16-row result set :
SQL> create or replace function div_by_hundred (value_in number) return number DETERMINISTIC
2 as
3 divided_by_hundred number;
4 begin
5 select trunc(value_in/100) into divided_by_hundred from dual;
6 return divided_by_hundred;
7 end;
8 /

Function created.

SQL>
SQL>
SQL> drop table my_objects purge;

Table dropped.

SQL>
SQL> create table my_objects (obj_id number , obj_name varchar2(30), created date);

Table created.

SQL>
SQL> insert into my_objects
2 select object_id, object_name,created
3 from dba_objects
4 where owner in ('HEMANT','SCOTT')
5 /

16 rows created.

SQL>
SQL> exec dbms_session.session_trace_enable;

PL/SQL procedure successfully completed.

SQL> select obj_id, div_by_hundred(obj_id)
2 from my_objects
3 order by obj_id
4 /

OBJ_ID DIV_BY_HUNDRED(OBJ_ID)
---------- ----------------------
73179 731
73180 731
73181 731
73182 731
73183 731
73184 731
82748 827
82749 827
82751 827
85339 853
85340 853

OBJ_ID DIV_BY_HUNDRED(OBJ_ID)
---------- ----------------------
85341 853
85344 853
85346 853
85429 854
85433 854

16 rows selected.

SQL> exec dbms_session.session_trace_disable;

PL/SQL procedure successfully completed.

SQL>

The trace file shows that the function is actually executed 16 times.
select obj_id, div_by_hundred(obj_id)
from my_objects
order by obj_id

call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.02 0.04 0 1 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 3 0.01 0.01 0 7 0 16
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 5 0.03 0.06 0 8 0 16


Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 184

Rows Row Source Operation
------- ---------------------------------------------------
16 SORT ORDER BY (cr=7 pr=0 pw=0 time=0 us cost=4 size=208 card=16)
16 TABLE ACCESS FULL MY_OBJECTS (cr=7 pr=0 pw=0 time=120 us cost=3 size=208 card=16)


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.08 0.10
********************************************************************************

SQL ID: dd7zz37sxfcsc
Plan Hash: 1388734953
SELECT TRUNC(:B1 /100)
FROM
DUAL


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 16 0.00 0.00 0 0 0 0
Fetch 16 0.00 0.00 0 0 0 16
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 33 0.00 0.00 0 0 0 16

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 184 (recursive depth: 1)


Rows Row Source Operation
------- ---------------------------------------------------
1 FAST DUAL (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)

********************************************************************************

We know that every time we pass the same value to "trunc(:b1/100)", the result will always be the same. This function had to be executed 16 times because each value passed to the function was different -- each time a new OBJ_ID was being passed.

So, what happens if the same OBJ_ID is passed to the function each time ?
SQL> UPDATE my_objects set obj_id = 1000000;

16 rows updated.

SQL> commit;

Commit complete.

SQL>
SQL> pause Press ENTER to proceed with new session
Press ENTER to proceed with new session

SQL> connect hemant/hemant
Connected.
SQL>
SQL> exec dbms_session.session_trace_enable;

PL/SQL procedure successfully completed.

SQL> select obj_id, div_by_hundred(obj_id)
2 from my_objects
3 order by obj_id
4 /

OBJ_ID DIV_BY_HUNDRED(OBJ_ID)
---------- ----------------------
1000000 10000
1000000 10000
1000000 10000
1000000 10000
1000000 10000
1000000 10000
1000000 10000
1000000 10000
1000000 10000
1000000 10000
1000000 10000

OBJ_ID DIV_BY_HUNDRED(OBJ_ID)
---------- ----------------------
1000000 10000
1000000 10000
1000000 10000
1000000 10000
1000000 10000

16 rows selected.

SQL> exec dbms_session.session_trace_disable;

PL/SQL procedure successfully completed.

SQL>

This appears in the trace file :
select obj_id, div_by_hundred(obj_id)
from my_objects
order by obj_id

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 3 0.00 0.04 0 7 0 16
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 5 0.01 0.05 0 7 0 16

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 184

Rows Row Source Operation
------- ---------------------------------------------------
16 SORT ORDER BY (cr=7 pr=0 pw=0 time=0 us cost=4 size=208 card=16)
16 TABLE ACCESS FULL MY_OBJECTS (cr=7 pr=0 pw=0 time=360 us cost=3 size=208 card=16)


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
Disk file operations I/O 1 0.00 0.00
SQL*Net message from client 3 0.05 0.08
********************************************************************************

SQL ID: dd7zz37sxfcsc
Plan Hash: 1388734953
SELECT TRUNC(:B1 /100)
FROM
DUAL


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 1 0.00 0.00 0 0 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 0.00 0.00 0 0 0 1


Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 184 (recursive depth: 1)

Rows Row Source Operation
------- ---------------------------------------------------
1 FAST DUAL (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)

********************************************************************************


Now, the function is executed only once ! Apparently, Oracle actually "peeks" (for want of a better word) at the value passed to the function. If it is the same as the last value (or one of the last four values ?-- see Jonathan Lewis's last paragraph in his note), it decides to not re-execute the function. That also means, that it holds the return value from the previous execution and re-uses that value -- to be returned again for the next row.


Will this behaviour hold true with DATEs ?
Stay tuned. .......

.
.
.