Best way to create multiple similar tables – CTAS vs INSERT

oracle-11g-r2

I am creating a few dozen tables as CREATE TABLE AS SELECT (CTAS). The only difference in the SELECT statements is specifying a different value in the WHERE clause for TEAM_ID. I'm an Oracle newbie and thought I could use bind variables to speed up the process, but those are not allowed in DDL statements.

My data is quite large – 500+ million rows.

What is my best option for speed? Currently we are using nologging on the CREATE TABLE statement. Would it be better to explicitly create the table and INSERT with the /*+ append */ hint and bind variables? Or do the gains of nologging outweigh the gains of bind variables?

(I am sure this is an "it depends" scenario, but I don't even know what it depends on…)

Best Answer

Use execute immediate to make creation of many very similar tables easier.

A little PL/SQL demo:

SQL> 
declare 
table_number number;
ctas_sql varchar(4000);
begin
  ctas_sql:='select sysdate as foo from dual';

  for table_number in 1..10
  loop
    execute immediate('create table foo'||table_number ||' as ('||ctas_sql||')');
  end loop;
end;
/
SQL> 
PL/SQL procedure successfully completed.

SQL> 
SQL> select table_name from user_tables;

TABLE_NAME
------------------------------
FOO1
FOO2
FOO3
FOO4
FOO5
FOO6
FOO7
FOO8
FOO9
FOO10

10 rows selected.

SQL> 

The create table statement can contain anything you want - the above is just showing that the statement can be dynamic. So, in your case you'd have simple logic to alter the TEAM_ID and table name for each statement.

Bind variables will offer no gain unless you're executing the same single query multiple times (extremely simplified for the sake of this answer) - in this case you're executing many different queries that are performing large bulk inserts.

Creating tables with NOLOGGING is not advisable if this is a production system. Also be aware that not logging and /*+APPEND*/ can have backup/restore implications. This Ask Tom thread may be of particular interest.

To clarify, using CTAS is the way to go. You only have to parse the CTAS statement once to insert your millions of rows. If you use individual INSERT statements you have to parse each statement over & over again, which adds a massive overhead!