Skip to Main Content

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, mathias.

Asked: March 04, 2017 - 6:58 pm UTC

Last updated: February 14, 2018 - 1:44 am UTC

Version: 12c

Viewed 1000+ times

You Asked

Hi,

I am curious about the table statistics if I use In-Database Archiving. Are the statistics calculated including or excluding invisible rows?

Best regards,

Mathias

and Connor said...

Statistics will include the archived rows, but filtering by archive state is essentially just a normal predicate, so the optimizer can see that and take advantage of the column level stats on the archive state, eg


SQL> alter session set row archival visibility = active;

Session altered.

SQL> create table t (
  2         x int,
  3         y int
  4  )
  5  row archival;

Table created.

SQL>
SQL> insert into t values (1,2);

1 row created.

SQL> insert into t values (3,4);

1 row created.

SQL> insert into t values (5,6);

1 row created.

SQL> insert into t values (7,8);

1 row created.

SQL> insert into t values (9,10);

1 row created.

SQL> commit;

Commit complete.

SQL> exec dbms_stats.gather_table_stats('','T')

PL/SQL procedure successfully completed.

SQL> select num_rows from user_tables where table_name = 'T';

  NUM_ROWS
----------
         5

1 row selected.

SQL>
SQL> select * from t;

         X          Y
---------- ----------
         1          2
         3          4
         5          6
         7          8
         9         10

5 rows selected.

SQL> update t set ora_archive_state=dbms_ilm.archivestatename(1) where x in (3,5);

2 rows updated.

SQL> exec dbms_stats.gather_table_stats('','T')

PL/SQL procedure successfully completed.

SQL> select num_rows from user_tables where table_name = 'T';

  NUM_ROWS
----------
         5

1 row selected.

SQL>
SQL>
SQL> set autotrace traceonly explain
SQL> select t1.* from t t1;

Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     3 |    24 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T    |     3 |    24 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

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

   1 - filter("T1"."ORA_ARCHIVE_STATE"='0')

SQL>
SQL> alter session set row archival visibility = all;

Session altered.

SQL> select t2.* from t t2;

Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     5 |    30 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| T    |     5 |    30 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

SQL>
SQL>


Rating

  (8 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Performance Impact?

Wayne Phillips, January 16, 2018 - 9:26 am UTC

What Performance benefit (IF ANY) would this "Optimizer Predicate Filter" of data in an archive state, have on:
Execution Plans, Retrieval Speed and Response Times?

Or is this feature simply to Enable an ILM/Archive strategy?
Connor McDonald
January 16, 2018 - 1:01 pm UTC

You could partition on this attribute to take advantage of partition elimination

SQL> create table t (
  2             x int,
  3             y int
  4      )
  5      row archival
  6      enable row movement
  7  partition by list ( ORA_ARCHIVE_STATE )
  8  (
  9    partition p1 values ('1'),
 10    partition p2 values ('0')
 11  );

Table created.


How to proceed if the table is already partititoned?

A reader, January 16, 2018 - 5:49 pm UTC

Hi,

What do you suggest if the table is already partitioned (not partitioned on ora_achive column).

Regards!!
Chris Saxon
January 18, 2018 - 1:47 pm UTC

You can retain your current partitioning strategy and use subpartitions:

create table t (
  x int,
  y int
) row archival enable row movement
partition by hash (x) 
subpartition by list ( ORA_ARCHIVE_STATE )
subpartition template
(
  subpartition p1 values ('1'),
  subpartition p2 values ('0')
) partitions 4;


Or the other way around:

create table t (
  x int,
  y int
) row archival enable row movement
partition by list ( ORA_ARCHIVE_STATE )
subpartition by hash (x) subpartitions 4 (
  partition p1 values ('1'),
  partition p2 values ('0')
);

for Partitioned Tables

Rajeshwaran, Jeyabal, January 17, 2018 - 1:39 pm UTC

In Database archiving is still possible on Partitioned Tables.

Think of In-Database archiving as something like this.

Rather than deleting the data, some application has the concept of “mark for delete”, so that data remains in table, but not used by application – this can be achieved by doing

a) Add an extra column to table – that holds a flag to indicate the data is deleted.

b) Add an extra column to SQL – that checks to exclude the deleted(inactive) rows from processing ( where deleted <> ‘N’)

In database archiving is a feature added up in 12c to allow this type of “mark for delete” functionality with few changes to application code


Rows that have been marked as archived are not visible (equivalent to a logical delete) unless the session is enabled to see archived data.

so think of In-Database archival as something equivalent to a logical deletes. no clean up of old data in tables (no physical delete), no more white space in tables, no more index rebuilds for table data cleanup.

demo@ORA12C> create table t
  2  partition by hash(object_id)
  3  ( partition p1, partition p2 )
  4  as
  5  select owner,object_id,object_name,object_type
  6  from all_objects
  7  where rownum <=10;

Table created.

demo@ORA12C> alter table t row archival;

Table altered.

demo@ORA12C> column ora_archive_state format a10
demo@ORA12C> select t.*,ora_archive_state from t;

OWNER       OBJECT_ID OBJECT_NAME                    OBJECT_TYPE             ORA_ARCHIV
---------- ---------- ------------------------------ ----------------------- ----------
SYS               133 ORA$BASE                       EDITION                 0
PUBLIC            143 DUAL                           SYNONYM                 0
SYS               417 MAP_OBJECT                     TABLE                   0
SYS               523 TABLE_PRIVILEGE_MAP            TABLE                   0
SYS               524 I_TABLE_PRIVILEGE_MAP          INDEX                   0
SYS               142 DUAL                           TABLE                   0
PUBLIC            418 MAP_OBJECT                     SYNONYM                 0
SYS               520 SYSTEM_PRIVILEGE_MAP           TABLE                   0
SYS               521 I_SYSTEM_PRIVILEGE_MAP         INDEX                   0
PUBLIC            522 SYSTEM_PRIVILEGE_MAP           SYNONYM                 0

10 rows selected.

demo@ORA12C> update t
  2  set ora_archive_state = dbms_ilm.archiveStateName(1)
  3  where object_id <=200;

3 rows updated.

demo@ORA12C> select t.*,ora_archive_state from t;

OWNER       OBJECT_ID OBJECT_NAME                    OBJECT_TYPE             ORA_ARCHIV
---------- ---------- ------------------------------ ----------------------- ----------
SYS               417 MAP_OBJECT                     TABLE                   0
SYS               523 TABLE_PRIVILEGE_MAP            TABLE                   0
SYS               524 I_TABLE_PRIVILEGE_MAP          INDEX                   0
PUBLIC            418 MAP_OBJECT                     SYNONYM                 0
SYS               520 SYSTEM_PRIVILEGE_MAP           TABLE                   0
SYS               521 I_SYSTEM_PRIVILEGE_MAP         INDEX                   0
PUBLIC            522 SYSTEM_PRIVILEGE_MAP           SYNONYM                 0

7 rows selected.

demo@ORA12C> alter session set row archival visibility=all;

Session altered.

demo@ORA12C> select t.*,ora_archive_state from t;

OWNER       OBJECT_ID OBJECT_NAME                    OBJECT_TYPE             ORA_ARCHIV
---------- ---------- ------------------------------ ----------------------- ----------
SYS               133 ORA$BASE                       EDITION                 1
PUBLIC            143 DUAL                           SYNONYM                 1
SYS               417 MAP_OBJECT                     TABLE                   0
SYS               523 TABLE_PRIVILEGE_MAP            TABLE                   0
SYS               524 I_TABLE_PRIVILEGE_MAP          INDEX                   0
SYS               142 DUAL                           TABLE                   1
PUBLIC            418 MAP_OBJECT                     SYNONYM                 0
SYS               520 SYSTEM_PRIVILEGE_MAP           TABLE                   0
SYS               521 I_SYSTEM_PRIVILEGE_MAP         INDEX                   0
PUBLIC            522 SYSTEM_PRIVILEGE_MAP           SYNONYM                 0

10 rows selected.

demo@ORA12C> alter session set row archival visibility=active;

Session altered.

demo@ORA12C> select t.*,ora_archive_state from t;

OWNER       OBJECT_ID OBJECT_NAME                    OBJECT_TYPE             ORA_ARCHIV
---------- ---------- ------------------------------ ----------------------- ----------
SYS               417 MAP_OBJECT                     TABLE                   0
SYS               523 TABLE_PRIVILEGE_MAP            TABLE                   0
SYS               524 I_TABLE_PRIVILEGE_MAP          INDEX                   0
PUBLIC            418 MAP_OBJECT                     SYNONYM                 0
SYS               520 SYSTEM_PRIVILEGE_MAP           TABLE                   0
SYS               521 I_SYSTEM_PRIVILEGE_MAP         INDEX                   0
PUBLIC            522 SYSTEM_PRIVILEGE_MAP           SYNONYM                 0

7 rows selected.

demo@ORA12C>

LiveSQL and VISIBILITY=ACTIVE

Duke Ganote, January 19, 2018 - 3:32 pm UTC

I tried a demo in LiveSQL, and the VISIBILITY=ACTIVE session alteration doesn't seem to work:

SCRIPT
create table EMP as select * from scott.emp;
alter table EMP add primary key ( empno );
alter table EMP row archival;
ALTER SESSION SET ROW ARCHIVAL VISIBILITY = ALL;
select deptno, count(*), sum(ora_archive_state) sum_hidden
  from EMP group by deptno order by 1;
UPDATE EMP
   SET ora_archive_state = '1'
 WHERE deptno = 20;
COMMIT;
ALTER SESSION SET ROW ARCHIVAL VISIBILITY = ACTIVE;
select deptno, count(*), sum(ora_archive_state) sum_hidden
  from EMP group by deptno order by 1;


Did I miss something? I see all the records, although some are marked:

RESULTS
Table created.

Table altered.

Table altered.

Statement processed.

Result Set 1
DEPTNO COUNT(*) SUM_HIDDEN
10 3 0
20 5 0
30 6 0
Download CSV
3 rows selected.

5 row(s) updated.

Statement processed.

Statement processed.

Result Set 2
DEPTNO COUNT(*) SUM_HIDDEN
10 3 0
20 5 5
30 6 0

3 rows selected.

RTFP: Read The Fine Print

Duke Ganote, January 19, 2018 - 4:02 pm UTC

As Vidar Eidissen noticed, the LiveSQL demo script suggests that VISIBILITY is undetermined. Explicitly it say:

"Note that the WHERE clause has been added for demonstration purposes in Live SQL. Outside the Live SQL environment the WHERE clause would not be needed because the ROW ARCHIVAL VISIBILITY session setting can be determined."

https://livesql.oracle.com/apex/livesql/docs/vldbg/indbarchive/indatabase-archiving-example.html
Chris Saxon
January 19, 2018 - 5:00 pm UTC

:)

Where is the ROW ARCHIVAL VISIBILITY parameter value stored?

Duke Ganote, February 06, 2018 - 9:34 pm UTC

I can't see to find it in V$PARAMETERS. How do I know what the current setting in my session?
Connor McDonald
February 07, 2018 - 12:59 am UTC

I'll ask around internally but I don't know of any way besides doing a small sample (kludgey I know):

SQL> create table t ( x int ) row archival;

Table created.

SQL> insert into t values (1);

1 row created.

SQL> update t set ora_archive_state=dbms_ilm.archivestatename(1);

1 row updated.

SQL>
SQL> select * From t;

no rows selected

SQL> alter session set row archival visibility = all;

Session altered.

SQL> select * From t;

         X
----------
         1


Kludgification

Duke Ganote, February 12, 2018 - 8:58 pm UTC

I guess kludge it is! ;)

drop table Z$_ROW_ARCHIVAL;
drop view Z$_ROW_ARCHIVAL_VISIBILITY;
create table Z$_ROW_ARCHIVAL ( visibility varchar2(10) primary key ) row archival;
insert into Z$_ROW_ARCHIVAL values ( 'active' );
insert into Z$_ROW_ARCHIVAL values ( 'all' );
UPDATE z$_ROW_ARCHIVAL
   SET ora_archive_state = '1'
 WHERE visibility = 'all'
 ;
 commit;
create view Z$_ROW_ARCHIVAL_VISIBILITY AS select max(visibility) as visibility from Z$_ROW_ARCHIVAL;
select * from Z$_ROW_ARCHIVAL_VISIBILITY;

VISIBILITY
----------
active

ALTER SESSION SET ROW ARCHIVAL VISIBILITY = active;

Session altered.

select * from Z$_ROW_ARCHIVAL_VISIBILITY;

VISIBILITY
----------
active

select * from z$_ROW_ARCHIVAL;

VISIBILITY
----------
active

ALTER SESSION SET ROW ARCHIVAL VISIBILITY = all;

Session altered.

select * from Z$_ROW_ARCHIVAL_VISIBILITY;

VISIBILITY
----------
all

select * from z$_ROW_ARCHIVAL;

VISIBILITY
----------
active
all

Connor McDonald
February 13, 2018 - 1:26 am UTC

I did a video on row archival and its impact on the optimizer



If it impacts the optimizer, then you'd expect to find information in V$SES_OPTIMIZER_ENV, or perhaps the underlying the internal objects that are to define V$SES_OPTIMIZER_ENV.

You get what I'm saying here :-)

I get what you're saying...

Duke Ganote, February 13, 2018 - 5:17 pm UTC

It's summer for you Antipodeans!

Setting that aside: I've poked at v$sql_optimizer_env, v$ses_optimizer_env, etc. Unfortunately I don't have access to the underlying objects.
Connor McDonald
February 14, 2018 - 1:44 am UTC

ping me at asktom_us@oracle.com :-)

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library