我有一个包含大约100k记录的表,我想删除一些行,问题是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
如何杀死这些会话?
在我杀死锁定表的会话后,问题已得到解决,感谢大家的帮助。 -
答案 0 :(得分:7)
可能有很多原因:
SELECT
很快)LOB
s,多列)。如果外键是问题,通常的解决方案是在外部列上添加索引:对于每次删除,Oracle需要检查这是否会违反外键关系。
答案 1 :(得分:3)
删除更改表格内容的方法。这意味着,在每个删除的行之后,必须更新所有索引并且必须检查所有外键引用。这可能需要很长时间!
也许这会有所帮助:
制作该表的副本,不包含任何引用,触发器和其他索引。然后这样做:
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;
答案 2 :(得分:1)
显然,删除操作所需的时间比选择时间长,但这并不能解释您所看到的差异。
这听起来像是在删除时运行了额外的代码,这表示桌面上可能还有正在运行的触发器。你能看看吗?
答案 3 :(得分:0)
当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。)