2012-04-11 2 views
4

У меня есть таблица с около 100k записей, и я хочу удалить несколько строк. Проблема в том, что оператор DELETE работает очень медленно - он не закончил через 30 минут. Но заявление select было возвращено через 1 секунду.Операция удаления была очень медленной в Oracle

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.

В чем может быть причина?

EDIT: таблица была заблокирована многими сессиями:

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

Как вы определили, что это не закончилось? Возможно, это закончилось, но не было выполнено, и вы не видите, что удаление произошло из другого соединения, пока оно не было завершено. –

+0

Я запустил его в консоли sqlplus, он просто не вернулся. поэтому я думаю, что это заявление все еще выполняется. –

+0

Убивание сессий - совершенно другая тема. Задайте новый вопрос (чтобы другие люди могли более легко найти это решение). Затем добавьте ссылку с этого вопроса на новый. –

ответ

7

Там может быть много причин:

Если проблема связана с внешними ключами, обычным решением является добавление индексов в чужой столбец: для каждого удаления Oracle необходимо проверить, будет ли это нарушать отношение внешнего ключа.

+0

Как проверить, заблокированы ли строки кем-либо? –

+0

Я добавил пару ссылок. –

+0

поэтому стол был заблокирован многими сеансами. см. отредактированный вопрос. Как убить сеансы? –

1

Очевидно, что операция удаления займет больше времени, чем выбор, но это не учитывает разницу, которую вы видите.

Похоже, что дополнительный код запускается при удалении, что указывает на наличие триггеров в таблице, которая также работает. Вы можете это проверить?

+0

нет никаких триггеров на столе, а также никаких СЛУЧАЙНЫХ ОГРАНИЧЕНИЙ. –

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; 
+0

Спасибо, Hubert. Я хочу выяснить, почему оператор DELETE так медленно, так как в таблице всего около 100 тыс. Записей. –

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% от общего количества строк.)

Смежные вопросы