【问题标题】:How to optimize the query to update a table column with a column in another table in oracle如何优化查询以使用oracle中另一个表中的列更新表列
【发布时间】:2020-02-19 13:00:15
【问题描述】:

我有 2 张桌子。一个表是 cr_archive,它有大约 9000000 条记录。它有一个名为 v_sales_person 的列,它没有值。我有另一个名为 table_2 的表,它具有名为 v_sales_person 的相同列,其中有值。两个表都有名为 product_label、account_num 的列。我想从表 _2 中选择与 cr_archive 具有相同 product_labels 和 account_num 的数据,并使用 table_2 中满足上述条件的值更新 cr_archive 中的 v_sales_person 列(使用 oracle)。我尝试了以下查询。

update cr_archive a
set a.v_sales_person = (select distinct b.v_sales_person from table_2 b where a.account_num = b.account_num and A.PRODUCT_LABEL=b.PRODUCT_LABEL )
/
commit
/

但是查询需要超过 6 个小时来处理并且不知道它是否给出了输出。我有 2 个问题。 1.上述查询是否正确? 2. 有什么方法可以优化上面的查询。

【问题讨论】:

  • 你能发布一个执行计划和DDL吗?如果您要更新 9.000.000 行,则索引很重要。此外,“distinct”可能不是您想要的。

标签: sql oracle query-optimization


【解决方案1】:

不要在子查询中使用select distinct。它表明它可以返回不止一行。相反,请使用rownum = 1。所以,开始吧:

update cr_archive a
    set a.v_sales_person = (select b.v_sales_person
                            from table_2 b
                            where a.account_num = b.account_num and
                                  A.PRODUCT_LABEL = b.PRODUCT_LABEL and
                                  rownum = 1
                           );

您想使用table_2(account_num, PRODUCT_LABEL, v_sales_person) 上的索引来优化它。该索引对性能很重要。

接下来,这是更新所有行。如果这不是必需的,那么它是昂贵的。所以:

update cr_archive a
    set a.v_sales_person = (select b.v_sales_person
                            from table_2 b
                            where a.account_num = b.account_num and
                                  A.PRODUCT_LABEL = b.PRODUCT_LABEL and
                                  rownum = 1
                           )
    where a.v_sales_person is null or
          a.v_sales_person <> (select b.v_sales_person
                               from table_2 b
                               where a.account_num = b.account_num and
                                     A.PRODUCT_LABEL = b.PRODUCT_LABEL and
                                     rownum = 1
                              );

最后,如果您确实需要更新所有行,那么这将是相当昂贵的。您可能会发现以下一种可行的替代方案:

  1. 重建表。大量插入比大量更新更快。
  2. 算了。当您查询表以获取名称时,只需 JOIN
  3. 添加具有相同主键的新表。

【讨论】:

    【解决方案2】:

    您可以使用MERGE声明如下:

    MERGE INTO CR_ARCHIVE A 
    USING (
              SELECT
                  MAX(B.V_SALES_PERSON) AS V_SALES_PERSON,
                  B.ACCOUNT_NUM,
                  B.PRODUCT_LABEL
              FROM
                  TABLE_2 B
              GROUP BY
                  B.ACCOUNT_NUM,
                  B.PRODUCT_LABEL
          )
    B ON ( A.ACCOUNT_NUM = B.ACCOUNT_NUM
           AND A.PRODUCT_LABEL = B.PRODUCT_LABEL )
    WHEN MATCHED THEN 
    UPDATE SET A.V_SALES_PERSON = B.V_SALES_PERSON;
    /
    

    干杯!!

    【讨论】:

      猜你喜欢
      • 2022-10-07
      • 2015-01-29
      • 2021-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多