A couple of ideas/theories:
SELECT INTO... lets the RDBMS determine sort order based on order of your original table. If you insert into an existing table, there may be a sort needed to match a clustered or nonclustered index(es).
No Indexes - when you SELECT INTO...
the RDBMS knows for certain there are no pre-existing indexes to update.
No Contention - since the table you are inserting into does not exist, SQL Server doesn't need to worry about row-level locking or contention handling. Nothing else can reference the table you create since it doesn't exist.
All that being said, there are other ways to insert into a table very quickly.
Make sure your clustered index keys match when possible. This means there is no on-the-fly sorting
Disable all non-clustered indexes. Self-explanatory.
Set recovery mode to simple and trace flag 610 to ON
. Use the TABLOCK
hint on your target table and NOLOCK
hint on your source table.
For example, assume tablea and tableb have the same clustered index:
INSERT INTO TableB WITH (TABLOCK)
SELECT <Columns>
FROM TableA WITH (NOLOCK)
In my experience this is faster than using SELECT INTO...
and then creating the clustered index afterwards. Please note this can also work on a table that already has data in it which is a much more useful scenario.
EDIT:
Here's a fantastically detailed whitepaper from MS for data load performance in Sql Server 2008.
SELECT INTO
can be minimally logged when not using Full Recovery.