Как удалить большие данные из БД Oracle 9i? - PullRequest
1 голос
/ 02 февраля 2010

У меня есть таблица размером 5 ГБ, теперь я пытался удалить, как показано ниже:

delete  from tablename
where to_char(screatetime,'yyyy-mm-dd') <'2009-06-01' 

Но он работает долго и не отвечает. Тем временем я попытался проверить, блокирует ли это кто-то ниже:

select l1.sid, ' IS BLOCKING ', l2.sid
from v$lock l1, v$lock l2
where l1.block =1 and l2.request > 0
and l1.id1=l2.id1
and l1.id2=l2.id2

Но я также не нашел никаких блокировок.

Как я могу удалить эти большие данные без проблем?

Ответы [ 4 ]

1 голос
/ 02 февраля 2010

5ГБ - бесполезное измерение размера таблицы.Общее количество строк имеет значение.Количество строк, которые вы собираетесь удалить как доля от общего значения.Средняя длина строки имеет значение.

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

С другой стороны, если вы удаляете большой кусок строк, вы можете найти еголучше

  1. Создать копию таблицы, используя 'create table t1_copy as select * from t1, где screatedate> = to_date (' 2009-06-01 ',' yyyy-mm-dd ') `
  2. Поменяйте местами таблицы с помощью команды rename.
  3. Повторно примените ограничения, индексы к новому T1.

Еще одна вещь, которую следует иметь в виду, заключается в том, чтоудаления поглощают больше UNDO, чем другие транзакции, потому что они требуют больше информации для отката.Поэтому, если ваши записи длинные и / или многочисленные, вашему администратору БД может потребоваться проверить табличное пространство UNDO (или сегменты отката, если вы все еще используете их).

Наконец, вы провели какое-либо расследование, чтобы выяснить, где находитсявремя на самом деле идет?Операторы DELETE - это просто еще один запрос, и их можно решить, используя обычный набор настроек.

1 голос
/ 02 февраля 2010

Если в screatetime есть индекс, ваш запрос может его не использовать. Измените свое утверждение, чтобы предложение where могло использовать индекс.

delete from tablename where screatetime < to_date('2009-06-01','yyyy-mm-dd')
1 голос
/ 02 февраля 2010

Он работает НАМНОГО быстрее, когда вы сначала блокируете стол. Также измените предложение where, как предложено Рене.

LOCK TABLE tablename IN EXCLUSIVE MODE;

DELETE FROM tablename
where screatetime < to_date('2009-06-01','yyyy-mm-dd');

РЕДАКТИРОВАТЬ: Если таблица не может быть заблокирована, потому что к ней постоянно обращаются, вы можете выбрать тактику салями, чтобы удалить эти строки:

BEGIN
  LOOP
    DELETE FROM tablename
      WHERE screatetime < to_date('2009-06-01','yyyy-mm-dd')
        AND ROWNUM<=10000;
    EXIT WHEN SQL%ROWCOUNT=0;
    COMMIT;
  END LOOP;
END;

В целом, это будет медленнее, но это не приведет к разрыву сегмента отката, и вы сможете увидеть прогресс в другом сеансе (т. Е. Количество строк в имени таблицы уменьшается). И если вам по какой-то причине придется его убить, откат не будет длиться вечно, и вы еще не потеряли всю проделанную работу.

1 голос
/ 02 февраля 2010
  • Использование условия запроса для экспорта необходимых строк
  • Усеченный стол
  • Импорт строк
...