更新查询需要时间来执行

时间:2016-12-06 11:19:17

标签: sql oracle

我有一个表xx_wr,它有一个我想要的列action_code 根据PER_ASG的action_code列进行更新。

此PER_ASG的列有效_start_date和effective_end_date。 只应选择此表中作为最新记录的max effective_start_date来更新xx_wr。

PER_ASG 

EFFECTIVE_START_DATE EFFECTIVE_END_DATE ACTION_CODE PERSON_ID
01-JAN-2016          31-DEC-4712         HR          10
02-FEB-2015          31-DEC-2015         TERM        10

因此,从该表中,应该选择01-JAN-2016的最新行,Action_code HR应该更新WR中的action_code。

我已为此编写了以下查询。但需要3小时才能更新10k行。有什么方法可以修改我的查询以提高性能吗?

 update XX_WR wr
            set wr.action_code = 
            (
            select pam.action_code
            from PER_ASG pam
            where 1=1
            and pam.person_id=wr.person_id
            and pam.effective_start_date = (select max(ppm.effective_start_date) from PER_ASG ppm 
            where 1=1 
            and ppm.person_id = pam.person_id
            )) 
            where 1=1;

3 个答案:

答案 0 :(得分:1)

而不是嵌套的子查询,以找到每个effective_start_date使用person_id窗口函数找到它的最大ROW_NUMBER

试试这种方式

MERGE INTO XX_WR AS wr
using (SELECT Row_number()OVER(partition BY person_id ORDER BY effective_start_date DESC ) AS rn,
              action_code,
              person_id
       FROM   PER_ASG) pam
ON wr.person_id = pam.person_id
   AND pam.rn = 1
WHEN matched THEN
  UPDATE SET action_code = pam.action_code;

注意:这里我们不必使用MERGE,因为我不确定Oracle使用Update from Join语句中的MERGE语法但是这个想法是一样的< / p>

答案 1 :(得分:1)

这是查询:

update XX_WR wr
    set wr.action_code =
        (select pam.action_code
         from PER_ASG pam
         where pam.person_id = wr.person_id and
               pam.effective_start_date =
                   (select max(ppm.effective_start_date)
                    from PER_ASG ppm 
                    where ppm.person_id = pam.person_id
                   ) 
        );

这是更新XX_WR中的所有行。这可能是性能问题的原因。

但是,仍然可以提高查询效率。我会推荐索引。从PER_ASG(person_id, effective_start_date)开始。我也会把它重写为:

update XX_WR wr
    set wr.action_code =
        (select max(pam.action_code) keep (dense_rank first order by effective_date)
         from PER_ASG pam
         where pam.person_id = wr.person_id 
        );

答案 2 :(得分:1)

试试这个:

 WITH
sub1 AS 
(  /*+ materialize */ 
SELECT pam.action_code,pam.person_id
  FROM PER_ASG pam
 WHERE     1 = 1 
       AND pam.effective_start_date =
              (SELECT MAX (ppm.effective_start_date)
                 FROM PER_ASG ppm
                WHERE 1 = 1 AND ppm.person_id = pam.person_id)
)                
update XX_WR wr
            set wr.action_code =sub1.action_code 
where sub1.person_id=wr.person_id