Here is a Method to Move Table or Schema Statistics to a Different Database using DBMS_STATS

Usually DBA face issue like unexpected execution plan by sql query. One of the common reason for this could be statistics of the table or schema which are chosen by optimizer at time of generating execution plan. Since this could be a production environment So Database Administrator can't do so much tweaking.

In this situation, One good idea is to Move Table or Schema Statistics to a Different Database using DBMS_STATS and do what ever research you wants to do. Database administrator can export a single table stats using dbms_stats.export_table_stats as well as whole schema status using dbms_stats.export_schema_stats.

One major advantage of moving Table or Schema Statistics is DBA will get same execution plan of queries at destination schema regardless of actual data stored at destination. This is because the Cost-Based Optimizer makes its decisions for obtaining  data on the basis of statistics. 


How to Move Table Statistics to a Different Database using DBMS_STATS ?


 Here are the main steps:

1. Create a table in database to hold statistics.
2. Move stats from Data dictionary to table created for Holding stats.
3. Take expdp dump of stats table and move to destination location.
4. Restore stats table using impdp.
5. Import table stats.


1. Create a Table in Database to hold statistics: We are making a table named "STATS" into SCOTT schema for holding table stats.

SQL> exec dbms_stats.create_stat_table('SCOTT','STATS');
PL/SQL procedure successfully completed.

SQL> desc stats;

 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 STATID                                             VARCHAR2(30)
 TYPE                                               CHAR(1)
 VERSION                                            NUMBER
 FLAGS                                              NUMBER
 C1                                                 VARCHAR2(30)
 ------------------------------------------------------------ 
 ------------------------------------------------------------ R2                                                 RAW(32)
 CH1                                                VARCHAR2(1000)
 CL1                                                CLOB

This table will store table stats.


2. Move Stats from Data dictionary to table created for Holding Stats: In this step DBA will move stats for an existing table (EXPORT_STATS) to table for holding table (STATS), Before that make sure DBA has gathered stats for main table like below.

SQL> select TABLE_NAME,NUM_ROWS,AVG_ROW_LEN,LAST_ANALYZED from user_tables where table_name like 'EXPORT_STATS';

TABLE_NAME                       NUM_ROWS AVG_ROW_LEN LAST_ANAL
------------------------------ ---------- ----------- ---------
EXPORT_STATS

SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT','EXPORT_STATS');
PL/SQL procedure successfully completed.

SQL> select TABLE_NAME,NUM_ROWS,AVG_ROW_LEN,LAST_ANALYZED from user_tables where table_name like 'EXPORT_STATS';
TABLE_NAME                       NUM_ROWS AVG_ROW_LEN LAST_ANAL
------------------------------ ---------- ----------- ---------
EXPORT_STATS                       585392          97 16-JUL-13


As first command output shows stats are not gathered for "EXPORT_STATS" table. Database Administrator should collect the table stats, this can also make an impact on current execution plan of queries running on this table. After gathering table status Now user_tables is updated with current stats of the table. Now DBA can take stats backup.

SQL> exec dbms_stats.export_table_stats('SCOTT','EXPORT_STATS',NULL,'STATS',NULL,TRUE);

PL/SQL procedure successfully completed.

Here, I have taken "EXPORT_STATS" stats backup into "STATS" table. To know more about export_table_stats.


3. Take Expdp backup of Stats Table and Move to Destination Location:  To restore table stats to a table on another server take backup of stats than and then copy dump file from source to destination server.

[oracle@database ~]$ expdp scott/tiger tables=stats dumpfile=stats.dmp logfile=stat_bku.log
Export: Release 11.2.0.2.0 - Production on Tue Jul 16 23:18:10 2013
Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
----------------------------------------- 
-----------------------------------------

Processing object type TABLE_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
. . exported "SCOTT"."STATS"                             16.67 KB      16 rows
Master table "SCOTT"."SYS_EXPORT_TABLE_01" successfully loaded/unloaded
******************************************************************************
Dump file set for SCOTT.SYS_EXPORT_TABLE_01 is:
/etc/oracle/admin/orcl/dpdump/stats.dmp
Job "SCOTT"."SYS_EXPORT_TABLE_01" successfully completed at 23:19:29

To know more about Expdp backup see  How to take schema backup using Expdp ?.


4. Restore Stats Table using Impdp: As DBA has moved dump on destination server execute this command on destination server to restore dump file. Now, DBA has to restore stats to the destination table using impdp command.

[oracle@database ~]$ impdp scott/tiger tables=stats dumpfile=stats.dmp logfile=stat_bku.log

Import: Release 11.2.0.2.0 - Production on Tue Jul 16 23:34:13 2013
Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Master table "SCOTT"."SYS_IMPORT_TABLE_01" successfully loaded/unloaded
Starting "SCOTT"."SYS_IMPORT_TABLE_01":  scott/******** tables=stats dumpfile=stats.dmp logfile=stat_bku.log 
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
Processing object type TABLE_EXPORT/TABLE/INDEX/INDEX
Processing object type TABLE_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
Job "SCOTT"."SYS_IMPORT_TABLE_01" successfully completed at 23:34:47


5. Import Table Stats: Please make sure destination table also has same structure and name as source table for importing table stats. Here, i am also taking a table "EXPORT_STATS" for getting back the stats. This table doesn't have any data, while source table has 585392 rows. Now, we will import table stats into destination table. Make sure destination table name is sure other wise Oracle will execute the command without any error, but will not import stats.

SQL> exec dbms_stats.import_table_stats('SCOTT','EXPORT_STATS' ,NULL,'STATS',NULL,TRUE); 
PL/SQL procedure successfully completed.

SQL> select TABLE_NAME,NUM_ROWS,AVG_ROW_LEN,LAST_ANALYZED from user_tables where table_name like 'EXPORT_STATS';
TABLE_NAME                       NUM_ROWS AVG_ROW_LEN LAST_ANAL
------------------------------ ---------- ----------- ---------
EXPORT_STATS                       585392          97 16-JUL-13

SQL> SELECT COUNT(*) FROM EXPORT_STATS;
  COUNT(*)
----------
         0


From the above screen shot, Database Administrator can notice EXPORT_STATS doesn't have any row but user_tables stats are showing 585392 rows into this table.This will generate same execution plan for any query on this table as on source database. In this way DBA can replicate production enviorment at local system witout copying data from production.


Trick to Copy Table Stats into Another Table: As I said earlier in this post, It's not possible to import one table stats into another table. In fact DBA can do that by playing a small trick. Suppose soruce table is EXPORT_STATS and database admin wants to move stats to IMPORT_STATS then Here is the trick.

SQL> select c1, c5 from stats;
C1                             C5
----------------------------- ------------------------------
EXPORT_STATS                   SCOTT
EXPORT_STATS                   SCOTT
EXPORT_STATS                   SCOTT
EXPORT_STATS                   SCOTT

4 rows selected.

SQL> update stats set c1 ='RESTORE_STAT';
4 rows updated.

SQL> COMMIT;
Commit complete.

SQL> exec dbms_stats.import_table_stats('SCOTT','RESTORE_STAT' ,NULL,'STATS',NULL,TRUE);
PL/SQL procedure successfully completed.

SQL> select TABLE_NAME,NUM_ROWS,AVG_ROW_LEN,LAST_ANALYZED from user_tables where table_name like 'RESTORE_STAT';
TABLE_NAME                       NUM_ROWS AVG_ROW_LEN LAST_ANAL
------------------------------ ---------- ----------- ---------
RESTORE_STAT                       585392          97 16-JUL-13

SQL> SELECT COUNT(*) FROM RESTORE_STAT;
  COUNT(*)
----------
         0


Just update stats C1 column with new table column name and import the stats. This will restore stats into a new table, but make sure table structure is same.

To export and import statisticians for an entire schema use exec dbms_stats.export_schema_stats in #3 and exec dbms_stats.import_schema_stats in #5 rest of the process is same.

SQL> exec dbms_stats.export_schema_stats('SCOTT','STATS');

SQL> exec dbms_stats.import_schema_stats('SCOTT','STATS');

Please share if this post help you in Restoring stats from one database to another database.

No comments:

Post a Comment