java程序正在批量插入Oracle表。它适用于100-200个记录,但它挂起超过4000个记录。
当我检查查询时,其中包含INSERT /*+APPEND*/
。
什么是INSERT /*+APPEND*/
以及为什么在INSERT查询中使用它?程序是否因为这件事而悬空?
答案 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 * /
如果要检查正在使用的提示,请查找该特定会话及其当前SQL和exec计划。当你在exec计划中看到类似的东西时 “插入表格传统” 然后忽略提示。如果你看到 “INSERT as 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)。