|
Удаление большого объема в логируемом состоянии
|
|||
---|---|---|---|
#18+
Есть громадная таблица - там около миллиарда записей. Изменение данных в рабочих таблицах привело к необходимости удаления примерно 10% записей в архивной таблице. Сервер работает 24/7/365, поэтому перевод в нелогируемое состояние невозможен. Отсюда - вопрос. Можно как-то штатно выполнить delete чтобы оно удаляло только какую-то часть записей? Потому что если выполнить delete сразу на весь объем удаляемых записей, то, предполагаю, что серверу станет плохо. Приходится удалять SPL-кой по принципу Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
При этом поле Lid имеет индекс, но, насколько я понимаю, судя по скорости выполнения, использование rowid приводит к sequential scan, а это нереально тормозно. В придачу, распределение rowid по удаляемым записям, мягко говоря, неравномерное, что приводит к выполнению удалений, которые ничего не удаляют из-за неправильного диапазона rowid которые перебираются последовательно при указанном мной методе. Есть какое-то решение, как удалять записи по типу delete first 50000 from... или какой-то другой метод решения проблемы удаления большого числа записей? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2009, 14:51 |
|
Удаление большого объема в логируемом состоянии
|
|||
---|---|---|---|
#18+
falcon111 Сервер работает 24/7/365, поэтому перевод в нелогируемое состояние невозможен. 1. Вы не сказали версию информикса. 2. Нелогируемой можно сделать одну таблицу (raw). 3. Что такое MaximumId? Удаляйте where Lid not in ValidLids and Lid<=MaximumId and Lid >= MaximumId - 5000 ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2009, 15:43 |
|
Удаление большого объема в логируемом состоянии
|
|||
---|---|---|---|
#18+
Журавлев Денис1. Вы не сказали версию информикса. Мне казалось, что здесь версия особой роли не играет. Исправляюсь. 11.50FC5 на w2003x64 Журавлев Денис2. Нелогируемой можно сделать одну таблицу (raw). Насколько я понимаю, это приведет к ошибкам в работе добавления записей в эту таблицу, так как там записи тоже добавляются как часть общей транзакции выполнения клиентского запроса. Журавлев Денис3. Что такое MaximumId? Удаляйте where Lid not in ValidLids and Lid<=MaximumId and Lid >= MaximumId - 5000 MaximumId - это защита от удаления записей с новыми идшниками, появившимися в системе во время выполнения процедуры удаления. where Lid between MaximumId-5000 and MaximumId так же трудно прогнозируется число записей, по одному lid записей может быть несколько тысяч, а по другому - десятки миллионов. Я уже подумываю выбирать lid, count(*) во временную таблицу, и потом удалять записи по ней, но все равно это будет работать до тех пор пока не возникнет необходимость удаления какого-нибудь старого объекта по которому будет много записей и все вернется к началу ;( ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2009, 15:56 |
|
Удаление большого объема в логируемом состоянии
|
|||
---|---|---|---|
#18+
falcon111Журавлев Денис1. Вы не сказали версию информикса. Мне казалось, что здесь версия особой роли не играет. Исправляюсь. 11.50FC5 на w2003x64ну вот например raw появились в определенной версии, а потом спустя несколько версий появилась возможность иметь индексы на raw таблицах. falcon111Журавлев Денис2. Нелогируемой можно сделать одну таблицу (raw). Насколько я понимаю, это приведет к ошибкам в работе добавления записей в эту таблицу, так как там записи тоже добавляются как часть общей транзакции выполнения клиентского запроса. значит отбрасываем этот вариант. falcon111Журавлев Денис3. Что такое MaximumId? Удаляйте where Lid not in ValidLids and Lid<=MaximumId and Lid >= MaximumId - 5000 MaximumId - это защита от удаления записей с новыми идшниками, появившимися в системе во время выполнения процедуры удаления. where Lid between MaximumId-5000 and MaximumId так же трудно прогнозируется число записей, по одному lid записей может быть несколько тысяч, а по другому - десятки миллионов. Я уже подумываю выбирать lid, count(*) во временную таблицу, и потом удалять записи по ней, но все равно это будет работать до тех пор пока не возникнет необходимость удаления какого-нибудь старого объекта по которому будет много записей и все вернется к началу ;(план вашего delete тогда смотрите, есть там или нет seq scan таблицы первичный ключ суррогатный есть? ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2009, 16:04 |
|
Удаление большого объема в логируемом состоянии
|
|||
---|---|---|---|
#18+
Журавлев Денис]план вашего delete тогда смотрите, есть там или нет seq scan таблицы первичный ключ суррогатный есть? Иными словами, штатной возможности лимитировать число удаленных записей действительно нет? Только самодельными костылями по rowid/lid/прочее? Жаль, я так надеялся что решение есть и я просто чего-то не знаю ;-) ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2009, 16:09 |
|
Удаление большого объема в логируемом состоянии
|
|||
---|---|---|---|
#18+
Почему нет? все есть, только нужно найти как єто использовать Можно удалять все пачкой, а можно удалять по одной записи begin work ; foreach select first 50000 ... delete ... end foreach; commit ; А если и есть пустой диапозон, то как он вам не мешает - ну будут пустые транзакции ну и фиг с ними. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2009, 21:42 |
|
Удаление большого объема в логируемом состоянии
|
|||
---|---|---|---|
#18+
zaietsbegin work ; foreach select first 50000 ... delete ... end foreach; commit ; Первый вариант был именно такой. Получается наиболее медленно. Настолько что использовать нет смысла. zaietsА если и есть пустой диапозон, то как он вам не мешает - ну будут пустые транзакции ну и фиг с ними. Пустые-то они ПОЛУЧАЮТСЯ пустые, только на их ПОЛУЧЕНИЕ тратятся ресурсы, время в первую очередь. В конечном итоге решил выборкой lid, count(*) во временную таблицу, потом группирую идшники так чтобы получить максимально приближенное число записей к желаемому в пределах одной транзакции и удаляю по одному только индексированному lid - получается наиболее быстро. Решение всем бы красивое, если бы не непонятки с "массивными" lid-шниками. Если подскажете более практичное решение - буду благодарен :) ... |
|||
:
Нравится:
Не нравится:
|
|||
25.12.2009, 21:57 |
|
Удаление большого объема в логируемом состоянии
|
|||
---|---|---|---|
#18+
Вы сами нашли решение, которое наиболее устраивает вас по скорости. По поводу "массивных" - ничего сложного не вижу. Вычислите какая максимально возможна массивность для вашей конфигурации и подберите соответствующий диапозон для удаления. В принципе,если делаете через временную таблицу, для временной таблицы можно сделать поле сериал и после помещения данных в таблицу в процедуре реализовать алгоритм подсчета коунтов и дробления записей для удаления. Чем вызвано ваше ограничение по времени? у меня обычно задача стояла как-бы немного замедленнить эту операцию - запустить в фоне и пускай работает особо никому не мешая. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.12.2009, 00:39 |
|
Удаление большого объема в логируемом состоянии
|
|||
---|---|---|---|
#18+
falcon111Пустые-то они ПОЛУЧАЮТСЯ пустые, только на их ПОЛУЧЕНИЕ тратятся ресурсы, время в первую очередь. ну нам что-ли покажите план запроса. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.12.2009, 08:54 |
|
Удаление большого объема в логируемом состоянии
|
|||
---|---|---|---|
#18+
Ну вы даете. На хрена один и тот же запрос гонять тысячи раз ? Пишите SP вида : declare i, vsp int; let i = 0; begin work; foreach cur1 with hold for <select condition for deleted records> delete from arc_01 where current of cur1; let i = i +1; if i > 5000 then let i = 0; commit work; begin work; end foreach; commit work; ... |
|||
:
Нравится:
Не нравится:
|
|||
28.12.2009, 21:00 |
|
Удаление большого объема в логируемом состоянии
|
|||
---|---|---|---|
#18+
ВыбегаллоНу вы даете. На хрена один и тот же запрос гонять тысячи раз ? Пишите SP вида : declare i, vsp int; let i = 0; begin work; foreach cur1 with hold for <select condition for deleted records> delete from arc_01 where current of cur1; let i = i +1; if i > 5000 then let i = 0; commit work; begin work; endif end foreach; commit work; ... |
|||
:
Нравится:
Не нравится:
|
|||
29.12.2009, 17:05 |
|
Удаление большого объема в логируемом состоянии
|
|||
---|---|---|---|
#18+
ВыбегаллоНу вы даете. На хрена один и тот же запрос гонять тысячи раз ?Потому и обратился за помощью, что это не правильно :) Выбегаллоdelete from arc_01 where current of cur1;Вот оно! Это и был судя по всему тот самый пробел в моих познаниях, я не знал, что в foreach можно так использовать выбранные строки, и мне, кстати, частенько этой возможности не хватало. Теперь тема раскрыта полностью, огромное спасибо!! :-) PS: А с какой версии существует where current of ? ... |
|||
:
Нравится:
Не нравится:
|
|||
29.12.2009, 17:52 |
|
Удаление большого объема в логируемом состоянии
|
|||
---|---|---|---|
#18+
falcon111 PS: А с какой версии существует where current of ? В 7.31 уже был точно. Достаточно? :) ... |
|||
:
Нравится:
Не нравится:
|
|||
29.12.2009, 17:59 |
|
Удаление большого объема в логируемом состоянии
|
|||
---|---|---|---|
#18+
АнатоЛойfalcon111 PS: А с какой версии существует where current of ? В 7.31 уже был точно. Достаточно? :) Да *стыдливо ковыряя ботинком землю* ;-)) Пошел посмотрю PDFку на предмет аналогичных дырок в моей голове :) ... |
|||
:
Нравится:
Не нравится:
|
|||
29.12.2009, 18:04 |
|
|
start [/forum/topic.php?fid=44&msg=36387489&tid=1607662]: |
0ms |
get settings: |
9ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
44ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
49ms |
get tp. blocked users: |
1ms |
others: | 14ms |
total: | 151ms |
0 / 0 |