There are several changes that arrive with the optimizer when you move to 12c and above. There are changes to histograms, all of the adaptive features etc, but also, one of the simplest but coolest optimizer improvements when it comes to loading data. When you perform a direct-path insert into an empty table, or a create-table-as-select (CTAS) operation, there is no need to perform an additional DBMS_STATS call to gather statistics at the conclusion of the load. The load process itself handles that for you. Here’s a simple example of that in action:
SQL> create table t (id primary key, tag)
2 as select rownum id, to_char(rownum) tag
3 from dual connect by level <= 50000;
Table created.
SQL>
SQL> select num_rows from user_tables
2 where table_name = 'T';
NUM_ROWS
----------
50000
1 row selected.
SQL>
SQL> select leaf_blocks
2 from user_indexes
3 where table_name = 'T';
LEAF_BLOCKS
-----------
103
1 row selected.
Of course, many people are now aware of this functionality, so why does it warrant a blog post? Mainly to make readers aware of a boundary case. If the table you are creating or loading is an index-organized table (IOT), then you do not get the statistics gathered automatically.