【问题标题】:Write efficient update query by joining multiple tables in Oracle通过在 Oracle 中连接多个表来编写高效的更新查询
【发布时间】:2018-05-22 19:16:19
【问题描述】:

我有一个复杂的要求,即通过连接多个表以查找正确的记录来更新一个表中的一些记录。我编写了以下正在运行的查询,但执行需要 2.5 分钟,这导致我的数据库连接超时。有没有办法通过重写来提高这个查询的效率?我也尝试过 MERGE 方法,这也需要很长时间。我在 EVENT_DYNAMIC_ATTRIBUTE 表中有超过 200 万条记录,在 EVENT 表中有 100 万条记录,在 CATEGORY 表中有 10 万条记录。

UPDATE EVENT_DYNAMIC_ATTRIBUTE eda
SET eda.ATTRIBUTE_VALUE = 'claim',
    eda.LAST_UPDATED_DATE = SYSDATE,
    eda.LAST_UPDATED_BY = 'superUsers'
WHERE eda.DYNAMIC_ATTRIBUTE_NAME_ID=4002
  AND eda.EVENT_ID IN
    (SELECT e.EVENT_ID
     FROM EVENT e
     WHERE e.PRIMARY_CATEGORY_ID IN
         (SELECT CATEGORY_ID
          FROM CATEGORY START WITH CATEGORY_ID = 495984 CONNECT BY PARENT_ID =
          PRIOR CATEGORY_ID));

这是合并查询:

 MERGE INTO EVENT_DYNAMIC_ATTRIBUTE eda
    USING (SELECT DISTINCT e.EVENT_ID FROM (
         SELECT CATEGORY_ID
         FROM CATEGORY 
         START WITH CATEGORY_ID=495984 
         CONNECT BY PARENT_ID =
         PRIOR CATEGORY_ID) CATEGORIES
    INNER JOIN  EVENT E ON e.PRIMARY_CATEGORY_ID = CATEGORY_ID 
    INNER JOIN  EVENT_DYNAMIC_ATTRIBUTE ed on ed.EVENT_ID = E.EVENT_ID) temp 
    ON (eda.EVENT_ID = temp.EVENT_ID ) 
    WHEN MATCHED THEN 
       UPDATE SET eda.ATTRIBUTE_VALUE = 'claim',
                  eda.LAST_UPDATED_DATE = SYSDATE,
                  eda.LAST_UPDATED_BY = 'superUser'
    WHERE eda.DYNAMIC_ATTRIBUTE_NAME_ID=4002

【问题讨论】:

  • MERGE 可能是实现这一目标的最佳方式
  • 在这种情况下我总是确保尝试在您的ORDER BY ed.rowid 子句中添加USING。在带有连接的UPDATE 中,它有很大帮助,我怀疑它可能在带有连接的MERGE 中有所帮助。请参阅此线程:asktom.oracle.com/pls/asktom/…。我已经看到它提高了 40-60%。

标签: sql oracle oracle11g sql-update inner-join


【解决方案1】:

你可以试试

update 
  (
    select
      eda.*
    from
      (select * from event_dynamic_attribute where dynamic_attribute_name_id = 4002) eda,
      (select category_id from category start with category_id = 495984 connect by parent_id = prior category_id) c,
      event e
    where
      e.primary_category_id = c.category_id and
      e.event_id = eda.event_id
  )
set
  attribute_value = 'claim', 
  last_updated_date = sysdate,
  last_updated_by = 'superUsers'

但我怀疑它是否有帮助。通常,即使在旧硬件上工作,这也是非常非常低的速度。您应该跟踪这些更新并检查它们的执行情况、受影响的块等。

首先,我会要求你执行

explain plan for <<your update statement text>>;
select * from table(dbms_xplan.display());

并将其结果写入问题中。还有一个……event_dynamic_attribute 表上有触发器吗?

【讨论】:

  • 这种方法的问题是,执行查询时总是出现以下错误。 SQL 错误 [1779] [42000]: ORA-01779: 无法修改映射到非键保留表的列
  • 这很奇怪,它看起来像密钥保留。 event_id 是事件的 pk 吗?类别的category_id? event_dynamic_attribute 中是否有主键?
  • 是的,event_id 是事件的 pk,category_id 是类别的 pk,event_dynamic_attribute_id 是 event_dynamic_attribute 的 pk。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-17
  • 2011-09-04
  • 2021-03-25
  • 1970-01-01
  • 1970-01-01
  • 2018-05-16
  • 1970-01-01
相关资源
最近更新 更多