繁体   English   中英

UPDATE语句Oracle 11g的替代方法

[英]Alternatives to UPDATE statement Oracle 11g

我目前正在使用Oracle 11g,假设我有一个包含以下各列的表(或多或少)

表格1

  • ID varchar(64)
  • 状态int(1)
  • 交易日期
  • 吨其他列

该表大约有10亿行 我想用特定的where子句更新status



    where transaction_date = somedatehere

除了普通的UPDATE语句,我还可以使用其他哪些选择?

目前,我正在尝试使用CTAS或Insert into select获取要更新的行,并在使用AS COLUMN_NAME时将其放置在另一个表上,因此值已在新表/临时表上更新,看起来像这个:



    INSERT INTO TABLE1_TEMPORARY (
        ID, 
        STATUS, 
        TRANSACTION_DATE, 
        TONS_OF_OTHER_COLUMNS)
    SELECT
        ID
        3 AS STATUS,
        TRANSACTION_DATE,
        TONS_OF_OTHER_COLUMNS
    FROM TABLE1
    WHERE
        TRANSACTION_DATE = SOMEDATE 

到目前为止,一切似乎都比正常的update语句更快。 现在的问题是,我想从原始表中获取剩余数据,这些数据我不需要更新,但确实需要包含在更新后的表/列表中。

我最初尝试做的是使用相同的where子句在同一原始表上使用DELETE ,因此从理论上讲,应保留在该表上的所有内容都应该是我不需要更新的所有数据,现在让我两个表:



    TABLE1 --which now contains the rows that i did not need to update
    TABLE1_TEMPORARY --which contains the data I updated

但是delete语句本身也太慢或与原始UPDATE语句一样慢,因此如果没有delete语句,我就会明白这一点。



    TABLE1 --which contains BOTH the data that I want to update and do not want to update
    TABLE1_TEMPORARY --which contains the data I updated

为了获得与WHERE子句相反的数据,我还可以使用其他替代方法(请注意,此示例中的where子句已简化,因此我没有在寻找NOT EXISTS / NOT IN / NOT EQUALS的答案加上那些条款比肯定条款还慢)

我已经排除了按分区删除的问题,因为我需要更新和不更新的数据可以存在于不同的分区中,而TRUNCATE也可以存在,因为我没有更新所有数据,而只是部分数据。

我是否将某种JOIN语句与T​​ABLE1和TABLE1_TEMPORARY一起使用,以过滤出不需要更新的数据?

我还想使用尽可能少的REDO / UNDO / LOGGING实现此目的。

提前致谢。

我假设这不是一次操作,但是您正在尝试设计可重复的过程。

以某种方式对表进行分区/划分,以便使接触的行不完全分布在所有分区上,而是局限于少数几个分区。

确保您的交易暂时不会使用这些分区。

通常,对于每个分区/子分区,通常都将对其进行更新,并对所有行执行CTAS(我的意思是,即使保持不变的行也都进入TABLE1_TEMPORARY)。 然后交换分区并重建索引分区。

最后,重建全局索引。

如果您没有Oracle Enterprise Edition,则需要CTAS整十亿行(紧跟着ALTER TABLE RENAME而不是ALTER TABLE EXCHANGE PARTITION),或者使用视图准备某种“穷人分区”(SELECT UNION) ALL SELECT UNION ALL SELECT等)和一堆表格。

这种混乱实际上有可能比UPDATE更快。

我并不是说这是优雅的还是最优的,不是说这是在Oracle中加快大型UPDATE操作的规范方法。

如何将UPDATE保留在同一表中,但将其分成多个小块呢?

UPDATE .. WHERE transaction_date = somedatehere AND id BETWEEN 0000000 and 0999999
COMMIT
UPDATE .. WHERE transaction_date = somedatehere AND id BETWEEN 1000000 and 1999999
COMMIT
UPDATE .. WHERE transaction_date = somedatehere AND id BETWEEN 2000000 and 2999999
COMMIT

如果总的工作量可能是可管理的,这可能会有所帮助,但是将问题全部集中在一起是一个问题。 这种方法将其分成中等大小的碎片。

这样,例如,可以使其他应用程序保持运行并查看其他工作负载。 并且可以避免在日志文件中进行单个繁琐的事务。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM