为什么 CREATE TABLE AS SELECT 比 INSERT with SELECT 更快

Why CREATE TABLE AS SELECT is more faster than INSERT with SELECT

我使用 INNER JOIN 进行查询,结果是 1200 万行。 我喜欢把它放在 table 中。 我做了一些测试,当我创建 table 使用子句 AS SELECT 比先创建 table 和 运行 后使用 SELECT INSERT 更快. 我不明白为什么。 有人可以为我解释吗? 谢谢

With SELECT STATEMENT 您创建的 table 没有主键、索引、标识...列始终允许 NULL。 并且它不必写入事务日志(因此不会回滚)。好像是 "Naked Table".

使用 INSERT ... SELECT 然后必须先创建 table 所以当您创建 table 时,您可以定义键、索引、身份 ... 它将使用事务日志 应用于大量数据时,速度很慢。

如果您使用 'create table as select' (CTAS)

CREATE TABLE new_table AS 
    SELECT * 
    FROM old_table

你自动做一个direct-path insert的数据。如果你做

INSERT INTO new_table AS 
    SELECT * 
    FROM old_table

你做了一个常规插入。如果您想改为执行直接路径插入,则必须使用 APPEND 提示。所以你必须做

INSERT /*+ APPEND */ INTO new_table AS 
    SELECT * 
    FROM old_table

获得与 'CREATE TABLE AS SELECT' 类似的性能。

通常的常规插入是如何工作的?

Oracle 检查 table 的 free list 以查找 table 段的已使用块,该块仍然可用 space.如果该块不在缓冲区缓存中,则将其读入缓冲区缓存。最终这个块被读回磁盘。 在此过程中,块的撤销被写入(这里只需要少量数据),数据结构被更新,例如如有必要,段头中的空闲列表和所有这些更改也将写入重做缓冲区。

直接路径插入如何工作?

进程在 table 的 高水位线 以上分配 space,即超出已使用的 space。它直接将数据写入磁盘,而不使用缓冲区缓存。并且它也被写入重做缓冲区。当会话被提交时,高水位标记被提升到超过新写入的数据,并且该数据现在对其他会话可见。

如何改进 CTAS 和直接路径插入?

  • 您可以在 NOLOGGING 模式下创建故事,而不是写入重做信息。如果你这样做,你应该在插入后备份包含 table 的 tablespace,否则你无法恢复 table 如果你需要这个。
  • 您可以并行执行 select

  • 可以并行插入

  • 如果您必须在插入操作期间维护索引和约束甚至触发器,这会大大减慢您的插入操作。所以你应该避免这种情况并在插入后创建索引,并可能使用 novalidata 创建约束。