какой оператор удаления лучше для удаления миллионов строк - PullRequest
0 голосов
/ 07 июня 2019

У меня есть таблица, которая содержит миллионы строк.Я хочу удалить все данные старше недели на основе значения столбца last_updated.

, поэтому вот мои два запроса,

Подход 1:

Delete from A where to_date(last_updated,''yyyy-mm-dd'')< sysdate-7;

Подход 2:

l_lastupdated varchar2(255) := to_char(sysdate-nvl(p_days,7),'YYYY-MM-DD');
insert into B(ID) select ID from A where LASTUPDATED < l_lastupdated;
delete from A where id in (select id from B);

Какой из них лучше, учитывая производительность, безопасность и блокировку?

Ответы [ 3 ]

1 голос
/ 07 июня 2019

Ваш сохраненный формат даты кажется подходящим для правильной сортировки, так что вы можете пойти другим путем и преобразовать sysdate в строку:

--this is false today    
select * from dual where '2019-06-05' < to_char(sysdate-7, 'YYYY-MM-DD'); 

--this is true today
select * from dual where '2019-05-05' < to_char(sysdate-7, 'YYYY-MM-DD'); 

Таким образом, это будет:

Delete from A where last_updated < to_char(sysdate-7, ''yyyy-mm-dd'');

Itимеет преимущество в том, что будет использоваться ваш индекс по умолчанию (если он есть).

Он имеет недостаток в том, что полагается на упорядочение String / Varchar, которое может быть изменено, т.е. изменения NLS bei (если я правильно помню),так что в любом случае вы должны сделать небольшое тестирование перед ...

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

0 голосов
/ 12 июня 2019

Предполагая, что удаление удаляет значительную часть данных и миллионы строк, подойдите к трем:

create table tmp
  Delete from A where to_date(last_updated,''yyyy-mm-dd'')< sysdate-7;

drop table a;

rename tmp to a;

https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:2345591157689

Очевидно, вам нужно скопироватьвсе индексы, гранты и т. д. Но переопределение в режиме онлайн может помочь в этомперейдите к 12.2, есть еще один более простой вариант: отфильтрованное перемещение.

Это операция изменения таблицы с дополнительным предложением, указывающим, какие строки вы хотите сохранить:

create table t (
  c1 int
);

insert into t values ( 1 );
insert into t values ( 2 );
commit;

alter table t
  move including rows where c1 > 1;

select * from t;

C1   
    2 

Пока вывы ждете обновления до 12.2+ и если по какой-то причине вы не хотите использовать метод create-as-select, подход 1 лучше:

  • Оба метода удаляют одинаковые строки из A* => это тот же объем работы, что и при удалении
  • Вариант 1 имеет одно утверждение;Вариант 2 имеет два утверждения;2> 1 => опция 2 - это больше работы

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

С помощью только удаления обновление будет заблокировано до завершения удаления.В этот момент строка исчезла, поэтому обновление ничего не делает.

Принимая во внимание, что если вы выполняете вставку первой, другой сеанс может обновить и зафиксировать строку до завершения вставки.Таким образом, обновление "успешно".Но удаление тогда удалит это!Что может привести к несчастным клиентам ...

0 голосов
/ 07 июня 2019

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

create <new table name> as
select *
from   <old table name>
where  <predicates for the data you want to keep>;

тогда

drop table <old table name>;

и, наконец, вы можете переименовать новую таблицу обратно в старую таблицу.

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

Таким образом, когда вам нужно удалить строки, достаточно просто удалить соответствующие разделы.

...