Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在oracle中更新大表而不降低基表_Sql_Oracle_Plsql_Plsqldeveloper - Fatal编程技术网

Sql 在oracle中更新大表而不降低基表

Sql 在oracle中更新大表而不降低基表,sql,oracle,plsql,plsqldeveloper,Sql,Oracle,Plsql,Plsqldeveloper,我正在尝试更新sql查询中的表。我的表包含50万条记录,大约需要10分钟的时间。这是我的开发环境 当我选择UAT或prod时,那里的表将包含比开发环境多得多的数据。更新整个表,然后提交将消耗大量内存。有人能给我推荐一种批量更新表格的好方法吗 我已经浏览过网络,我发现最常见的解决方案是通过“创建新表作为从旧表中选择(更新)”来创建一个新表。但在我的情况下,我不能使用它,因为在我的产品环境中,我不能删除和创建表 谢谢 安基特 如果“createtableasselect”不是一个选项,那么最好的选择

我正在尝试更新sql查询中的表。我的表包含50万条记录,大约需要10分钟的时间。这是我的开发环境


当我选择UAT或prod时,那里的表将包含比开发环境多得多的数据。更新整个表,然后提交将消耗大量内存。有人能给我推荐一种批量更新表格的好方法吗

我已经浏览过网络,我发现最常见的解决方案是通过“创建新表作为从旧表中选择(更新)”来创建一个新表。但在我的情况下,我不能使用它,因为在我的产品环境中,我不能删除和创建表

谢谢
安基特

如果“createtableasselect”不是一个选项,那么最好的选择是编写一个PL/SQL存储过程,该过程利用
批量收集
FORALL
语句。这是一个很好的起点

CTAS仍然是最快的选择。记住,你不需要放下原来的桌子;您可以重命名并保留它,以使您的管理层满意

否则,根据您的情况,您会有一些选择

如果:

  • 担心的只是时间的流逝;及
  • 您拥有企业版许可证;及
  • 生产中需要备用CPU

你可以考虑并行DML来解决这个问题。

alter session enable parallel dml;

update /*+ parallel (your_table) */ your_table
set ..
如果您只有标准版,但使用的是11gR2或更高版本,则可以使用DBMS_PARALLEL_EXECUTE包并行运行PL/SQL作业。关于CPU的警告仍然适用

除此之外,您还应该看看WHERE子句的效率。更新也是一种扫描,可以像任何其他查询一样进行调优

将更新拆分为批将使总运行时间更长。当然会的,你正在做更多的工作。与单个update语句相比,批处理的主要优点是,通过提交记录块,如果任务中途完成,我们不会丢失工作。如果有一种机制来区分更新的记录(通过此任务更新的状态或日期列而不是其他的),这只是一种优势。如果您没有这样的标志,您就有绝对损坏表的风险

批处理的最简单方法是简单的PL/SQL循环。假设有一百万行要更新:

begin
    for idx in 1..100 loop
         update your_table
         set whatever = whatever * 1.1
                    , status = 'touched'
         where status != 'touched'
          and rownum <= 10000;
          commit;
    end loop;
end;
开始
对于1..100循环中的idx
更新您的_表
设置whatever=whatever*1.1
,状态='toucted'
状态在哪里!='感动

和rownum在循环中以10000为一批更新它们,而行计数更新>0。执行内部循环提交,这将停止回滚,如果中途停止,则可以恢复到停止的位置。嗨,Ab Bennett,我不想进入PL/SQL,因为我试图避免上下文切换切换有什么大不了的,切换是为了找到正确的平衡,只是不要每行都执行。为了回答您的问题,如果您不能使用pl/swl,也不会使用新表,那么您唯一的选择就是一次更新。确保你有一个大的回滚段。如果你的空间不够,你会失望的。记录在案,如果你不是每行都做,上下文切换就没什么大不了的。10轧机行工作台,更新100k卡盘,即100/switches@abbennett-在循环内提交会带来自身的复杂性。您需要确保事务在出现故障时是可恢复的。您需要避免ORA-01555错误。“更新整个表,然后提交将消耗大量内存”。一点也不正确。它需要磁盘——具体来说就是撤销,但磁盘很便宜。定期提交是件好事,这是一种常见的误解。我建议您重新考虑您的方法,为最大的事务(可能就是这个事务)调整足够的撤销大小,并将其作为单个update语句来执行。