Saturday, December 20, 2014

Partitioning made easy



One of the nice features in Oracle 12c is the easier mainteannace of partitioning operations. 

In pre-12c oracle databases , to add , split , merge the partitions ,  the commands has to be done per partition .  Starting with Oracle 12c , the operations can be done in one single statement.

Let us see an example.

We will create a table range based partitioned table called t_part with two partitions.




SQL> Create table t_part
 2  ( productcode  int ,  productname varchar2(150) , company varchar2(150))
 3  partition by range (productcode)
 4  (
 5  partition product_1000 values less than (1000) ,
 6  partition product_2000 values less than (2000)
 7  )
 8  ;


Table created.




To add partitions in prior to 12c , we would need to issue three statements as below.

SQL> alter table t_part
 2  add partition product_3000 values less than ( 3000) ;


Table altered.

SQL> alter table t_part
 2  add partition product_4000 values less than ( 4000) ;

Table altered.

SQL> alter table t_part
 2  add partition product_5000 values less than ( 5000) ;

Table altered.

For the similar operations in oracle 12c , we can do it in one statement as below. 
In the following example , I am adding five partitions in one statement.


SQL> alter table t_part
 2  add
 3  partition product_6000 values less than ( 6000) ,
 4  partition product_7000 values less than ( 7000) ,
 5  partition product_8000 values less than ( 8000) ,
 6  partition product_9000 values less than ( 9000),
 7  partition product_10000 values less than ( 10000),
 8  partition product_15000 values less than ( 15000)
 9  ;

Table altered.


SQL> insert into t_part
 2  select object_id as productcode
 3  , object_name as productname
 4  , owner as company from all_objects
 5  where object_id <15000 span="">
 6  ;

14602 rows created.
SQL> exec dbms_stats.gather_table_stats ( user , 'T_PART') ;
PL/SQL procedure successfully completed.

SQL> select  table_name , partition_name , num_rows ,
 2  last_analyzed
 3  from user_tab_partitions where table_name ='T_PART'
 4  order by 2 ;

TABLE_NAME PARTITION_NAME         NUM_ROWS LAST_ANAL
---------- -------------------- ---------- ---------
T_PART     PRODUCT_1000                889 20-DEC-14
T_PART     PRODUCT_10000               986 20-DEC-14
T_PART     PRODUCT_15000              4978 20-DEC-14
T_PART     PRODUCT_2000                924 20-DEC-14
T_PART     PRODUCT_3000               1000 20-DEC-14
T_PART     PRODUCT_4000               1000 20-DEC-14
T_PART     PRODUCT_5000               1000 20-DEC-14
T_PART     PRODUCT_6000                985 20-DEC-14
T_PART     PRODUCT_7000                944 20-DEC-14
T_PART     PRODUCT_8000                928 20-DEC-14
T_PART     PRODUCT_9000                968 20-DEC-14

11 rows selected.


Similarly , I can split the partition in one statement as well as shown below.





SQL> alter table t_part
 2  split
 3  partition product_15000
 4  into
 5  (
 6  partition product_11000 values less than ( 11000) ,
 7  partition product_12000 values less than ( 12000) ,
 8  partition product_13000 values less than ( 13000) ,
 9  partition product_14000 values less than ( 14000) ,
10  partition product_15000
11  ) ;


Table altered.

SQL> select  table_name , partition_name , num_rows ,
 2  last_analyzed
 3  from user_tab_partitions where table_name ='T_PART'
 4  order by 2 ;

TABLE_NAME PARTITION_NAME         NUM_ROWS LAST_ANAL
---------- -------------------- ---------- ---------
T_PART     PRODUCT_1000                889 20-DEC-14
T_PART     PRODUCT_10000               986 20-DEC-14
T_PART     PRODUCT_11000
T_PART     PRODUCT_12000
T_PART     PRODUCT_13000
T_PART     PRODUCT_14000
T_PART     PRODUCT_15000
T_PART     PRODUCT_2000                924 20-DEC-14
T_PART     PRODUCT_3000               1000 20-DEC-14
T_PART     PRODUCT_4000               1000 20-DEC-14
T_PART     PRODUCT_5000               1000 20-DEC-14

TABLE_NAME PARTITION_NAME         NUM_ROWS LAST_ANAL
---------- -------------------- ---------- ---------
T_PART     PRODUCT_6000                985 20-DEC-14
T_PART     PRODUCT_7000                944 20-DEC-14
T_PART     PRODUCT_8000                928 20-DEC-14
T_PART     PRODUCT_9000                968 20-DEC-14

15 rows selected.


This enhancement is one of the best in Oracle 12c.

Welcome your comments.

Monday, December 15, 2014

Filtered index in SQL Server / Oracle's equivalent



One of my favorite things in SQL Server is Filtered index .  Filtered index helps us in higher selectivity and also in decreased storage consumption , if the  query criteria looks only for pre defined. sub set of data . 

Let us say , you got a table of 50 million records , out of which only 50,000 are active records  and your application only looks for active records . Then filtered index will make much more sense . 

Here is an example. 



 

 


As you can see , there is a significant difference in the index size. 
The query optimizer uses the second indexes , whenever , there is query looks for any ACTIVE product. 































In Oracle  , we can simulate the filtered index with Function Based Index . 


SQL> drop table t purge ;

Table dropped.

SQL> Create table t as select * from all_objects ;

Table created.

SQL> Create index idx1_t on t( owner , object_type ) ;

Index created.

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

PL/SQL procedure successfully completed.

SQL> analyze index idx1_t validate structure ;

Index analyzed.

SQL> col name format a15
SQL> Select name , height , blocks , lf_rows , lf_blks , btree_space , used_space  from index_stats ;

NAME                HEIGHT     BLOCKS    LF_ROWS    LF_BLKS BTREE_SPACE USED_SPACE
--------------- ---------- ---------- ---------- ---------- ----------- ----------
IDX1_T                   3        384      93172        336     2712096    2415824


Now , let us create a FBI , where I am interested only in 'MATERIALIZED VIEW' of a user. 

SQL> Create index idx2_t on t( owner , case when object_type = 'MATERIALIZED VIEW' then 'MATERIALIZED VIEW' end ) ;

Index created.

SQL> analyze index idx2_t validate structure ;

Index analyzed.

SQL> Select name , height , blocks , lf_rows , lf_blks , btree_space , used_space  from index_stats ;

NAME                HEIGHT     BLOCKS    LF_ROWS    LF_BLKS BTREE_SPACE USED_SPACE
--------------- ---------- ---------- ---------- ---------- ----------- ----------
IDX2_T                   2        256      93172        232     1864032    1664870


As you can see, the storage has decreased from 2712096 to 1864032  , leaf blocks from 336 to 232 and also like the height of the index from 3 to 2 , which helps the optimizer to relatively find the data faster. 


Comments welcome.




Thursday, December 11, 2014

Minimize logging for Data Pump Import - IMPDP



Starting in Oracle 12c, we  can disable ( well ... minimize) the logging by setting the new setting in the TRANFORM parameter . Logging is not totally eliminated but it will be minimal . This setting has no effect if the database is in FORCE LOGGING mode. 

This is useful in loading large data sets or creating new databases .  With this setting , you can minimize the logging for table or index or both. 

if we look at the help at the command prompt ( impdp -help) , we can see there are few settings have added. 

11g 


TRANSFORM
Metadata transform to apply to applicable objects.
Valid keywords are: OID, PCTSPACE, SEGMENT_ATTRIBUTES and STORAGE.


12c

TRANSFORM
Metadata transform to apply to applicable objects.
Valid keywords are: DISABLE_ARCHIVE_LOGGING, LOB_STORAGE, OID, PCTSPACE,

SEGMENT_ATTRIBUTES, STORAGE, and TABLE_COMPRESSION_CLAUSE.


Here are the examples.

In the following example , the logging is disabled for both table and index.

C:\>impdp zahir schemas=zahir directory=dataad dumpfile=zdata.dmp logfile=zdata.log  remap_schema=zahir:testuser transform=disable_archive_logging:Y

Import: Release 12.1.0.1.0 - Production on Thu Dec 11 14:33:04 2014

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

Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, Oracle Label Security, OLAP, Advanced Analytics
and Real Application Testing options
Master table "ZAHIR"."SYS_IMPORT_SCHEMA_01" successfully loaded/unloaded
Starting "ZAHIR"."SYS_IMPORT_SCHEMA_01":  zahir/******** schemas=zahir directory=dataad dumpfile=zdata.dmp logfile=zdata.log remap_schema=zahir:testuser transform=disable_archive_logging:Y
Processing object type SCHEMA_EXPORT/USER
ORA-31684: Object type USER:"TESTUSER" already exists
Processing object type SCHEMA_EXPORT/SYSTEM_GRANT
Processing object type SCHEMA_EXPORT/ROLE_GRANT
Processing object type SCHEMA_EXPORT/DEFAULT_ROLE
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processing object type SCHEMA_EXPORT/TABLE/TABLE
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
. . imported "TESTUSER"."ZAHIRTESTL"                     12.50 MB  110350 rows
Processing object type SCHEMA_EXPORT/TABLE/INDEX/INDEX
Processing object type SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
Processing object type SCHEMA_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Processing object type SCHEMA_EXPORT/STATISTICS/MARKER
Processing object type SCHEMA_EXPORT/POST_SCHEMA/PROCACT_SCHEMA
Job "ZAHIR"."SYS_IMPORT_SCHEMA_01" completed with 1 error(s) at Thu Dec 11 14:33:18 2014 elapsed 0 00:00:11

In the following example , the logging is disabled for table. 


C:\>impdp zahir schemas=zahir directory=dataad dumpfile=zdata.dmp logfile=zdata.log  remap_schema=zahir:testuser transform=disable_archive_logging:Y:TABLE

Import: Release 12.1.0.1.0 - Production on Thu Dec 11 14:34:27 2014

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

Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, Oracle Label Security, OLAP, Advanced Analytics
and Real Application Testing options
Master table "ZAHIR"."SYS_IMPORT_SCHEMA_01" successfully loaded/unloaded
Starting "ZAHIR"."SYS_IMPORT_SCHEMA_01":  zahir/******** schemas=zahir directory=dataad dumpfile=zdata.dmp logfile=zdata.log remap_schema=zahir:testuser transform=disable_archive_logging:Y:TABLE
Processing object type SCHEMA_EXPORT/USER
ORA-31684: Object type USER:"TESTUSER" already exists
Processing object type SCHEMA_EXPORT/SYSTEM_GRANT
Processing object type SCHEMA_EXPORT/ROLE_GRANT
Processing object type SCHEMA_EXPORT/DEFAULT_ROLE
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processing object type SCHEMA_EXPORT/TABLE/TABLE
ORA-39151: Table "TESTUSER"."ZAHIRTESTL" exists. All dependent metadata and data will be skipped due to table_exists_action of skip
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
Processing object type SCHEMA_EXPORT/TABLE/INDEX/INDEX
Processing object type SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
Processing object type SCHEMA_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Processing object type SCHEMA_EXPORT/STATISTICS/MARKER
Processing object type SCHEMA_EXPORT/POST_SCHEMA/PROCACT_SCHEMA
Job "ZAHIR"."SYS_IMPORT_SCHEMA_01" completed with 2 error(s) at Thu Dec 11 14:34:31 2014 elapsed 0 00:00:01


In the following example , the logging is disabled for index.

C:\>impdp zahir schemas=zahir directory=dataad dumpfile=zdata.dmp logfile=zdata.log  remap_schema=zahir:testuser transform=disable_archive_logging:Y:INDEX

Import: Release 12.1.0.1.0 - Production on Thu Dec 11 14:34:44 2014

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

Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, Oracle Label Security, OLAP, Advanced Analytics
and Real Application Testing options
Master table "ZAHIR"."SYS_IMPORT_SCHEMA_01" successfully loaded/unloaded
Starting "ZAHIR"."SYS_IMPORT_SCHEMA_01":  zahir/******** schemas=zahir directory=dataad dumpfile=zdata.dmp logfile=zdata.log remap_schema=zahir:testuser transform=disable_archive_logging:Y:INDEX
Processing object type SCHEMA_EXPORT/USER
ORA-31684: Object type USER:"TESTUSER" already exists
Processing object type SCHEMA_EXPORT/SYSTEM_GRANT
Processing object type SCHEMA_EXPORT/ROLE_GRANT
Processing object type SCHEMA_EXPORT/DEFAULT_ROLE
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processing object type SCHEMA_EXPORT/TABLE/TABLE
ORA-39151: Table "TESTUSER"."ZAHIRTESTL" exists. All dependent metadata and data will be skipped due to table_exists_action of skip
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
Processing object type SCHEMA_EXPORT/TABLE/INDEX/INDEX
Processing object type SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
Processing object type SCHEMA_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Processing object type SCHEMA_EXPORT/STATISTICS/MARKER
Processing object type SCHEMA_EXPORT/POST_SCHEMA/PROCACT_SCHEMA
Job "ZAHIR"."SYS_IMPORT_SCHEMA_01" completed with 2 error(s) at Thu Dec 11 14:34:47 2014 elapsed 0 00:00:01


I welcome your comments.