PLSQL块需要很长时间来声明游标

时间:2012-11-06 12:55:56

标签: database performance plsql cursor

我正在执行一个PL / SQL块,用于更新显式游标中的某些行。声明游标的代码如下:

cursor DUP_SUBJECTS is  
  select * 
    from ODS_SUBJECT_D  
   WHERE SUBJECT_COD = ANY (SELECT SUBJECT_COD  
                              FROM ODS_SUBJECT_D  
                             WHERE END_DATE = TO_DATE ('31-12-9999','DD-MM-YYYY')   
                             GROUP BY SUBJECT_COD, ROW_TYPE_DE  
                            HAVING COUNT(*) > 1)  
   ORDER BY SUBJECT_COD, START_DATE; 

正文中的第一个语句是DBMS_OUTPUT.PUT_LINE,以便在它开始执行块时通知。上述脚本中的查询返回表中2900000行中的20000行。在脚本的声明块中似乎需要很长时间(30分钟后它还没有打印消息) 有什么建议可以优化脚本的性能吗?

谢谢,
安东尼奥

3 个答案:

答案 0 :(得分:1)

你误解了DBMS_OUTPUT的工作原理。在您的代码块完成运行之前,客户端无法接收发送到DBMS_OUTPUT的消息。您可以通过向DBMS_OUTPUT条消息添加时间戳来验证这一点。我怀疑你会发现第一条消息几乎是立即被写入,而实际的瓶颈就是其他地方。

答案 1 :(得分:0)

您可以尝试以不同的方式编写查询:

cursor dup_subjects is  
  select
    * 
  from (
    select
      o.*,
      count(*) over (partition by subject_cod, row_type_de) count_per
    from
      ods_subject_d
    where
      end_date = date '9999-12-31')
  where
    count_per > 1
  order by
    subject_cod,
    start_date;

如果这不是一个非常常见的值,请确保将end_date编入索引 - 如果您不经常在end_date上查询除此值之外的内容,请考虑索引:

create index ...
on     ods_subject_d (
         case end_date
           when date '9999-12-31' then 1
         end)

...并将该谓词更改为......

where case end_date when date '9999-12-31' then 1 end = 1

有可能进一步细化索引和查询,更多地了解值的分布以及满足“count(*)> 1”条件的可能性。

答案 2 :(得分:-1)

如果你的pl / sql块需要更长的时间来运行并且没有从程序中出来, 那么你需要在适当的列上创建索引。