为什么使用INSERT / * + APPEND * /?

时间:2014-05-23 07:07:38

标签: oracle insert

java程序正在批量插入Oracle表。它适用于100-200个记录,但它挂起超过4000个记录。

当我检查查询时,其中包含INSERT /*+APPEND*/

什么是INSERT /*+APPEND*/以及为什么在INSERT查询中使用它?程序是否因为这件事而悬空?

5 个答案:

答案 0 :(得分:5)

这是一个SQL优化器提示。在你的情况下,它很可能没有影响。也许这是一个不成熟的优化。

此提示应强制执行所谓的直接路径插入,它绕过Oracle的缓冲区缓存并将数据直接写入数据文件。数据附加在高水位线(HWM)之外 - 忽略表的可用空间映射,不触发触发器并且不检查约束。 另一方面,这种类型的插入物是阻塞的。只有一个会话可以同时在特定的表上使用它。

摘自文档:

  

“APPEND提示仅支持子查询语法   INSERT语句,而不是VALUES子句。如果您指定APPEND   使用VALUES子句提示,它被忽略并传统插入   将会被使用。要使用带有VALUES子句的直接路径INSERT,请参阅   “APPEND_VALUES提示”此提示仅在您使用INSERT时有效   SELECT语句

 insert into <table> SELECT * FROM ....

当您插入值时,Oracle默默地忽略它。较新的Oracle版本也支持APPEND_VALUES提示。

如果要验证正在使用的提示打开Toad或SQL Developer,请选择会话浏览器,找到该特定会话及其当前的SQL和exec计划。当您在exec计划中看到类似"INSERT into TABLE CONVENTIONAL"的内容时,将忽略该提示。如果您看到"INSERT as SELECT",那么您正在使用直接路径加载。

答案 1 :(得分:4)

insert通常会查找表中的第一个空白区域以添加新记录。虽然这节省了空间,但有时可能会减慢操作速度。

/*+APPEND*/是一个hint,导致insert语句总是因为缺少更好的术语,所以在表的末尾添加新插入的行。这可能会浪费一些空间,但通常会更快。如果您知道桌子中间没有太多空白区域(例如,您不会执行大量delete和{{1},那么它会特别有用在它上面。)

答案 2 :(得分:2)

这是一个ORACLE compliler提示。它是出于某种目的而不是评论。 这个提示用于加速插入,所以我认为这不是挂起程序的原因。

但是,请让你的dba检查这个表正在使用的表空间中的可用空间。(你的dba会更好地理解这个声明:))

可能存在一个问题,即该表空间中的任何更多插入空间可用的空间非常少,dba应该能够解析这些空间。

为什么可用的空间会减少?因为APPEND提示会浪费空间,如@Mureinik的上述答案所解释的那样,如果在该表中有太多频繁插入此提示,则可能会出现问题。

答案 3 :(得分:2)

/ * + APPEND * /

  • 称为直接路径插入。
  • 数据附加在高水位线(HWM)之外 - 忽略表的可用空间映射,不会触发任何触发器,也不会检查约束。
  • 只有一个会话可以同时在特定的桌面上使用
  

如果要检查正在使用的提示,请查找该特定会话及其当前SQL和exec计划。当你在exec计划中看到类似的东西时   “插入表格传统”   然后忽略提示。如果你看到   “INSERT as SELECT”   然后你正在使用直接路径加载

  • 仅支持INSERT语句的子查询语法,而不支持VALUES子句。
  • 如果使用VALUES子句指定APPEND提示,则会忽略该提示并使用常规插入。
  • 要使用带有VALUES子句的直接路径INSERT,请参阅“APPEND_VALUES提示”此提示仅在将INSERT用作SELECT语句时才有效。

答案 4 :(得分:0)

我不知道“加速”插入,但我肯定找到了提示,是的,这就是Oracle所谓的 - 而不是注释 - 对于维护记录的顺序非常有用当我将命令与最后的array (size=1) 0 => object(App\Tag)[267] protected 'table' => string 'tags' (length=4) protected 'fillable' => array (size=4) ... protected 'connection' => null protected 'primaryKey' => string 'id' (length=2) protected 'keyType' => string 'int' (length=3) protected 'perPage' => int 15 public 'incrementing' => boolean true public 'timestamps' => boolean true protected 'attributes' => array (size=7) ... ... ... C:\wamp64\www\Petro\app\Http\Controllers\CatalogedController.php:53: object(Illuminate\Database\Eloquent\Collection)[272] protected 'items' => array (size=0) 配对时,从一个表插入另一个表:

ORDER BY

我已经知道这只是一个巧合(参见S.O.的this thread),但我已经多次使用它了,现在,这至少是我最终的成果。如果您将INSERT /*+ append */ INTO MYAPP.COUNTRIES (ID, CODE, NAME) SELECT ID, CODE, NAME FROM MYAPP.OLD_COUNTRIES_TABLE ORDER BY NAME ASC; COMMIT; INSERT一起使用,但没有附加提示,ORDER BY会被忽略,并且完全没用,以确保可以根据它们的插入顺序(见my proof in my answer, here)。