It’s been a long time since I posted on my blog. This post is in response to the question that I received through email:
<<
Just like to know if I can use dbms_stats.import_table_stats to import table statistics to another table?
I am wondering if I can import table statistics from T1 to T2 using dbms_stats package?.
>>
The simple answer to the above question is “NO”. You cannot copy statistics to a different table even if they are identical. However, there are two ways of achieving this:
1) Temporarily rename the destination table (T_IDENTICAL) as original table (T) and import statistics or
2) Break into the statistics table.
Option -1 is pretty straight forward so we will not discuss that. Let’s see how to break into statistics table.
Let us create the two tables: source table “T” and the destination table “T_IDENTICAL”. I am creating both these tables in the same schema, so as to avoid exporting and importing of statistics table.
SQL>
SQL> drop table t purge;
Table dropped.
SQL> drop table t_identical purge;
Table dropped.
SQL>
SQL> create table t as select rownum id, object_name name from all_objects where rownum < 1001;
Table created.
SQL>
SQL> create table t_identical as select * from t where 1=2;
Table created.
SQL>
SQL>
Collect statistics for the source table (T)
SQL>
SQL> exec dbms_stats.gather_table_stats(user, 't');
PL/SQL procedure successfully completed.
SQL>
SQL> select table_name, num_rows from user_tables where table_name in ('T', 'T_IDENTICAL');
TABLE_NAME NUM_ROWS
------------------------------ ----------
T 1000
T_IDENTICAL
SQL>
Create a statistics table (“MY_STATS_TAB”) and export statistics of the source table “T”.
SQL>
SQL> exec dbms_stats.create_stat_table('TEST','MY_STATS_TAB');
PL/SQL procedure successfully completed.
SQL> exec dbms_stats.export_table_stats('TEST','T',NULL,'MY_STATS_TAB');
PL/SQL procedure successfully completed.
SQL>
Now let us try to import statistics to the destination table (T_IDENTICAL):
SQL> exec dbms_stats.import_table_stats('TEST','T_IDENTICAL', null, 'MY_STATS_TAB');
PL/SQL procedure successfully completed.
SQL>
SQL>
SQL> select table_name, num_rows from user_tables where table_name in ('T', 'T_IDENTICAL');
TABLE_NAME NUM_ROWS
------------------------------ ----------
T 1000
T_IDENTICAL
SQL>
No affect.
Oracle simply ignored my request without reporting any errors.
As we have source table statistics in a safe place, let us delete statistics from the source table and import them back from the container table. (This step ensures stats import is working as expected)
SQL> exec dbms_stats.delete_table_stats(user, 'T');
PL/SQL procedure successfully completed.
SQL> select table_name, num_rows from user_tables where table_name in ('T', 'T_IDENTICAL');
TABLE_NAME NUM_ROWS
------------------------------ ----------
T
T_IDENTICAL
SQL>
SQL>
SQL> exec dbms_stats.import_table_stats('TRADE','T', null, 'MY_STATS_TAB');
PL/SQL procedure successfully completed.
SQL> select table_name, num_rows from user_tables where table_name in ('T', 'T_IDENTICAL');
TABLE_NAME NUM_ROWS
------------------------------ ----------
T 1000
T_IDENTICAL
SQL>
SQL>
As you can see, import works only when the source and destination tables are same.
Let us see what’s there in the MY_STATS_TABLE:
SQL>
SQL> select count(*) from my_stats_tab;
COUNT(*)
----------
3
SQL>
SQL>
SQL> select c1, c5 from my_stats_tab;
C1 C5
------------------------------ ------------------
T TRADE
T TRADE
T TRADE
SQL>
SQL>
Columns “C5” and “C1” of the statistics table represent schema owner and table name respectively. Let us update the table name from “T” to “T_IDENTICAL”.
SQL> update my_stats_tab set c1 = 'T_IDENTICAL';
3 rows updated.
SQL> commit;
Commit complete.
SQL>
Now import the table statistics for “T_IDENTICAL” table
SQL> select table_name, num_rows from user_tables where table_name in ('T', 'T_IDENTICAL');
TABLE_NAME NUM_ROWS
------------------------------ ----------
T 1000
T_IDENTICAL
SQL>
SQL> exec dbms_stats.import_table_stats('TRADE','T_IDENTICAL', null, 'MY_STATS_TAB');
PL/SQL procedure successfully completed.
SQL> select table_name, num_rows from user_tables where table_name in ('T', 'T_IDENTICAL');
TABLE_NAME NUM_ROWS
------------------------------ ----------
T 1000
T_IDENTICAL 1000
SQL>
SQL>
There you go. We were able to successfully move statistics to another table by hacking into the statistics table.
Hope you enjoyed this post.