How to conver columns to rows and convert rows to columns?

Convert columns to rows:
create table tr1 (name varchar2(10), cust_value_1 number,cust_value_2 number,cust_value_3 number);
insert into tr1 values(‘a’,1,1,1);
insert into tr1 values(‘b’,1,0,1);
insert into tr1 values(‘c’,0,0,1);

–transform sql
select * from (
select      name,
case when rowno=1 then cust_value_1
when rowno=2 then cust_value_2
when rowno=3 then cust_value_3
end cust_value
from tr1, (select rownum rowno  from dual connect by level <= 3)
)
order by name;

NAME       CUST_VALUE
———- ———-
a                   1
a                   1
a                   1
b                   1
b                   0
b                   1
c                   0
c                   0
c                   1

9 rows selected.


Convert rows to columns:

–1.number or varchar
–create table and insert data
create table tr2 (name varchar2(10), cust_value number);
insert into tr2
select * from (
select      name,
case when rowno=1 then cust_value_1
when rowno=2 then cust_value_2
when rowno=3 then cust_value_3
end cust_value
from tr1, (select rownum rowno  from dual connect by level <= 3)
)
order by name;
SQL> select * from tr2;

NAME       CUST_VALUE
———- ———-
a                   1
a                   1
a                   1
b                   1
b                   0
b                   1
c                   0
c                   0
c                   1
9 rows selected.

–transform sql
SELECT name,
MAX(case when seq=1 then cust_value end) AS “cust_value_1″,
MAX(case when seq=2 then cust_value end) AS “cust_value_2″,
MAX(case when seq=3 then cust_value end) AS “cust_value_3″
FROM (SELECT name, cust_value, ROW_NUMBER() over(partition by name ORDER BY name) AS seq FROM tr2)
GROUP BY name;

NAME       cust_value_1 cust_value_2 cust_value_3
———- ———— ———— ————
a                     1            1            1
b                     1            0            1
c                     0            0            1

3 rows selected.

–2.connect varchar
create table tr2v(gid number,name varchar2(10));
insert into tr2v values (1,’Alex’);
insert into tr2v values (1,’Alice’);
insert into tr2v values (1,’Angle’);
insert into tr2v values (2,’Bob’);
insert into tr2v values (2,’Bill’);
insert into tr2v values (3,’Charlie’);
SQL> select * from tr2v;

GID NAME
———- ———-
1 Alex
1 Alice
1 Angle
2 Bob
2 Bill
3 Charlie

6 rows selected.

–transform sql
select gid,substr(SYS_CONNECT_BY_PATH(name,’,'),2) group_all
from (select gid, name,
count(*) over (partition by gid) cnt,
row_number() over (partition by gid order by name) seq
from tr2v
) where cnt=seq
start with seq=1 connect by prior seq+1=seq and prior gid=gid;

GID GROUP_ALL
———- —————–
1 Alex,Alice,Angle
2 Bill,Bob
3 Charlie

3 rows selected.

How to setup Data Guard Broker and enable Fast Start Failover in 11g?

Environment: 11g, initial primary db ‘upup’, standby db ‘upup1′

Here are the major steps:

1.Setup primary db and standby db
2.using spfile instead of pfile for both standby db and primary db.
3.set DG_BROKER_START = true

4.Set parameters of data guard broker configuration files

On the server you want to setup the broker, in my case, it is the primary db server
dg_broker_config_file1 = /u01/app/oracle/product/11.1.0/db_2/dbs/dr1upup1.dat
dg_broker_config_file2 = /u01/app/oracle/product/11.1.0/db_2/dbs/dr2upup1.dat

5.static register services in listener

Configure service upup1_DGB in upup1 listener
Configure service upup_DGB in upup listener

6.Setup the broker configuration
dgmgrl
DGMGRL> connect /
create configuration my_dg as
   primary database is upup1
   connect identifier is upup1;

add database upup as
   connect identifier is upup
   maintained as physical;

enable configuration

show configuration
Configuration
  Name:                my_dg
  Enabled:             YES
  Protection Mode:     MaxPerformance
  Databases:
    upup1 – Primary database
    upup  – Physical standby database

Fast-Start Failover: DISABLED

Current status for “my_dg”:
SUCCESS

DGMGRL> show database verbose upup1

Database
  Name:            upup1
  Role:            PRIMARY
  Enabled:         YES
  Intended State:  TRANSPORT-ON
  Instance(s):
    upup

  Properties:
    DGConnectIdentifier             = ‘upup1′
    ObserverConnectIdentifier       = ”
    LogXptMode                      = ‘ASYNC’
    DelayMins                       = ‘0′
    Binding                         = ‘OPTIONAL’
    MaxFailure                      = ‘0′
    MaxConnections                  = ‘1′
    ReopenSecs                      = ‘300′
    NetTimeout                      = ‘30′
    RedoCompression                 = ‘DISABLE’
    LogShipping                     = ‘ON’
    PreferredApplyInstance          = ”
    ApplyInstanceTimeout            = ‘0′
    ApplyParallel                   = ‘AUTO’
    StandbyFileManagement           = ‘auto’
    ArchiveLagTarget                = ‘0′
    LogArchiveMaxProcesses          = ‘5′
    LogArchiveMinSucceedDest        = ‘1′
    DbFileNameConvert               = ”
    LogFileNameConvert              = ”
    FastStartFailoverTarget         = ”
    StatusReport                    = ‘(monitor)’
    InconsistentProperties          = ‘(monitor)’
    InconsistentLogXptProps         = ‘(monitor)’
    SendQEntries                    = ‘(monitor)’
    LogXptStatus                    = ‘(monitor)’
    RecvQEntries                    = ‘(monitor)’
    HostName                        = ‘rac1.baby.com’
    SidName                         = ‘upup’
    StandbyArchiveLocation          = ‘/u01/app/oracle/oradata/upup/arch/’
    AlternateLocation               = ”
    LogArchiveTrace                 = ‘0′
    LogArchiveFormat                = ‘upup_%t_%s_%r.arc’
    LatestLog                       = ‘(monitor)’
    TopWaitEvents                   = ‘(monitor)’

Current status for “upup1″:
SUCCESS

DGMGRL> show database verbose upup

Database
  Name:            upup
  Role:            PHYSICAL STANDBY
  Enabled:         YES
  Intended State:  APPLY-ON
  Instance(s):
    upup

  Properties:
    DGConnectIdentifier             = ‘upup’
    ObserverConnectIdentifier       = ”
    LogXptMode                      = ‘ASYNC’
    DelayMins                       = ‘0′
    Binding                         = ‘OPTIONAL’
    MaxFailure                      = ‘0′
    MaxConnections                  = ‘1′
    ReopenSecs                      = ‘300′
    NetTimeout                      = ‘30′
    RedoCompression                 = ‘DISABLE’
    LogShipping                     = ‘ON’
    PreferredApplyInstance          = ”
    ApplyInstanceTimeout            = ‘0′
    ApplyParallel                   = ‘AUTO’
    StandbyFileManagement           = ‘auto’
    ArchiveLagTarget                = ‘0′
    LogArchiveMaxProcesses          = ‘5′
    LogArchiveMinSucceedDest        = ‘1′
    DbFileNameConvert               = ”
    LogFileNameConvert              = ”
    FastStartFailoverTarget         = ”
    StatusReport                    = ‘(monitor)’
    InconsistentProperties          = ‘(monitor)’
    InconsistentLogXptProps         = ‘(monitor)’
    SendQEntries                    = ‘(monitor)’
    LogXptStatus                    = ‘(monitor)’
    RecvQEntries                    = ‘(monitor)’
    HostName                        = ‘rac2.baby.com’
    SidName                         = ‘upup’
    StandbyArchiveLocation          = ‘/u01/app/oracle/oradata/upup/arch/’
    AlternateLocation               = ”
    LogArchiveTrace                 = ‘0′
    LogArchiveFormat                = ‘upup_%t_%s_%r.arc’
    LatestLog                       = ‘(monitor)’
    TopWaitEvents                   = ‘(monitor)’

Current status for “upup”:
SUCCESS

6.Switchover
DGMGRL> switchover to upup
Performing switchover NOW, please wait…
New primary database “upup” is opening…
Operation requires shutdown of instance “upup” on database “upup1″
Shutting down instance “upup”…
ORA-01031: insufficient privileges

You are no longer connected to ORACLE
Please connect again.
Unable to shut down instance “upup”
You must shut down instance “upup” manually
Operation requires startup of instance “upup” on database “upup1″
You must start instance “upup” manually
Switchover succeeded, new primary is “upup”

Now upup is primary and in open status, I need to shutdown upup1 and startup mount
conn sys/oracle@upup1 as sysdba
SQL> shutdown immediate

7.Check DGMGRL status again
DGMGRL> show configuration

Configuration
  Name:                my_dg
  Enabled:             YES
  Protection Mode:     MaxPerformance
  Databases:
    upup  – Primary database
    upup1 – Physical standby database

Fast-Start Failover: DISABLED

Current status for “my_dg”:
SUCCESS

8.Setup Fast failover
–Enable flashback on both db
SQL> startup mount
SQL> alter system set db_recovery_file_dest_size=1G;
SQL> alter system set db_recovery_file_dest=’/u01/app/oracle/oradata’;

–set fast failover target
DGMGRL> EDIT DATABASE upup SET PROPERTY FastStartFailoverTarget = upup1;
DGMGRL> EDIT DATABASE upup1 SET PROPERTY FastStartFailoverTarget = upup;

–set log mode and protection mode
DGMGRL> EDIT DATABASE ‘upup’ SET PROPERTY LogXptMode=SYNC;
DGMGRL> EDIT DATABASE ‘upup1′ SET PROPERTY LogXptMode=SYNC;
DGMGRL> EDIT CONFIGURATION SET PROTECTION MODE AS MaxAvailability;
DGMGRL> EDIT CONFIGURATION SET PROPERTY FastStartFailoverThreshold = 10;

–enable fash failover
DGMGRL> enable fast_start failover
DGMGRL> connect sys/oracle@upup1
Connected.
DGMGRL> start observer
Observer started
…<to be continue>…

–connect another session
dgmgrl
DGMGRL> show fast_start failover

Fast-Start Failover: ENABLED
  Threshold:           10 seconds
  Target:              upup1
  Observer:            rac1.baby.com
  Lag Limit:           30 seconds (not in use)
  Shutdown Primary:    TRUE
  Auto-reinstate:      TRUE

Configurable Failover Conditions
  Health Conditions:
    Corrupted Controlfile          YES
    Corrupted Dictionary           YES
    Inaccessible Logfile            NO
    Stuck Archiver                  NO
    Datafile Offline               YES

  Oracle Error Conditions:
    (none)

Make sure standby db is ready to fast failover
SQL>  select  FS_FAILOVER_STATUS,FS_FAILOVER_OBSERVER_PRESENT   from v$database;

FS_FAILOVER_STATUS     FS_FAIL
———————- ——-
SYNCHRONIZED           YES

conn primary db, simulate primary failure
SQL> shutdown abort
ORACLE instance shut down.

At the observer session:
DGMGRL> start observer
Observer started
21:50:30.64  Tuesday, June 23, 2009
Initiating Fast-Start Failover to database “upup1″…
Performing failover NOW, please wait…
Failover succeeded, new primary is “upup1″
21:50:51.64  Tuesday, June 23, 2009

21:56:10.28  Tuesday, June 23, 2009
Initiating reinstatement for database “upup”…
Reinstating database “upup”, please wait…
Operation requires shutdown of instance “upup” on database “upup”
Shutting down instance “upup”…
ORA-01109: database not open

Database dismounted.
ORACLE instance shut down.
Operation requires startup of instance “upup” on database “upup”
Starting instance “upup”…
Unable to connect to database
ORA-12541: TNS:no listener

Failed.
You are no longer connected to ORACLE
Please connect again.
Unable to start instance “upup”
You must start instance “upup” manually
Reinstatement of database “upup” failed
21:56:33.07  Tuesday, June 23, 2009

–as indicated, start upup
SQL> startup mount

DGMGRL> reinstate database upup;
Reinstating database “upup”, please wait…
Reinstatement of database “upup” succeeded

DGMGRL> show database verbose upup

Database
  Name:            upup
  Role:            PHYSICAL STANDBY
  Enabled:         YES
  Intended State:  APPLY-ON
  Instance(s):
    upup

  Properties:
    DGConnectIdentifier             = ‘upup’
    ObserverConnectIdentifier       = ”
    LogXptMode                      = ’sync’
    DelayMins                       = ‘0′
    Binding                         = ‘OPTIONAL’
    MaxFailure                      = ‘0′
    MaxConnections                  = ‘1′
    ReopenSecs                      = ‘300′
    NetTimeout                      = ‘30′
    RedoCompression                 = ‘DISABLE’
    LogShipping                     = ‘ON’
    PreferredApplyInstance          = ”
    ApplyInstanceTimeout            = ‘0′
    ApplyParallel                   = ‘AUTO’
    StandbyFileManagement           = ‘auto’
    ArchiveLagTarget                = ‘0′
    LogArchiveMaxProcesses          = ‘5′
    LogArchiveMinSucceedDest        = ‘1′
    DbFileNameConvert               = ”
    LogFileNameConvert              = ”
    FastStartFailoverTarget         = ‘upup1′
    StatusReport                    = ‘(monitor)’
    InconsistentProperties          = ‘(monitor)’
    InconsistentLogXptProps         = ‘(monitor)’
    SendQEntries                    = ‘(monitor)’
    LogXptStatus                    = ‘(monitor)’
    RecvQEntries                    = ‘(monitor)’
    HostName                        = ‘rac2.baby.com’
    SidName                         = ‘upup’
    StandbyArchiveLocation          = ‘/u01/app/oracle/oradata/upup/arch/’
    AlternateLocation               = ”
    LogArchiveTrace                 = ‘0′
    LogArchiveFormat                = ‘upup_%t_%s_%r.arc’
    LatestLog                       = ‘(monitor)’
    TopWaitEvents                   = ‘(monitor)’

Current status for “upup”:
SUCCESS

Note: monitor your alter logs all the time and correct error if any.

How to operate lob by using DBMS_LOB in 11g

–Test version: 11.1.0.6

–The DBMS_LOB package provides subprograms to operate on BLOBs, CLOBs, NCLOBs, BFILEs, and temporary LOBs.
–DBMS_LOB can read and modify BLOBs, CLOBs, and NCLOBs;it provides read-only operations for BFILEs
Temporary LOB
-Stored in temporary tablespaces, deleted at the end of the session by default
Internal LOB
-LOB columns are defined in a table
-Use DML to initialize or populate the locators in the LOB columns
External LOB
-BFILE is the only type, can only read data in oracle.
-Using DIRECTORY and filename to create a LOB locator


–Temporary LOB

–create test tables
create table t1 (id number, chunk_value1 varchar2(4000),chunk_value2 varchar2(4000));
create table t2 (id number, chunk clob);

create or replace function f_getclob(p_chunk1 in varchar2,p_chunk2 in varchar2)
return clob
as
v_chunk clob;
v_temp varchar2(8000);
begin
dbms_lob.createtemporary(lob_loc=> v_chunk, cache=> true, dur=> dbms_lob.session);
v_temp := p_chunk1||p_chunk2;
dbms_lob.write(v_chunk,length(v_temp),1,v_temp);
–dbms_lob.freetemporary(v_chunk);
–as we need to return it, we cannot free it now.let it free automatically
return v_chunk;
end;
/

–insert data
insert into t1 values(1,lpad(‘*’,4000,’*'),’test’);
insert into t2 select id,f_getclob(chunk_value1,chunk_value2) from t1;
SQL> select id,length(chunk) from t2;
ID LENGTH(CHUNK)
———- ————-
1          4004

SQL> select * from V$TEMPORARY_LOBS;

SID CACHE_LOBS NOCACHE_LOBS ABSTRACT_LOBS
———- ———- ———— ————-
231          0            0             0

–check tempsize used by temporary LOB
select s.username, s.sid, u.tablespace, u.contents, u.segtype, round(u.blocks*8192/1024/1024,2) MB
from v$session s, v$sort_usage u
where s.saddr = u.session_addr and u.contents = ‘TEMPORARY’ and u.segtype=’LOB_DATA’
order by MB DESC ;
USERNAME                              SID TABLESPACE
—————————— ———- ——————————-
CONTENTS  SEGTYPE           MB
——— ——— ———-
SCOTT                            231 TEMP
TEMPORARY LOB_DATA           1


–Internal LOB

create table ti1(id number unique, chunk clob);
create or replace procedure p_insertlob(p_id in number,p_chunk1 in varchar2,p_chunk2 in varchar2) as
v_clob clob;
begin
–insert
insert into ti1 values (p_id, empty_clob()) returning chunk into v_clob;
dbms_lob.write(v_clob,length(p_chunk1),1,p_chunk1);
commit;
–update
select chunk into v_clob from ti1 where id=p_id for update;
dbms_lob.writeappend(v_clob,length(p_chunk2),p_chunk2);
commit;
end;
/

exec p_insertlob(1,lpad(‘$’,32767,’$'),lpad(‘*’,32767,’*'));

select id,dbms_lob.getlength(chunk) from ti1;

ID DBMS_LOB.GETLENGTH(CHUNK)
———- ————————-
1                     65534

Note:if you have functional and domain indexes on the LOB column, using dbms_lob.open() before write and dbms_lob.close() before commit are good for performance.
as the close() operation will trigger update on indexes. If no open() and close(), the indexes are updated at the same time doing update.


–External LOB

–function to read file from a giving diretory and file name
create or replace function p_get_elob(p_directory varchar2, p_filename varchar2)
return clob
as
v_file bfile;
v_flag integer :=0;
v_length number :=0;
v_clob clob;
v_src_offset integer :=1;
v_des_offset integer :=1;
v_lang_context integer :=0;
v_waring integer;
begin
dbms_lob.createtemporary(v_clob, true, dbms_lob.session);
v_file := bfilename(p_directory,p_filename);
v_flag := dbms_lob.fileexists(v_file);
if v_flag =0  then
dbms_output.put_line(‘File does not exist!’);
else
v_flag := dbms_lob.fileisopen(v_file);
if v_flag =0 then
dbms_lob.fileopen(v_file,dbms_lob.file_readonly);
end if;
v_length := dbms_lob.getlength(v_file);
dbms_lob.loadclobfromfile(v_clob, v_file, v_length, v_src_offset, v_des_offset, 0, v_lang_context, v_waring);
end if;
dbms_output.put_line(‘File length :’||dbms_lob.getlength(v_file));
dbms_output.put_line(‘Return length :’||dbms_lob.getlength(v_clob));
dbms_lob.fileclose(v_file);
return v_clob;
end;
/

–test
select p_get_elob(‘T’,'t.txt’)||’@’ from dual;

P_GET_ELOB(‘T’,'T.TXT’)||’@’
——————————————————————————–
Data Pump default directory object created:
directory object name: DATA_PUMP_DIR
creation date: 11-FEB-2009 01:52
END!
@

File length :121
Return length :121

References:
http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28419/d_lob.htm about operating lob
http://www.mydatabasesupport.com/forums/oracle-server/244585-tuning-clob-usage.html about lob performance
http://www.idevelopment.info/data/Oracle/DBA_tips/LOBs/LOBS_1.shtml about genernal lob idea
metalink doc 61737.1

Result cache in oracle 11g

DB version: 11.1.0.6

*Result cache:
The result cache stores the results of SQL queries and PL/SQL functions in an area called Result Cache Memory in the shared pool.

Server result cache is detetermined by below 3 parameters:
result_cache_max_result              integer     5
result_cache_max_size                big integer 384K
result_cache_mode string      MANUAL
if result_cache_mode is AUTO, no hint is requred to cache the sql result. It is automatically done by oracle.

Client result cache is detemined by below 2 parameters:
client_result_cache_lag              big integer 3000
client_result_cache_size big integer 0 (32K is minimum,less than it will disable the feature)
When client result caching is enabled, the query result set can be cached on the client or on the server or both

Sql Example:
SYS@ORA11G>select/*+ result_cache */ count(*) from t.t2 where object_id>10000;

Both client side and server side require same hint result_cache when result_cache_mode is MANUAL.

Step by step test Sql Performance Analyzer of Real Application Test

–Test version: 11.1.0.6


–create an analysis task

–Use the following procedures to create a sql tuning set
– populate the tuning set from the cursor cache
DECLARE
cur DBMS_SQLTUNE.SQLSET_CURSOR;
BEGIN
DBMS_SQLTUNE.CREATE_SQLSET(
sqlset_name => ‘my_sts’,
description  => ‘Sql tunning set for SPA’);
OPEN cur FOR
SELECT VALUE(P)
FROM table(
DBMS_SQLTUNE.SELECT_CURSOR_CACHE(
‘parsing_schema_name <> ”SYS” ‘,
NULL, NULL, NULL, NULL, 1, NULL,
‘ALL’)) P;
DBMS_SQLTUNE.LOAD_SQLSET(sqlset_name => ‘my_sts’,
populate_cursor => cur);
END;
/
–show sql tune set contents
SELECT * FROM TABLE(DBMS_SQLTUNE.SELECT_SQLSET(‘my_sts’));

–create analysis task
VARIABLE t_name VARCHAR2(100);
EXEC :t_name := DBMS_SQLPA.CREATE_ANALYSIS_TASK(sqlset_name => ‘my_sts’,task_name => ‘my_spa_task’);

–Also you can create a analysis task by giving sql_text
EXEC :t_name := DBMS_SQLPA.CREATE_ANALYSIS_TASK(sql_text => ’select * from t2 where object_id=990′,task_name => ’single_spa_task’);

–create a pre-change sql trail
EXEC DBMS_SQLPA.EXECUTE_ANALYSIS_TASK(task_name => ‘my_spa_task’, execution_type => ‘TEST EXECUTE’, execution_name => ‘my_exec_BEFORE_change’);

–perform changes on the test system
SYS@ORA11G>alter system set memory_target=140m;
T@ORA11G>drop index t2_oid;

–create a post-change sql trial
EXEC DBMS_SQLPA.EXECUTE_ANALYSIS_TASK(task_name => ‘my_spa_task’, execution_type => ‘TEST EXECUTE’, execution_name => ‘my_exec_AFTER_change’);

–compare sql trials
–analysis
EXEC DBMS_SQLPA.EXECUTE_ANALYSIS_TASK(task_name => ‘my_spa_task’, execution_type => ‘COMPARE PERFORMANCE’, execution_name => ‘my_exec_compare’, execution_params => dbms_advisor.arglist(‘execution_name1′,’my_exec_BEFORE_change’,'execution_name2′,’my_exec_AFTER_change’,'comparison_metric’, ‘buffer_gets’));

–report
VAR rep   CLOB;
EXEC :rep := DBMS_SQLPA.REPORT_ANALYSIS_TASK(‘my_spa_task’,'text’, ‘typical’, ’summary’);
SET LONG 100000 LONGCHUNKSIZE 100000 LINESIZE 130
PRINT :rep

REP
————————————————————————————————————-
———-
General Information
———————————————————————————————
Task Information:                              Workload Information:
———————————————  ———————————————
Task Name    : my_spa_task                     SQL Tuning Set Name        : my_sts
Task Owner   : SYS                             SQL Tuning Set Owner       : SYS
Description  :                                 Total SQL Statement Count  : 17

Execution Information:
———————————————————————————————
Execution Name  : my_exec_compare        Started             : 12/12/2008 15:52:51
Execution Type  : COMPARE PERFORMANCE    Last Updated        : 12/12/2008 15:52:51
Description     :                        Global Time Limit   : UNLIMITED
Scope           : COMPREHENSIVE          Per-SQL Time Limit  : UNUSED
Status          : COMPLETED              Number of Errors    : 8

Analysis Information:
———————————————————————————————
Comparison Metric: BUFFER_GETS
——————
Workload Impact Threshold: 1%
————————–
SQL Impact Threshold: 1%
———————-
Before Change Execution:                       After Change Execution:
———————————————  ———————————————
Execution Name      : my_exec_BEFORE_change    Execution Name      : my_exec_AFTER_change
Execution Type      : TEST EXECUTE             Execution Type      : TEST EXECUTE
Description         :                          Description         :
Scope               : COMPREHENSIVE            Scope               : COMPREHENSIVE
Status              : COMPLETED                Status              : COMPLETED
Started             : 12/12/2008 15:43:56      Started             : 12/12/2008 15:46:02
Last Updated        : 12/12/2008 15:43:58      Last Updated        : 12/12/2008 15:46:03
Global Time Limit   : UNLIMITED                Global Time Limit   : UNLIMITED
Per-SQL Time Limit  : UNUSED                   Per-SQL Time Limit  : UNUSED
Number of Errors    : 1                        Number of Errors    : 2

Report Summary
———————————————————————————————
Projected Workload Change Impact:
——————————————-
Overall Impact      :  -3.57%
Improvement Impact  :  0%
Regression Impact   :  -3.57%

SQL Statement Count
——————————————-
SQL Category  SQL Count  Plan Change Count
Overall              17                  2
Regressed             2                  2
Unchanged             7                  0
with Errors           8                  0

Projected Workload Performance Distribution
————————————————–
——————————————————————–
|          | Cumulative Perf. |        | Cumulative Perf. |        |
| Bucket   | Before Change    | (%)    | After Change     | (%)    |
——————————————————————–
| < = 1    |                0 |     0% |                0 |     0% |
| < = 4    |                9 |   .11% |                6 |   .07% |
| < = 32   |               31 |   .38% |                0 |     0% |
| < = 256  |              328 |  4.04% |              652 |  7.75% |
| < = 8192 |             7756 | 95.47% |             7756 | 92.18% |
——————————————————————–

Single SQL Statement Execution Count Distribution
——————————————————-
————————————————————-
|          | SQL Count     |        | SQL Count    |        |
| Bucket   | Before Change | (%)    | After Change | (%)    |
————————————————————-
| < = 1    |             2 | 11.76% |            2 | 11.76% |
| < = 4    |             3 | 17.65% |            2 | 11.76% |
| < = 32   |             1 |  5.88% |            0 |     0% |
| < = 256  |             2 | 11.76% |            4 | 23.53% |
| < = 8192 |             1 |  5.88% |            1 |  5.88% |
————————————————————-

SQL Statements Sorted by their Absolute Value of Change Impact on the Workload
————————————————————————————–
———————————————————————————————————
|           |               | Impact on | Metric | Metric | Impact   | % Workload | % Workload | Plan   |
| object_id | sql_id        | Workload  | Before | After  | on SQL   | Before     | After      | Change |
———————————————————————————————————
|        49 | 2ydjxgd87t9hk |    -1.96% |      3 |    162 |   -5300% |       .04% |      1.93% | y   |
|        47 | 94dwfa8yd87kw |    -1.61% |     31 |    162 | -422.58% |       .38% |      1.93% | y   |
———————————————————————————————————

SQL Statements with Errors Sorted by their object_id (8)
————————————————————
——————————————————————————–
| object_id | sql_id        | Error Message                                    |
——————————————————————————–
|        36 | 572674pu6mra0 | Type of SQL statement not supported.             |
|        37 | 8qhjcm5uv4j85 | Type of SQL statement not supported.             |
|        38 | 2jpf0qbj9vxq3 | Type of SQL statement not supported.             |
|        40 | g4y6nw3tts7cc | Type of SQL statement not supported.             |
|        43 | 36s7502m471xz | Error in execution ‘my_exec_AFTER_change’:       |
|           |               | ORA-01760: illegal argument for function         |
|        46 | ccuwpvmn6rp9t | Error in execution ‘my_exec_AFTER_change’:       |
|           |               | ORA-00907: missing right parenthesis             |
|        51 | bsaf69ghqw2ja | Type of SQL statement not supported.             |
|        52 | caj558xbnmytz | Type of SQL statement not supported.             |
——————————————————————————–
———————————————————————————————

–find out the sql
SYS@ORA11G>SELECT sql_text FROM TABLE(DBMS_SQLTUNE.SELECT_SQLSET(‘my_sts’)) where sql_id=’2ydjxgd87t9hk’;

SQL_TEXT
———————————————————————————————————–
———-
select count(*) from t2 where object_id<1000

SYS@ORA11G>SELECT sql_text FROM TABLE(DBMS_SQLTUNE.SELECT_SQLSET(‘my_sts’)) where sql_id=’94dwfa8yd87kw’;

SQL_TEXT
———————————————————————————————————
———-
select count(*) from t2

–tune regressed sql statement,reference SQL Tuning Advisor and SQL plan baselines procedures
–For sql ‘94dwfa8yd87kw’, the sql plan before change is
T@ORA11G>select * from table(dbms_xplan.display_cursor());

PLAN_TABLE_OUTPUT
————————————————————————–
————
SQL_ID  94dwfa8yd87kw, child number 0
————————————-
select count(*) from t2

Plan hash value: 3659760998

————————————————————————
| Id  | Operation             | Name   | Rows  | Cost (%CPU)| Time     |
————————————————————————
|   0 | SELECT STATEMENT      |        |       |     9 (100)|          |
|   1 |  SORT AGGREGATE       |        |     1 |            |          |
|   2 |   INDEX FAST FULL SCAN| T2_OID | 11892 |     9   (0)| 00:00:01 |
————————————————————————

–the sql plan after change, index is deleted, is
T@ORA11G>select * from table(dbms_xplan.display_cursor());

PLAN_TABLE_OUTPUT
——————————————————————-
————
SQL_ID  2hkvgb0cwhvvn, child number 0
————————————-
select count(*) from t2

Plan hash value: 3321871023

——————————————————————-
| Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |
——————————————————————-
|   0 | SELECT STATEMENT   |      |       |    48 (100)|          |
|   1 |  SORT AGGREGATE    |      |     1 |            |          |
|   2 |   TABLE ACCESS FULL| T2   | 11892 |    48   (0)| 00:00:01 |
——————————————————————-

–views related to SPA
DBA_ADVISOR_TASKS
DBA_ADVISOR_EXECUTIONS
DBA_ADVISOR_FINDINGS
DBA_ADVISOR_SQLPLANS
DBA_ADVISOR_SQLSTATS
V$ADVISOR_PROGRESS

Step by step test Database Replay of Real Application Test

–Test version: 11.1.0.6


–1.Capture workload

Before capturing a database workload, carefully consider the following options:
*Restarting the Database
–to avoid capture partial transaction
*Defining the Workload Filters
–inclusion filters or exclusion filters, not both
*Setting Up the Capture Directory

–capturing a database workload using APIs, Adding and Removing Workload Filters
BEGIN
DBMS_WORKLOAD_CAPTURE.ADD_FILTER (
fname => ‘user_t’,
fattribute => ‘USER’,
fvalue => ‘T’);
END;
/

–this will filte out all sessions beloings to user T
–fattribute should be PROGRAM, MODULE, ACTION, SERVICE, INSTANCE_NUMBER, and USER
–wildcard can be used in fvalue, such as %

–to delete a filter
BEGIN
DBMS_WORKLOAD_CAPTURE.DELETE_FILTER (fname => ‘user_ichan’);
END;
/

–start_capture
SYS@ORA11G>create directory testdir as ‘D:\oracle\reorg’;
BEGIN
DBMS_WORKLOAD_CAPTURE.START_CAPTURE (name => ‘mytest’,
dir => ‘TESTDIR’,
duration => 600);
END;
/

–it will stop automatically after 600 seconds
–if duration is not specified, call the following statement to stop it
BEGIN
DBMS_WORKLOAD_CAPTURE.FINISH_CAPTURE ();
END;
/

–export AWR data for workload capture
Exporting AWR data enables detailed analysis of the workload.
This data is also required if you plan to run the AWR Compare Period report
on a pair of workload captures or replays.
–get the capture id
SYS@ORA11G>select id from  DBA_WORKLOAD_CAPTURES;

ID
———-
1

–export awr of this id
BEGIN
DBMS_WORKLOAD_CAPTURE.EXPORT_AWR (capture_id => 1);
END;
/


–2.Preprocessing workload

–This is very resource contention, should not run on production system
–copy the dirctory files to the replay db, and run the procedure
BEGIN
DBMS_WORKLOAD_REPLAY.PROCESS_CAPTURE (capture_dir => ‘TESTDIR’);
END;
/


–3.Replaying a Database Workload

–step1. setup test system
Using rman restore/duplicate to test system
do the change you want, such as parameter change, hardware change
resetting system time, set the system time to capture start time

–step2. replaying
copy the preprocessed files to a db directory
resolving references to external system: db links, external tables, directories,URL, Email
remapping connections: the connection string used to connect the production system are captured
options:
synchronization
connect_time_scale
think_time_scale

–setting up replay clients
replay program: $ORACLE_HOME/bin/wrc, a multithreaded program
wrc [user/password[@server]] MODE=[value] [keyword=[value]]

–Calibrating Replay Clients
C:\Documents and Settings\Zengw>wrc t/t mode=calibrate replaydir=D:\oracle\reorg

Workload Replay Client: Release 11.1.0.6.0 – Production on Wed Dec 10 16:15:37 2008

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

Report for Workload in: D:\oracle\reorg
———————–

Recommendation:
Consider using at least 1 clients divided among 1 CPU(s).

Workload Characteristics:
- max concurrency: 1 sessions
- total number of sessions: 1

Assumptions:
- 1 client process per 50 concurrent sessions
- 4 client process per CPU
- think time scale = 100
- connect time scale = 100
- synchronization = TRUE

–OEM is the primary tools to do replay
--initializing replay data
BEGIN
DBMS_WORKLOAD_REPLAY.INITIALIZE_REPLAY (replay_name => ‘mytest_replay’,
replay_dir => ‘TESTDIR’);
END;
/

–setting workload replay options
BEGIN
DBMS_WORKLOAD_REPLAY.PREPARE_REPLAY (synchronization => TRUE);
END;
/

–start replay clients
C:\Documents and Settings\Zengw>wrc t/t mode=replay replaydir=D:\oracle\reorg

Workload Replay Client: Release 11.1.0.6.0 – Production on Wed Dec 10 16:23:07 2008

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

Wait for the replay to start (16:23:07)
–i get the below output after the below procedure is done
Replay started (16:23:48)
Replay finished (16:25:39)

–starting a workload replay in another window
BEGIN
DBMS_WORKLOAD_REPLAY.START_REPLAY ();
END;
/

–Exporting AWR Data for Workload Replay
–get the replay id
SYS@ORA11G>select id from dba_workload_replays;

ID
———-
1

BEGIN
DBMS_WORKLOAD_REPLAY.EXPORT_AWR (replay_id => 1);
END;
/

–workload replay views
DBA_WORKLOAD_CAPTURES
DBA_WORKLOAD_FILTERS
DBA_WORKLOAD_REPLAYS
DBA_WORKLOAD_REPLAY_DIVERGENCE
DBA_WORKLOAD_CONNECTION_MAP


–4.Analyzing replay workload

–generating a workload capture report, OEM/procedure
set serveroutput on
DECLARE
cap_id         NUMBER;
cap_rpt        CLOB;
rpt_len                 NUMBER;
BEGIN
cap_id  := DBMS_WORKLOAD_CAPTURE.GET_CAPTURE_INFO(dir => ‘TESTDIR’);
cap_rpt := DBMS_WORKLOAD_CAPTURE.REPORT(capture_id => cap_id,format => DBMS_WORKLOAD_CAPTURE.TYPE_TEXT);
rpt_len :=DBMS_LOB.GETLENGTH(cap_rpt);
dbms_output.put_line(‘length:’||rpt_len);
dbms_output.put_line(DBMS_LOB.SUBSTR(cap_rpt,32767,1)); –if rpt_len < 32767
END;
/

length:11623

Database Capture Report For ORA11G

DB Name         DB Id    Release     RAC Capture Name               Status
————
———– ———– — ————————– ———-
ORA11G        2333620726 11.1.0.6.0  NO  mytest                                            COMPLETED
Start time: 10-Dec-08 15:43:05 (SCN = 237383)
End time: 10-Dec-08 15:48:25
(SCN = 238531)
Duration: 5 minutes 20 seconds
Capture size: 1.99 KB
Directory object: TESTDIR
Directory path: D:\oracle\reorg
Directory shared in RAC: TRUE
Filters used: 1 EXCLUSION filter

Captured Workload Statistics                          DB: ORA11G  Snaps: 13-14
-> ‘Value’ represents the corresponding statistic aggregated across the entire captured database workload.
-> ‘% Total’ is the percentage of ‘Value’ over the corresponding system-wide aggregated total.
Statistic Name                                   Value   %Total
—————————————- ————- ———
DB time (secs)                                    0.06        0.22
Average Active Sessions                           0.00
User calls captured                                  4        8.00
User calls captured with Errors                      0
Session logins                                       0        0.00
Transactions                                         0    0.00
————————————————————-
Top Events Captured                                   DB:ORA11G  Snaps: 13-14

No data exists for this section of the report.
————————————————————-
Top Service/Module Captured                           DB:ORA11G  Snaps: 13-14
No data exists for this section of the report.
————————————————————-
Top SQL Captured                                      DB:ORA11G  Snaps: 13-14
No data exists for this section of the report.
————————————————————-
Top Sessions Captured                                 DB:ORA11G  Snaps: 13-14
No data exists for this section of the report.
————————————————————-
Top Events containing Unreplayable Calls              DB:ORA11G  Snaps: 13-14
No data exists for this section of the report.
————————————————————-
Top Service/Module containing Unreplayable Calls      DB:ORA11G  Snaps: 13-14
No data exists for this section of the report.
————————————————————-
Top SQL containing Unreplayable Calls                 DB:ORA11G  Snaps: 13-14
No data exists for this section of the report.
————————————————————-
Top Sessions containing Unreplayable Calls            DB:ORA11G  Snaps: 13-14
No data exists for this section of the report.
————————————————————-
Top Events Filtered Out                               DB:ORA11G  Snaps: 13-14
Avg Active Event                        Event Class        % Event   Sessions
———————————– ————— ———- ———-
CPU + Wait for CPU
CPU                  37.70       0.07
db file scattered read              User I/O              1.64       0.00
db file sequential
read             User I/O              1.64       0.00
————————————————————-

Top Service/Module Filtered Out                       DB: ORA11G  Snaps: 13-14
Service        Module                   % Activity
Action               % Action
————– ———————— ———- —————— ———-
SYS$USERS
SQL*Plus                      39.34 UNNAMED                 39.34
sqlplus.exe                    1.64 UNNAMED
1.64
————————————————————-

Top SQL Filtered Out        DB: ORA11G  Snaps: 13-14
SQL ID     % Activity Event                          % Event
———————–
————– —————————— ——-
a6ta5bs4qwy6p          31.15 CPU + Wait for CPU
31.15
select count(*) from t,t2

2jpf0qbj9vxq3           3.28 CPU + Wait for CPU                3.28
** SQL Text Not Available **

fcwj05qyp0f6w           3.28 db file scattered read            1.64
** SQL Text Not Available **

db file sequential read           1.64

bs8bzd41vz3×0           1.64 CPU + Wait for CPU                1.64
BEGIN
DBMS_WORKLOAD_CAPTURE.START_CAPTURE (name => ‘mytest’,
dir => ‘TESTDIR’, duration => 600); END;

g9u5j7y6cfxxq
1.64 CPU + Wait for CPU                1.64
** SQL Text Not Available **

————————————————————-
Top Sessions Filtered Out                             DB:
ORA11G  Snaps: 13-14
-> ‘# Samples Active’ shows the number of ASH samples in which the session was found waiting for that particular event. The percentage shown in this column is calculated with respect to wall clock time and not total database activity.
-> ‘XIDs’ shows the number of distinct transaction IDs sampled in ASH when the session was waiting for that particular event
-> For sessions running Parallel Queries, this section will NOT aggregate the PQ slave activity into the session issuing the PQ. Refer to the ‘Top Sessions running PQs’ section for such statistics.
Sid, Serial# % Activity
Event                             % Event
————— ———- —————————— ———-
User
Program                          # Samples Active     XIDs
——————– —————————— ——————
——–
88,    7      39.34 CPU + Wait for CPU                  36.07
T                    sqlplus.exe
22/320 [  7%]        2

db file scattered read               1.64

1/320 [  0%]        1

db file sequential read              1.64

1/320 [  0%]        1

61,   27       1.64 CPU + Wait for CPU                   1.64
SYS                  sqlplus.exe
1/320 [  0%]        0

————————————————————-
Top Events (Jobs and
Background Activity)             DB: ORA11G  Snaps: 13-14
Avg
Active
Event                               Event Class        % Event   Sessions
———————————– —————
———- ———-
db file sequential read             User I/O             14.75       0.03
CPU + Wait for CPU
CPU                   9.84       0.02
control file parallel write         System I/O            9.84       0.02
null event
Other                 6.56       0.01
control file sequential read        System I/O            4.92       0.01
————————————————————-
Top Service/Module (Jobs and Background Activity)     DB:ORA11G  Snaps: 13-14
Service        Module                   % Activity Action               % Action
————–
———————— ———- —————— ———-
SYS$BACKGROUND UNNAMED                       37.70 UNNAMED
37

PL/SQL procedure successfully completed.

–generating a workload replay report , OEM/procedure

set serveroutput on
DECLARE
cap_id         NUMBER;
rep_id         NUMBER;
rep_rpt        CLOB;
rpt_len                 NUMBER;
BEGIN
cap_id := DBMS_WORKLOAD_REPLAY.GET_REPLAY_INFO(dir => ‘TESTDIR’);
/* Get the latest replay for that capture */
SELECT max(id)
INTO   rep_id
FROM   dba_workload_replays
WHERE  capture_id = cap_id;

rep_rpt := DBMS_WORKLOAD_REPLAY.REPORT(replay_id => rep_id,
format => DBMS_WORKLOAD_REPLAY.TYPE_TEXT);
rpt_len :=DBMS_LOB.GETLENGTH(rep_rpt);
dbms_output.put_line(‘length:’||rpt_len);
dbms_output.put_line(DBMS_LOB.SUBSTR(rep_rpt,32767,1)); –if rpt_len < 32767
END;
/
–format can be DBMS_WORKLOAD_REPLAY.TYPE_TEXT, DBMS_WORKLOAD_REPLAY.TYPE_HTML, and DBMS_WORKLOAD_REPLAY.TYPE_XML.
length:6603
DB Replay Report for mytest_replay
————————————————————————–
—————–
———————————————————-
| DB Name | DB Id      | Release    | RAC | Replay Name   | Replay Status
|
————————————————————————–
| ORA11G  | 2333620726 | 11.1.0.6.0 | NO  |
mytest_replay | COMPLETED     |
————————————————————————–
Replay Information
—————————————————————-
|   Information    | Replay             | Capture
|
—————————————————————-
| Name             | mytest_replay      | mytest
|
—————————————————————-
| Status           | COMPLETED          | COMPLETED
|
—————————————————————-
| Database Name    | ORA11G             | ORA11G
|
—————————————————————-
| Database Version | 11.1.0.6.0         | 11.1.0.6.0
|
—————————————————————-
| Start Time       | 10-DEC-08 16:23:38 | 10-DEC-08 15:43:05
|
—————————————————————-
| End Time         | 10-DEC-08 16:24:02 | 10-DEC-08 15:48:25
|
—————————————————————-
| Duration         | 24 seconds         | 5 minutes 20 seconds
|
—————————————————————-
| Directory Object | TESTDIR            | TESTDIR
|
—————————————————————-
| Directory Path   | D:\oracle\reorg    | D:\oracle\reorg
|
—————————————————————-

Replay Options
———————————————————
|       Option Name       | Value
|
———————————————————
| Synchronization         | TRUE
|
———————————————————
| Connect Time            | 100%
|
———————————————————
| Think Time              | 100%
|
———————————————————
| Think Time Auto Correct | TRUE
|
———————————————————
| Number of WRC Clients   | 1 (1 Completed, 0 Running )
|
———————————————————

Replay Statistics
———————————————————–
|        Statistic        | Replay        | Capture
|
———————————————————–
| DB Time                 | 4.388 seconds | 0.061 seconds
|
———————————————————–
| Average Active Sessions |           .18 |             0
|
———————————————————–
| User calls              |             4 |             4
|
———————————————————–
| Network Time            | 0.000 seconds | .
|
———————————————————–
| Think Time              | 0.000 seconds | .
|
———————————————————–

Replay Divergence Summary
——————————————————————-
|                Divergence Type                | Count
| % Total |
——————————————————————-
| Session Failures During Replay                |
0 |    0.00 |
——————————————————————-
| Errors No Longer Seen During Replay           |
0 |    0.00 |
——————————————————————-
| New Errors Seen During Replay                 |
0 |    0.00 |
——————————————————————-
| Errors Mutated During Replay                  |
0 |    0.00 |
——————————————————————-
| DMLs with Different Number of Rows Modified   |
0 |    0.00 |
——————————————————————-
| SELECTs with Different Number of Rows Fetched |
0 |    0.00
|
——————————————————————-

————————————————————-
————————————–
Workload Profile Top Events
————————————————–
| No data
exists for this section of the report. |
————————————————–
Top
Service/Module/Action
————————————————–
| No data exists for this section of the report.
|
————————————————–
Top SQL with Top Events
————————————————–
| No
data exists for this section of the report. |
————————————————–
Top Sessions with Top
Events
————————————————–
| No data exists for this section of the report.
|
————————————————–
Replay Divergence Session Failures By
Application
————————————————–
| No data exists for this section of the report.
|
————————————————–
Error Divergence By
Application
————————————————–
| No data exists for this section of the report.
|
————————————————–
By SQL
————————————————–
| No data exists for
this section of the report. |
————————————————–
By
Session
————————————————–
| No data exists for this section of the report.
|
————————————————–
DML Data Divergence By
Application
————————————————–
| No data exists for this section of the report.
|
————————————————–
By SQL
————————————————–
| No data exists for
this section of the report. |
————————————————–
SELECT Data Divergence By
Application
————————————————–
| No data exists for this section of the report.
|
————————————————–

End of Report.

PL/SQL procedure successfully completed.

–cause I am doing the capture and replay on same db, there is no much divergence

–appendix: sql statements tested
T@ORA11G>create table t as select * from dba_objects;

Table created.

T@ORA11G>select count(*) from dba_objects;

COUNT(*)
———-
12091

T@ORA11G>create index t_oid on t(object_id);

Index created.

T@ORA11G>create index t_oname on t(object_name);

Index created.

T@ORA11G>update t set object_id=99999999-object_id;

12091 rows updated.

T@ORA11G>commit;

Commit complete.

T@ORA11G>select min(object_id) from t;

MIN(OBJECT_ID)
————–
99987491

T@ORA11G>create table t2 as select * from dba_objects;

Table created.

T@ORA11G>select count(*) from t,t2 where t.object_id=t2.object_id;

COUNT(*)
———-
0

T@ORA11G>select count(*) from t,t2 where t.object_name=t2.object_name;

COUNT(*)
———-
18629

T@ORA11G>create index t2_oname on t2(object_name);

Index created.

T@ORA11G>select count(*) from t,t2 where t.object_name=t2.object_name;

COUNT(*)
———-
18629

T@ORA11G>update t set object_id=99999999-object_id;

12091 rows updated.

T@ORA11G>select count(*) from t,t2 where t.object_id=t2.object_id;

COUNT(*)
———-
12091

T@ORA11G>commit;

Commit complete.

T@ORA11G>select count(*) from t,t2;

COUNT(*)
———-
146228554

Step by step test Sql Plan Management

–Test Version: 11.1.0.6
–Plan history is maintained only for repeatable SQL statements.A SQL statement is recognized as repeatable when it is parsed or executed again after it has been logged.

–How to turn on Automatic Plan Capture
Alter system set OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES = TRUE

–Manual Plan Loading
–Loading Plans from SQL Tuning Sets
DECLARE
my_plans pls_integer;
BEGIN
my_plans := DBMS_SPM.LOAD_PLANS_FROM_SQLSET(sqlset_name => ‘tset1′);
END;
/
–you can load plans from AWR to Sql tuning Set, then load it to SPM

–Manual load from cursor cache
–run a test sql
T@ORCL11G>select count(*) from t;

COUNT(*)
———-
1101840

SYS@orcl11g>select sid,serial# from v$session where username=’T';

SID    SERIAL#
———- ———-
87          7

SYS@orcl11g>select sql_id from v$session where sid=87;

SQL_ID
————-
cyzznbykb509s

–manual load the sql to base line from cursor cache
DECLARE
my_plans pls_integer;
BEGIN
my_plans := DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(sql_id => ‘cyzznbykb509s’);
END;
/

–get sql_handle
SYS@orcl11g>select sql_handle,sql_text from DBA_SQL_PLAN_BASELINES;

SQL_HANDLE                     SQL_TEXT
—————————— ————————————
SYS_SQL_793213869456f9be       select count(*) from t

–Evolving Plans
SET SERVEROUTPUT ON
SET LONG 10000
DECLARE
report clob;
BEGIN
report := DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE(
sql_handle => ‘SYS_SQL_793213869456f9be’);
DBMS_OUTPUT.PUT_LINE(report);
END;
/

———————————————————
Evolve SQL Plan Baseline Report
———————————————————

Inputs:
——-
SQL_HANDLE =
SYS_SQL_793213869456f9be
PLAN_NAME  =
TIME_LIMIT = DBMS_SPM.AUTO_LIMIT
VERIFY     = YES
COMMIT     =
YES

———————————————————
Report
Summary
———————————————————
There were no SQL plan baselines that
required processing.

PL/SQL procedure successfully completed.

–Displaying SQL Plan Baselines
select * from table(
dbms_xplan.display_sql_plan_baseline(
sql_handle=>’SYS_SQL_793213869456f9be’,
format=>’basic’));

PLAN_TABLE_OUTPUT
———————————————————————
SQL handle: SYS_SQL_793213869456f9be
SQL text: select count(*) from t
———————————————————————
Plan name: SYS_SQL_PLAN_9456f9be3fdbb376
Enabled: YES     Fixed: NO      Accepted: YES     Origin: MANUAL-LOAD
———————————————————————
Plan hash value: 2966233522
———————————–
| Id  | Operation          | Name |
———————————–
|   0 | SELECT STATEMENT   |      |
|   1 |  SORT AGGREGATE    |      |
|   2 |   TABLE ACCESS FULL| T    |
———————————–

20 rows selected.

–modify table and add index
T@ORCL11G>alter table t modify object_name not null;
Table altered.

T@ORCL11G>create index idx_obj_name on t(object_name);
Index created.

T@ORCL11G>select count(*) from t;
COUNT(*)
———-
1101840

SYS@orcl11g>select sql_id from v$session where sid=87;
SQL_ID
————-
cyzznbykb509s

–load the sql plan from cursor cache again
SYS@orcl11g>DECLARE
my_plans pls_integer;
BEGIN
my_plans := DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(sql_id => ‘cyzznbykb509s’);
END;
/
–When you manually load plans into a SQL plan baseline, these loaded plans are added as accepted plans.

–Evolving the sql plan again
SYS@orcl11g>DECLARE
report clob;
BEGIN
report := DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE(
sql_handle => ‘SYS_SQL_793213869456f9be’);
DBMS_OUTPUT.PUT_LINE(report);
END;
/
————————————————————————-
Evolve SQL Plan Baseline Report
————————————————————————-
Inputs:
——-
SQL_HANDLE =
SYS_SQL_793213869456f9be
PLAN_NAME  =
TIME_LIMIT = DBMS_SPM.AUTO_LIMIT
VERIFY     = YES
COMMIT     = YES

Plan:
SYS_SQL_PLAN_9456f9be3e1ca9ac
———————————–
Plan was verified: Time used 53.006 seconds.
Passed
performance criterion: Compound improvement ratio >= 2.96.
Plan was changed to an accepted plan.

Baseline Plan      Test Plan     Improv. Ratio
————-      ———     ————-
Execution Status:        COMPLETE       COMPLETE
Rows Processed:                 1              1
Elapsed Time(ms):           30428           5475                            5.56
CPU Time(ms):                 290            130              2.23
Buffer Gets:                16228           5477                            2.96
Disk Reads:                 16217           5463              2.97
Direct Writes:                  0              0

Fetches:                      238                101              2.36
Executions:                     1                            1

————————————————————————-
Report Summary
————————————————————————-
Number of SQL plan baselines verified: 1.
Number of SQL plan baselines evolved: 1.
PL/SQL procedure successfully completed.

–The new plan was accepted
–check SQL Plan Baselines again
SYS@orcl11g>select * from table(
dbms_xplan.display_sql_plan_baseline(
sql_handle=>’SYS_SQL_793213869456f9be’,
format=>’basic’));
PLAN_TABLE_OUTPUT
———————————————————————–
SQL handle: SYS_SQL_793213869456f9be
SQL text: select count(*) from t
———————————————————————–
Plan name: SYS_SQL_PLAN_9456f9be3e1ca9ac
Enabled: YES     Fixed: NO      Accepted: YES     Origin: AUTO-CAPTURE  –Don’t understand why it is auto!?
———————————————————————–
Plan hash value: 1628650996
———————————————-
| Id  | Operation             | Name         |
———————————————-
|   0 | SELECT STATEMENT      |              |
|   1 |  SORT AGGREGATE       |              |
|   2 |   INDEX FAST FULL SCAN| IDX_OBJ_NAME | –the new plan is added
———————————————-

———————————————————————–
Plan name: SYS_SQL_PLAN_9456f9be3fdbb376
Enabled: YES     Fixed: NO      Accepted: YES     Origin: MANUAL-LOAD
———————————————————————–
Plan hash value: 2966233522
———————————–
| Id  | Operation          | Name |
———————————–
|   0 | SELECT STATEMENT   |      |
|   1 |  SORT AGGREGATE    |      |
|   2 |   TABLE ACCESS FULL| T    |
———————————–

35 rows selected.

–let’s fix the new plan SYS_SQL_PLAN_9456f9be3e1ca9ac
DECLARE
my_plans pls_integer;
BEGIN
my_plans := DBMS_SPM.ALTER_SQL_PLAN_BASELINE (
sql_handle  => NULL,
plan_name   => ‘SYS_SQL_PLAN_9456f9be3e1ca9ac’,
attribute_name => ‘fixed’,
attribute_value => ‘YES’);
END;
/

–let’s check the plan again
SYS@orcl11g>select * from table(
dbms_xplan.display_sql_plan_baseline(
sql_handle=>’SYS_SQL_793213869456f9be’,
format=>’basic’));
PLAN_TABLE_OUTPUT
———————————————————————-
SQL handle: SYS_SQL_793213869456f9be
SQL text: select count(*) from t
———————————————————————-
Plan name: SYS_SQL_PLAN_9456f9be3e1ca9ac
Enabled: YES     Fixed: YES Accepted: YES     Origin: AUTO-CAPTURE
———————————————————————-
Plan hash value: 1628650996  –It is now fixed “Fixed: YES”

———————————————-
| Id  | Operation             | Name         |
———————————————-
|   0 | SELECT STATEMENT      |              |
|   1 |  SORT AGGREGATE       |              |
|   2 |   INDEX FAST FULL SCAN| IDX_OBJ_NAME |
———————————————-

———————————————————————-
Plan name: SYS_SQL_PLAN_9456f9be3fdbb376
Enabled: YES     Fixed: NO      Accepted: YES     Origin: MANUAL-LOAD
———————————————————————-

Plan hash value: 2966233522

———————————–
| Id  | Operation          | Name |
———————————–
|   0 | SELECT STATEMENT   |      |
|   1 |  SORT AGGREGATE    |      |
|   2 |   TABLE ACCESS FULL| T    |
———————————–

35 rows selected.

–A fixed plan takes precedence over a non-fixed plan.Oracle will use the fixed plan whenever possible
–A SQL plan baseline is fixed if it contains at least one enabled plan whose FIXED attribute is set to YES.

–clean this sql baseline
DECLARE
my_plans pls_integer;
BEGIN
my_plans := DBMS_SPM.DROP_SQL_PLAN_BASELINE (sql_handle => ‘SYS_SQL_793213869456f9be’);
END;
/

T@ORCL11G>select sql_handle,sql_text from DBA_SQL_PLAN_BASELINES;
no rows selected

–Other related configurations
–Disk Space Usage in SYSAUX

–To change the percentage limit, use the CONFIGURE procedure of the DBMS_SPM package:
BEGIN
DBMS_SPM.CONFIGURE(
’space_budget_percent’,30);  –default 10% SYSAUX, range 1% to 50%
END;
/

–Purging Policy
BEGIN
DBMS_SPM.CONFIGURE(
‘plan_retention_weeks’,105);  –default 53 weeks, range 5 to 523
END;
/

–get the configuration from view dba_sql_management_config
select parameter_name, parameter_value from dba_sql_management_config;
PARAMETER_NAME                 PARAMETER_VALUE
—————————— —————
SPACE_BUDGET_PERCENT                        30
PLAN_RETENTION_WEEKS                       105


–Importing and Exporting SQL Plan Baselines

1.On the original system, create a staging table using the CREATE_STGTAB_BASELINE procedure:
BEGIN
DBMS_SPM.CREATE_STGTAB_BASELINE(
table_name => ’stage1′);
END;
/

2.pack the needed baselines
DECLARE
my_plans number;
BEGIN
my_plans := DBMS_SPM.PACK_STGTAB_BASELINE(
table_name => ’stage1′,
enabled => ‘yes’,
creator => ‘dba1′);
END;
/

3.Export the staging table stage1 into a flat file using the export command or Oracle Data Pump.
4.Transfer the flat file to the target system.
5.Import the staging table stage1 from the flat file using the import command or Oracle Data Pump.
6.Unpack the SQL plan baselines from the staging table into the SQL management base on the target system using the UNPACK_STGTAB_BASELINE function:
DECLARE
my_plans number;
BEGIN
my_plans := DBMS_SPM.UNPACK_STGTAB_BASELINE(
table_name => ’stage1′,
fixed => ‘yes’);
END;
/

Step by step test 11g adaptive cursor

DB version: 11.1.0.6

–Adaptive Cursors in 11g

–create a test table
T@ORCL11G>alter system flush shared_pool;
System altered.
T@ORCL11G>create table t2
as
select case when rownum = 1 then 1 else 99 end id, a.*
from dba_objects a
/

Table created.
T@ORCL11G>create index t2_id on t2(id);
Index created.

T@ORCL11G> begin
dbms_stats.gather_table_stats
( user, ‘T2′,
estimate_percent => 100,
method_opt=> ‘for all indexed columns’,cascade=>TRUE);
end;
/
PL/SQL procedure successfully completed.
–gather 100% is necessary as the data is skew

–bind 99, which have many duplicated rows
T@ORCL11G>variable id number
T@ORCL11G>exec :id :=99
PL/SQL procedure successfully completed.

T@ORCL11G>select * from t2 where id=:id;
…..
68868 rows selected.

–check the LAST EXECUTED SQL plan
T@ORCL11G>select * from table(dbms_xplan.display_cursor(null,null,’typical +peeked_binds’));

PLAN_TABLE_OUTPUT
—————————————————————————————————
SQL_ID  g852rfbbqn2f9, child number 0
————————————-
select * from t2 where id=:id

Plan hash value: 1513984157

————————————————————————–
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
————————————————————————–
|   0 | SELECT STATEMENT  |      |       |       |   293 (100)|          |
|*  1 |  TABLE ACCESS FULL| T2   | 68868 |  6994K|   293   (1)| 00:00:04 |
————————————————————————–

Peeked Binds (identified by position):
————————————–

1 – :ID (NUMBER): 99

Predicate Information (identified by operation id):
—————————————————

1 – filter(“ID”=:ID)

23 rows selected.

–it is “TABLE ACCESS FULL” now
–let’s check the bina related statistics
T@ORCL11G>select sql_id, is_bind_sensitive, is_bind_aware from v$sql where sql_text=’select * from t2 where id=:id’;

SQL_ID        I I
————- – -
g852rfbbqn2f9 Y N
–is_bind_sensitive=Y, means oracle knows this sql is bind sensitive
–is_bind_aware=N, means oracle is not aware yet of a performance issue with regards to the bind values

–let’s change the bind value and run again
T@ORCL11G>exec :id := 1;

PL/SQL procedure successfully completed.

T@ORCL11G>select * from t2 where id=:id;
ID OWNER
———- —————
OBJECT_NAME
————————————————————————————————————-
——–
SUBOBJECT_NAME                  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE         CREATED            LAST_DDL_TIME
—————————— ———- ————– ——————- —————— ————-
TIMESTAMP           STATUS  T G S  NAMESPACE EDITION_NAME
——————- ——- – - – ———- ——————————
1 SYS
ICOL$
20              2 TABLE               15-OCT-07          15-OCT-07
2007-10-15:10:09:08 VALID   N N N          1

–let’s check the plan
T@ORCL11G>select * from table(dbms_xplan.display_cursor(null,null,’typical +peeked_binds’));
PLAN_TABLE_OUTPUT
—————————————————————————————————
SQL_ID  g852rfbbqn2f9, child number 0
————————————-
select * from t2 where id=:id

Plan hash value: 1513984157

————————————————————————–
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
————————————————————————–
|   0 | SELECT STATEMENT  |      |       |       |   293 (100)|          |
|*  1 |  TABLE ACCESS FULL| T2   | 68868 |  6994K|   293   (1)| 00:00:04 |
————————————————————————–

Peeked Binds (identified by position):
————————————–

1 – :ID (NUMBER): 99

Predicate Information (identified by operation id):
—————————————————

1 – filter(“ID”=:ID)

23 rows selected.

–the same plan 1513984157 as previous, but oracle expected to get 68868 rows, but it actually got 1 row

–let’s run the same sql with same bind variable again

T@ORCL11G>select * from t2 where id=:id;

ID OWNER
———- —————
OBJECT_NAME
————————————————————————————————————–
——–
SUBOBJECT_NAME                  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE         CREATED            LAST_DDL_TIME
—————————— ———- ————– ——————- —————— ————–
TIMESTAMP           STATUS  T G S  NAMESPACE EDITION_NAME
——————- ——- – - – ———- ——————————
1 SYS
ICOL$
20              2 TABLE               15-OCT-07          15-OCT-07
2007-10-15:10:09:08 VALID   N N N          1

–let’s check the plan
T@ORCL11G>select * from table(dbms_xplan.display_cursor(null,null,’typical +peeked_binds’));
PLAN_TABLE_OUTPUT
————————————————————————————–
SQL_ID  g852rfbbqn2f9, child number 1
————————————-
select * from t2 where id=:id

Plan hash value: 3119810522

————————————————————————————-
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
————————————————————————————-
|   0 | SELECT STATEMENT            |       |       |       |     2 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| T2    |     1 |   104 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T2_ID |     1 |       |     1   (0)| 00:00:01 |

————————————————————————————-

Peeked Binds (identified by position):
————————————–

1 – :ID (NUMBER): 1

Predicate Information (identified by operation id):
—————————————————

2 – access(“ID”=:ID)

24 rows selected.

–You see the execution plan is changed, cool!

–let’s check  bind aware or not
T@ORCL11G>select sql_id, child_number, is_bind_sensitive, is_bind_aware from v$sql where sql_text=’select * from t2 where id=:id’;
SQL_ID        CHILD_NUMBER I I
————- ———— – -
g852rfbbqn2f9            0 Y N
g852rfbbqn2f9            1 Y Y  –you can set is_bind_aware=Y in this new line. That means oracle know there is a problem

–let’s test another id which is not exist
T@ORCL11G>exec :id := 50;

PL/SQL procedure successfully completed.

T@ORCL11G>select * from t2 where id=:id;
no rows selected

T@ORCL11G>select * from table(dbms_xplan.display_cursor(null,null,’typical +peeked_binds’));
PLAN_TABLE_OUTPUT
——————————————————————————————–
——————————–
SQL_ID  g852rfbbqn2f9, child number 2
————————————-
select * from t2 where id=:id

Plan hash value: 3119810522

————————————————————————————-
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
————————————————————————————-
|   0 | SELECT STATEMENT            |       |       |       |     2 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| T2    |     1 |   104 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T2_ID |     1 |       |     1   (0)| 00:00:01 |
————————————————————————————-

Peeked Binds (identified by position):
————————————–

1 – :ID (NUMBER): 50

Predicate Information (identified by operation id):
—————————————————

2 – access(“ID”=:ID)

24 rows selected.

–it is still using index, but it is a new plan with child number 2

–try another non exist id 2 times

T@ORCL11G>exec :id := 88
PL/SQL procedure successfully completed.

T@ORCL11G>select * from t2 where id=:id;
no rows selected

T@ORCL11G>select * from table(dbms_xplan.display_cursor(null,null,’typical +peeked_binds’));
PLAN_TABLE_OUTPUT
————————————————————————————————-
SQL_ID  g852rfbbqn2f9, child number 2
————————————-
select * from t2 where id=:id

Plan hash value: 3119810522

————————————————————————————-
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
————————————————————————————-
|   0 | SELECT STATEMENT            |       |       |       |     2 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| T2    |     1 |   104 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T2_ID |     1 |       |     1   (0)| 00:00:01 |
————————————————————————————-

Peeked Binds (identified by position):
————————————–

1 – :ID (NUMBER): 50

Predicate Information (identified by operation id):
—————————————————

2 – access(“ID”=:ID)

24 rows selected.

T@ORCL11G>select * from t2 where id=:id;
no rows selected

T@ORCL11G>select * from table(dbms_xplan.display_cursor(null,null,’typical +peeked_binds’));
PLAN_TABLE_OUTPUT
————————————————————————————————-
——————————–
SQL_ID  g852rfbbqn2f9, child number 2
————————————-
select * from t2 where id=:id

Plan hash value: 3119810522

————————————————————————————-
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
————————————————————————————-
|   0 | SELECT STATEMENT            |       |       |       |     2 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| T2    |     1 |   104 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T2_ID |     1 |       |     1   (0)| 00:00:01 |
————————————————————————————-

Peeked Binds (identified by position):
————————————–

1 – :ID (NUMBER): 50

Predicate Information (identified by operation id):
—————————————————

2 – access(“ID”=:ID)

24 rows selected.

–you can see, the 2 are using the same plan with child number 2

–let’s use sql_id to show all plans of this sql
T@ORCL11G>select * from table(dbms_xplan.display_cursor(‘g852rfbbqn2f9′,null,’typical +peeked_binds));

PLAN_TABLE_OUTPUT
—————————————————————————————————
SQL_ID  g852rfbbqn2f9, child number 0
————————————-
select * from t2 where id=:id

Plan hash value: 1513984157

————————————————————————–
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
————————————————————————–
|   0 | SELECT STATEMENT  |      |       |       |   293 (100)|          |
|*  1 |  TABLE ACCESS FULL| T2   | 68868 |  6994K|   293   (1)| 00:00:04 |
————————————————————————–

Peeked Binds (identified by position):
————————————–

1 – :ID (NUMBER): 99

Predicate Information (identified by operation id):
—————————————————

1 – filter(“ID”=:ID)

SQL_ID  g852rfbbqn2f9, child number 1
————————————-
select * from t2 where id=:id

Plan hash value: 3119810522

————————————————————————————-
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
————————————————————————————-
|   0 | SELECT STATEMENT            |       |       |       |     2 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| T2    |     1 |   104 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T2_ID |     1 |       |     1   (0)| 00:00:01 |
————————————————————————————-

Peeked Binds (identified by position):
————————————–

1 – :ID (NUMBER): 1

Predicate Information (identified by operation id):
—————————————————

2 – access(“ID”=:ID)

SQL_ID  g852rfbbqn2f9, child number 2
————————————-
select * from t2 where id=:id

Plan hash value: 3119810522

————————————————————————————-
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
————————————————————————————-
|   0 | SELECT STATEMENT            |       |       |       |     2 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| T2    |     1 |   104 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T2_ID |     1 |       |     1   (0)| 00:00:01 |
————————————————————————————-

Peeked Binds (identified by position):
————————————–

1 – :ID (NUMBER): 50

Predicate Information (identified by operation id):
—————————————————

2 – access(“ID”=:ID)

71 rows selected.

–Oracle is not BLIND now even bind variable is used if there is accurate statistics.

Step by step test flashback data archives, a.k.a. Total Recall

–Flashback Data Archives, a.k.a. Total Recall
–  A Flashback Data Archive (Oracle Total Recall) provides the ability to track and store all transactional changes to a table over its lifetime.
–  Test version: 11.1.0.6

–create a system-wide default flashback archive on an existing tablespace.
conn / as sysdba
SYS@orcl11g>create flashback archive default fb tablespace example retention 1 year;
Flashback archive created.

–create test table t
conn t/t@orcl11g
create table t as select * from dba_objects;

T@orcl11g>alter table t flashback archive;
Table altered.

T@orcl11g>select systimestamp from dual;
SYSTIMESTAMP
———————————————————-
24-NOV-08 04.05.49.182000 PM +08:00

T@orcl11g>select timestamp_to_scn(systimestamp) from dual;
TIMESTAMP_TO_SCN(SYSTIMESTAMP)
——————————
1052630  –created point

–insert 1 time
T@orcl11g>insert into t select * from t;
68865 rows created.
T@orcl11g>commit;
Commit complete.
T@orcl11g>select current_scn from v$database;
CURRENT_SCN
———–
1052723  –test point A

–insert 2 times
T@orcl11g>insert into t select * from t;
137730 rows created.
T@orcl11g>insert into t select * from t;
275460 rows created.
T@orcl11g>commit;
Commit complete.
T@orcl11g>select current_scn from v$database;
CURRENT_SCN
———–
1054928  –test point B

–insert another time

T@orcl11g>insert into t select * from t;
550920 rows created.
T@orcl11g>commit;
Commit complete.
T@orcl11g>select current_scn from v$database;
CURRENT_SCN
———–
1056385  –test point C

–check count(*) of T at created point, point A, B and C
T@orcl11g>select count(*) from t as of scn 1052630;
COUNT(*)
———-
68865  –start count

–you can also use timestamp to check
T@orcl11g>select count(*) from t as of timestamp to_timestamp_tz(‘24-NOV-08 04.05.49.182000 PM +08:00′,’DD-Mon-RR HH:MI:SS.FF AM TZH:TZM’);
COUNT(*)
———-
68865  –start count

T@orcl11g>select count(*) from t as of scn 1052723;
COUNT(*)
———-
137730    –point A, doubled

T@orcl11g>select count(*) from t as of scn 1054928;
COUNT(*)
———-
550920  –point B, doubled 2 times comparing to A

T@orcl11g>select count(*) from t as of scn 1056385;

COUNT(*)
———-
1101840  –point C, doubled comparing to B

–it is exactly expected result! You may test it againt a long time period.

–Let’s check the under line view
–dba_flashback_archive includes all flashback archive defined in the db
T@orcl11g>select * from dba_flashback_archive;
FLASHBACK_ FLASHBACK_ARCHIVE# RETENTION_IN_DAYS CREATE_TIME
———- —————— —————– ———————————–
———————–
LAST_PURGE_TIME                                                             STATUS
————————————————————————— ——-
FB                          1               365 24-NOV-08 04.03.14.000000000 PM
24-NOV-08 04.03.14.000000000 PM                                             DEFAULT

–dba_flashback_archive_ts includes tablespaces information related to falshback archive
–you can have more than 1 tablespace in a flashback archive
T@orcl11g>select * from dba_flashback_archive_ts;

FLASHBACK_ FLASHBACK_ARCHIVE# TABLESPACE_NAME      QUOTA_IN_M
———- —————— ——————– ———-
FB                          1 EXAMPLE

–dba_flashback_archive_tables inculdes tables information
T@orcl11g>select * from dba_flashback_archive_tables;

TABLE_NAME OWNER_NAME FLASHBACK_ARCHIVE_NAME    ARCHIVE_TABLE_NAME
———- ———- ————————- ——————-
T          T          FB                        SYS_FBA_HIST_70992

–let’s clean up
T@orcl11g>alter table t no flashback archive;
Table altered.
T@orcl11g>select * from dba_flashback_archive_tables;
no rows selected    –Table is removed

conn / as sysdba
SYS@orcl11g>drop flashback archive fb;
Flashback archive dropped.
SYS@orcl11g>select * from dba_flashback_archive;
no rows selected  –fb is dropped
SYS@orcl11g>select * from dba_flashback_archive_ts;
no rows selected  –related tablspace information is disappear, but the tablespace still exists

–Limitations:
–These DDL Statements Not Allowed on Tables Enabled for Flashback Data Archive

**ALTER TABLE statement that does any of the following:
Drops, renames, or modifies a column
Performs partition or subpartition operations
Converts a LONG column to a LOB column
Includes an UPGRADE TABLE clause, with or without an INCLUDING DATA clause
**DROP TABLE statement
**RENAME TABLE statement
**TRUNCATE TABLE statement


–Sql statement reference

-Create a default Flashback Data Archive named fla1 that uses up to 10 G of tablespace tbs1, whose data will be retained for one year:
CREATE FLASHBACK ARCHIVE DEFAULT fla1 TABLESPACE tbs1 QUOTA 10G RETENTION 1 YEAR;

–Create a Flashback Data Archive named fla2 that uses tablespace tbs2, whose data will be retained for two years:
CREATE FLASHBACK ARCHIVE fla2 TABLESPACE tbs2 RETENTION 2 YEAR;

–Make Flashback Data Archive fla1 the default Flashback Data Archive:
ALTER FLASHBACK ARCHIVE fla1 SET DEFAULT;

–To Flashback Data Archive fla1, add up to 5 G of tablespace tbs3:
ALTER FLASHBACK ARCHIVE fla1 ADD TABLESPACE tbs3 QUOTA 5G;

–To Flashback Data Archive fla1, add as much of tablespace tbs4 as needed:
ALTER FLASHBACK ARCHIVE fla1 ADD TABLESPACE tbs4;

–Change the maximum space that Flashback Data Archive fla1 can use in tablespace tbs3 to 20 G:
ALTER FLASHBACK ARCHIVE fla1 MODIFY TABLESPACE tbs3 QUOTA 20G;

–Allow Flashback Data Archive fla1 to use as much of tablespace tbs1 as needed:
ALTER FLASHBACK ARCHIVE fla1 MODIFY TABLESPACE tbs1;

–Change the retention time for Flashback Data Archive fla1 to two years:
ALTER FLASHBACK ARCHIVE fla1 MODIFY RETENTION 2 YEAR;

–Remove tablespace tbs2 from Flashback Data Archive fla1:
ALTER FLASHBACK ARCHIVE fla1 REMOVE TABLESPACE tbs2;

–Purge all historical data from Flashback Data Archive fla1:
ALTER FLASHBACK ARCHIVE fla1 PURGE ALL;

–Purge all historical data older than one day from Flashback Data Archive fla1:
ALTER FLASHBACK ARCHIVE fla1
PURGE BEFORE TIMESTAMP (SYSTIMESTAMP – INTERVAL ‘1′ DAY);

–Purge all historical data older than SCN 728969 from Flashback Data Archive fla1:
ALTER FLASHBACK ARCHIVE fla1 PURGE BEFORE SCN 728969;

–Remove Flashback Data Archive fla1 and all its historical data, but not its tablespaces:
DROP FLASHBACK ARCHIVE fla1;

–Create table employee and store the historical data in the default Flashback Data Archive:
CREATE TABLE employee (EMPNO NUMBER(4) NOT NULL, ENAME VARCHAR2(10)) FLASHBACK ARCHIVE;

–Create table employee and store the historical data in the Flashback Data Archive fla1:
CREATE TABLE employee (EMPNO NUMBER(4) NOT NULL, ENAME VARCHAR2(10)) FLASHBACK ARCHIVE fla1;

–Enable flashback archiving for the table employee and store the historical data in the default Flashback Data Archive:
ALTER TABLE employee FLASHBACK ARCHIVE;

–Enable flashback archiving for the table employee and store the historical data in the Flashback Data Archive fla1:
ALTER TABLE employee FLASHBACK ARCHIVE fla1;

–Disable flashback archiving for the table employee:
ALTER TABLE employee NO FLASHBACK ARCHIVE;

Step by step test 11g new partition methods

DB version: 11.1.0.6

–new partition methods, ** are tested
**interval partition
**referencial partition
**virtual column partition
**system partition

*other new composite partitions
*Range-Range
*List-Range
*List-Hash
*List-List
*Interval-Range
*Interval-Hash
*Interval-List
*partition advisor, part of the SQL Access Advisor
*partition mode data pump, tables=[schema].[table_name].[partiton_name], PARTITION_OPTIONS = {NONE | DEPARTITION | MERGE}


–**interval partition, a kind of range partition

–use a sale table as example
create table sales
(prod_id        NUMBER,
cust_id        NUMBER,
time_id        DATE
)
PARTITION BY RANGE (time_id)
INTERVAL(NUMTOYMINTERVAL(1, ‘MONTH’)) STORE IN (USERS,DATA)
( PARTITION p1 VALUES LESS THAN (TO_DATE(‘2007-1-1′, ‘YYYY-MM-DD’)),
PARTITION p2 VALUES LESS THAN (TO_DATE(‘2008-11-15′, ‘YYYY-MM-DD’))
);
–p1 and p2 are different wide partition
–2008-11-15 is the transition point
–abover it each partition will be created with the same width 1 month

–let’s add data
INSERT INTO SALES VALUES (1,1,TO_DATE(‘2006-09-02′,’YYYY-MM-DD’));
INSERT INTO SALES VALUES (2,2,TO_DATE(‘2008-10-14′,’YYYY-MM-DD’));
INSERT INTO SALES VALUES (2,2,TO_DATE(‘2008-11-08′,’YYYY-MM-DD’));
INSERT INTO SALES VALUES (3,3,TO_DATE(‘2008-12-16′,’YYYY-MM-DD’));
INSERT INTO SALES VALUES (3,3,TO_DATE(‘2008-12-26′,’YYYY-MM-DD’));
commit;

–check partitions available
T@ONASM>SELECT PARTITION_NAME,TABLESPACE_NAME FROM DBA_SEGMENTS WHERE SEGMENT_NAME=’SALES’

PARTITION_NAME                 TABLESPACE_NAME
—————————— ——————–
P1                             USERS
P2                             USERS
SYS_P41                        DATA

T@ONASM>select * from SALES PARTITION (p1);

PROD_ID    CUST_ID TIME_ID
———- ———- ——————
1          1 02-SEP-06  –each data before 2007-1-1 in this partition

T@ONASM>select * from SALES PARTITION (p2);

PROD_ID    CUST_ID TIME_ID
———- ———- ——————
2          2 14-OCT-08
2          2 08-NOV-08  –each data before 2008-11-15 in this partition, it is predefined

T@ONASM>select * from SALES PARTITION (SYS_P41);

PROD_ID    CUST_ID TIME_ID
———- ———- ——————
3          3 16-DEC-08
3          3 26-DEC-08  –they are in the same partition

–we can also use another approach “partition for” to access interval partion
T@ONASM>select * from sales partition for(TO_DATE(‘2008-12-20′,’YYYY-MM-DD’));

PROD_ID    CUST_ID TIME_ID
———- ———- ——————
3          3 16-DEC-08
3          3 26-DEC-08

–check the partition value range
T@ONASM>select PARTITION_NAME,HIGH_VALUE from dba_tab_partitions where TABLE_NAME=’SALES’;
PARTITION_NAME                 HIGH_VALUE
—————————— ——————————————————————————–
P1                             TO_DATE(‘ 2007-01-01 00:00:00′, ‘SYYYY-MM-DD HH24:MI:SS’, ‘NLS_CALENDAR=GREGORIA
P2                             TO_DATE(‘ 2008-11-15 00:00:00′, ‘SYYYY-MM-DD HH24:MI:SS’, ‘NLS_CALENDAR=GREGORIA
SYS_P41                        TO_DATE(‘ 2009-01-15 00:00:00′, ‘SYYYY-MM-DD HH24:MI:SS’, ‘NLS_CALENDAR=GREGORIA
–The intermediate partition is not created

–let’s add a partition in the hole betweeen P2 and SYS_P41
T@ONASM>INSERT INTO SALES VALUES (3,3,TO_DATE(‘2008-12-14′,’YYYY-MM-DD’));

–check value range again
T@ONASM>select PARTITION_NAME,HIGH_VALUE from dba_tab_partitions where TABLE_NAME=’SALES’;
PARTITION_NAME                 HIGH_VALUE
—————————— ——————————————————————————–
P1                             TO_DATE(‘ 2007-01-01 00:00:00′, ‘SYYYY-MM-DD HH24:MI:SS’, ‘NLS_CALENDAR=GREGORIA
P2                             TO_DATE(‘ 2008-11-15 00:00:00′, ‘SYYYY-MM-DD HH24:MI:SS’, ‘NLS_CALENDAR=GREGORIA
SYS_P41                        TO_DATE(‘ 2009-01-15 00:00:00′, ‘SYYYY-MM-DD HH24:MI:SS’, ‘NLS_CALENDAR=GREGORIA
SYS_P61                        TO_DATE(‘ 2008-12-15 00:00:00′, ‘SYYYY-MM-DD HH24:MI:SS’, ‘NLS_CALENDAR=GREGORIA

T@ONASM>SELECT PARTITION_NAME,TABLESPACE_NAME FROM DBA_SEGMENTS WHERE SEGMENT_NAME=’SALES’;
PARTITION_NAME                 TABLESPACE_NAME
—————————— ——————–
P1                             USERS
P2                             USERS  –the predefined partition are always using the first tablespace
SYS_P41                        DATA   –you can see tablespace usage start with round-robin fashion
SYS_P61                        USERS

–The system-generated partition name can be changed
ALTER TABLE SALES RENAME PARTITION SYS_P41 to p_200901;

–an existing partitioned table can be altered to an interval-partitioned table
ALTER TABLE customers SET INTERVAL (NUMTOYMINTERVAL (1, ‘MONTH’));

–interval partition limitations:
–  can only use 1 partition key column, NUMBER or DATA type only
–  at least one partition must be specified
–  not support index-organized tables
–  MAXVALUES is not allowed
–  partition key cannot have null values
–  cannot manually add partitions
–  cannot used with reference partition


–**reference partition
–using orders and order_items as example

CREATE TABLE orders
( order_id           NUMBER(12),
order_date         DATE,
customer_id        NUMBER(6),
CONSTRAINT orders_pk PRIMARY KEY(order_id)
)
PARTITION BY RANGE(order_date)
( PARTITION Q1_2008 VALUES LESS THAN (TO_DATE(‘2008-04-01′,’YYYY-MM-DD’)),
PARTITION Q2_2008 VALUES LESS THAN (TO_DATE(‘2008-07-01′,’YYYY-MM-DD’)),
PARTITION Q3_2008 VALUES LESS THAN (TO_DATE(‘2008-10-01′,’YYYY-MM-DD’)),
PARTITION Q4_2008 VALUES LESS THAN (TO_DATE(‘2009-01-01′,’YYYY-MM-DD’))
);

CREATE TABLE order_items
( order_id           NUMBER(12) NOT NULL,
line_item_id       NUMBER(3)  NOT NULL,
product_id         NUMBER(6)  NOT NULL,
unit_price         NUMBER(8,2),
quantity           NUMBER(8),
CONSTRAINT order_items_fk
FOREIGN KEY(order_id) REFERENCES orders(order_id)
)
PARTITION BY REFERENCE(order_items_fk);

–check the partitions
T@ONASM>SELECT SEGMENT_NAME,PARTITION_NAME FROM DBA_SEGMENTS WHERE SEGMENT_NAME IN (‘ORDERS’,'ORDER_ITEMS’);

SEGMENT_NAME         PARTITION_NAME
——————– ——————————
ORDERS               Q1_2008
ORDERS               Q2_2008
ORDERS               Q3_2008
ORDERS               Q4_2008
ORDER_ITEMS          Q1_2008  –exactly what we expected
ORDER_ITEMS          Q2_2008
ORDER_ITEMS          Q3_2008
ORDER_ITEMS          Q4_2008

8 rows selected.

–insert data to test
insert into orders values (1,TO_DATE(‘2008-03-03′,’YYYY-MM-DD’),1);
insert into orders values (2,TO_DATE(‘2008-06-03′,’YYYY-MM-DD’),2);
insert into orders values (3,TO_DATE(‘2008-09-03′,’YYYY-MM-DD’),3);
insert into orders values (4,TO_DATE(‘2008-12-03′,’YYYY-MM-DD’),4);
insert into order_items values (1,1,1,1,1);
insert into order_items values (2,2,2,2,2);
insert into order_items values (3,3,3,3,3);
insert into order_items values (4,4,4,4,4);
commit;

–check data in partition
T@ONASM>select * from order_items partition (Q1_2008);
ORDER_ID LINE_ITEM_ID PRODUCT_ID UNIT_PRICE   QUANTITY
———- ———— ———- ———- ———-
1            1          1          1          1
T@ONASM>select * from order_items partition (Q2_2008);
ORDER_ID LINE_ITEM_ID PRODUCT_ID UNIT_PRICE   QUANTITY
———- ———— ———- ———- ———-
2            2          2          2          2
T@ONASM>select * from order_items partition (Q3_2008);
ORDER_ID LINE_ITEM_ID PRODUCT_ID UNIT_PRICE   QUANTITY
———- ———— ———- ———- ———-
3            3          3          3          3
T@ONASM>select * from order_items partition (Q4_2008);
ORDER_ID LINE_ITEM_ID PRODUCT_ID UNIT_PRICE   QUANTITY
———- ———— ———- ———- ———-
4            4          4          4          4
–it is exactly as expected

–reference partition limitation: cannot used with interval partition
–benefit: avoids having to duplicate the partition-key column, partition-wise join
–         automatically maintain partitions at the same time


–**virtual column partition, all partition methods are supported using virtual columns.

–use a employee table as example
create table employee (
employee_id number,
name  varchar2(20),
title varchar2(40),
emp_year as (trunc(employee_id,-4)/10000)
)
PARTITION BY RANGE (emp_year) INTERVAL (1)
( PARTITION p1 VALUES LESS THAN (2006)
);

-let’s add data, suppose the first 4 digit of employee_id is represent year.
insert into employee(employee_id,name,title) values (20062023,’Alex’,'dba’);
insert into employee(employee_id,name,title) values (20070001,’Daniel’,'ceo’);
insert into employee(employee_id,name,title) values (20080201,’Susan’,’secretary’);
insert into employee(employee_id,name,title) values (20080520,’Tom’,'accountant’);
commit;

–let’s check the partition available
T@ONASM>select PARTITION_NAME,HIGH_VALUE from dba_tab_partitions where TABLE_NAME=’EMPLOYEE’;

PARTITION_NAME                 HIGH_VALUE
—————————— ————————————————————–
P1                             2006
SYS_P81                        2007
SYS_P82                        2008
SYS_P83                        2009

–let’s check the data
T@ONASM>select * from employee partition (p1);

no rows selected

T@ONASM>select * from employee partition (SYS_P81);

EMPLOYEE_ID NAME                 TITLE                                      EMP_YEAR
———– ——————– —————————————- ———-
20062023 Alex                 dba                                            2006

T@ONASM>select * from employee partition (SYS_P82);

EMPLOYEE_ID NAME                 TITLE                                      EMP_YEAR
———– ——————– —————————————- ———-
20070001 Daniel               ceo                                            2007

T@ONASM>select * from employee partition (SYS_P83);

EMPLOYEE_ID NAME                 TITLE                                      EMP_YEAR
———– ——————– —————————————- ———-
20080201 Susan                secretary                                      2008
20080520 Tom                  accountant                                     2008

–good, it is just as expected!
–vitual column partition comments:
– vitual column stored as metadata only
– can be used in queries, DML, DDL statements
– can be indexed
– can have statistics collected on them
– limitation: cannot call PL/SQL function
–     Cannot update, insert to a virtual column
–     The virtual column cannot reference another virtual column
–     All columns referenced in the expression for the virtual column
–     must exist in the same table
–     The output of the column expression must be a scalar value


–**system partition, application-controlled partitioning, database do not control the data placement.
– an insertion into a system partitioned table without the explicit specification of a partition will fail.

CREATE TABLE credits (name varchar2(20), telephone number)
PARTITION BY SYSTEM
(
PARTITION p_good,
PARTITION p_fair,
PARTITION p_bad
);

INSERT INTO credits PARTITION (p_good) VALUES (‘Alex’,50002563);
INSERT INTO credits PARTITION (p_fair) VALUES (‘Susan’,67002587);
INSERT INTO credits PARTITION (p_bad) VALUES (‘Daniel’,85892095);

–if you don’t specify the partition name
T@ONASM>INSERT INTO credits VALUES (‘Bob’,12345678);
INSERT INTO credits VALUES (‘Bob’,12345678)
*
ERROR at line 1:
ORA-14701: partition-extended name or bind variable must be used for DMLs on tables partitioned by the System method

–delete and update do not require partition syntax, but if specified, partition pruning is the benefit

–you can use bind variable to specify the partition name
T@ONASM>SELECT SUBOBJECT_NAME,OBJECT_ID FROM USER_OBJECTS WHERE object_name=’CREDITS’ AND OBJECT_TYPE=’TABLE PARTITION’;

SUBOBJECT_NAME                  OBJECT_ID
—————————— ———-
P_BAD                               12503
P_FAIR                              12502
P_GOOD                              12501

T@ONASM>var partition_id number
T@ONASM>exec :partition_id :=12501

PL/SQL procedure successfully completed.

T@ONASM>insert into credits partition(dataobj_to_partition(“CREDITS”, :partition_id)) values (‘Tom’,98765432);

1 row created.

T@ONASM>commit;

Commit complete.

T@ONASM>select * from credits partition (p_good);

NAME                  TELEPHONE
——————– ———-
Alex                   50002563
Tom                    98765432  –it is here

–it is not SYSTEM. It is actually do it yourself, :)