【问题标题】:Delete statement was very slow in OracleOracle中的删除语句非常慢
【发布时间】:2012-04-23 11:52:56
【问题描述】:

我有一个包含大约 10 万条记录的表,我想删除一些行,问题是 DELETE 语句运行非常缓慢 - 它没有在 30 分钟内完成。但是select 语句在 1 秒内返回。

SELECT声明如下:

select * from daily_au_by_service_summary 
    where summary_ts >= to_date('09-04-2012','dd-mm-yyyy') 
    order by summary_ts desc;

DELETE声明如下:

delete from daily_au_by_service_summary 
    where summary_ts > to_date('09-04-2012','dd-mm-yyyy');

此表的唯一索引为 summary_ts

可能是什么原因?

编辑:在我杀死锁定表的会话后,问题已经解决,感谢大家的帮助。

SESSION_ID ORACLE_USERNAME                OS_USER_NAME                   OBJECT OWNER                   OBJECT_NAME                                                                                                                      OBJECT_TYPE         LOCKED_MODE
---------- ------------------------------ ------------------------------ ------------------------------ -------------------------------------------------------------------------------------------------------------------------------- ------------------- -----------
       213 T03RPT                         elou                           T03RPT                         DAILY_AU_BY_SERVICE_SUMMARY                                                                                                      TABLE                         3 
       203 T03RPT                         elou                           T03RPT                         DAILY_AU_BY_SERVICE_SUMMARY                                                                                                      TABLE                         3 
       202 T03RPT                         elou                           T03RPT                         DAILY_AU_BY_SERVICE_SUMMARY                                                                                                      TABLE                         3 
       190 T03RPT                         elou                           T03RPT                         DAILY_AU_BY_SERVICE_SUMMARY                                                                                                      TABLE                         3 
       189 T03RPT                         elou                           T03RPT                         DAILY_AU_BY_SERVICE_SUMMARY                                                                                                      TABLE                         3 
       188 T03RPT                         elou                           T03RPT                         DAILY_AU_BY_SERVICE_SUMMARY                                                                                                      TABLE                         3 
       187 T03RPT                         elou                           T03RPT                         DAILY_AU_BY_SERVICE_SUMMARY         

【问题讨论】:

  • 你是如何确定它没有完成的?也许它已完成但尚未提交,并且在提交之前您看不到从另一个连接发生删除。
  • 我在 sqlplus 控制台中运行它,它只是没有返回。所以我认为该语句仍在执行中。
  • 终止会话是一个完全不同的话题。请提出一个新问题(以便其他人更容易找到该解决方案)。然后,将此问题的链接添加到新问题。
  • 在我杀死了锁表的会话后问题已经解决了,谢谢大家的帮助。

标签: sql oracle


【解决方案1】:

可能有很多原因:

如果外键是问题,通常的解决方案是在外列上添加索引:对于每次删除,Oracle 都需要检查这是否会违反外键关系。

【讨论】:

  • 如何检查行是否被任何人锁定?
  • 所以该表被许多会话锁定。请参阅已编辑的问题。如何终止会话?
  • 请为此提出一个新问题。
【解决方案2】:

删除意味着改变表格的内容。这意味着,在每个删除的行之后,必须更新所有索引,并且必须检查所有外键引用。这可能需要很长时间!

也许这会有所帮助:

在没有任何引用、触发器和其他索引的情况下复制该表。然后这样做:

insert into new_table (field1, field2, ...) values (
    select field1, field2, ...
    from daily_au_by_service_summary 
    where summary_ts < to_date('09-04-2012','dd-mm-yyyy') 
);

如果表格中的字段以相同的顺序定义,这也可能有效:

insert into new_table values (
    select *
    from daily_au_by_service_summary 
    where summary_ts < to_date('09-04-2012','dd-mm-yyyy') 
);

之后:

truncate daily_au_by_service_summary

然后:

insert into daily_au_by_service_summary (field1, field2, ...) values (
    select field1, field2, ...
    from new_table; 
);

不再需要新表:

drop new_table;

【讨论】:

  • 谢谢休伯特。我想弄清楚为什么 DELETE 语句这么慢,因为表中只有大约 100k 条记录。
【解决方案3】:

显然,删除操作将比选择花费更长的时间,但这并不能说明您看到的差异。

听起来在删除时正在运行其他代码,这表明表上可能有触发器也在运行。你能检查一下吗?

【讨论】:

  • 表上没有任何触发器,也没有任何引用约束。
【解决方案4】:

当 DML 操作需要很长时间时,使用剩余的行创建新表并删除之前的表,而不是删除。

我的意思是,

create table NEW_TABLE as
select * from daily_au_by_service_summary  
where summary_ts <= to_date('09-04-2012','dd-mm-yyyy'); 

这会更快,尤其是当您要删除大量行时。 (例如,占总行数的 %10。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    • 1970-01-01
    相关资源
    最近更新 更多