![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Удаление большого количества записей firebird 1.5 [D6, firebird]
Dim!S © (2009-10-28 08:43:00)Уважаемые форумчане!
Есть бд на Firebird 1.5 (gdb). Необходимо из неё удалить каждые несколько записей...
вот кусок кода, но иногда программа выдаёт сообщение out of memory
...
IBTable1.DisableControls;
cnt_Rec := 0;
IBTable1.First;
with IBTable1 do
while not(EOF) do
begin
IBTable1.First;
Delete;
Delete;
Delete;
Delete;
Next;
Inc(cnt_Rec);
Application.ProcessMessages;
if cnt_Rec >= 10000 then
begin
ShowMessage(IntToStr(RecNo) + ' - ' + IntToStr(cnt_Rec));
cnt_Rec := 0;
IBTransaction1.Commit;
IBTransaction1.StartTransaction;
end;
end;
IBTransaction1.Commit;
IBTable1.EnableControls;
Label2.Caption := TimeToStr(Time);
IBTable1.Refresh;
...
Как лучше написать код для указанной задачи? Записей в таблице может быть миллион. К базе никто не подключен... Может лучше через IBQuery ии есть более изящный способ?
P.S. с firebird дело не имел вообще, только с paradox
Большое спасибо.
Dim!S (2009-10-28 17:51:00) [61]:) ок, получается:
с использованием IBTable
procedure DelRec;
var cnt_Rec: longint; //наврядли будет больше 2 млрд. записей :)
begin
with IBTable do
begin
First;
cnt_Rec := 0;
while not(EOF) do
if cnt_Rec < 4 then
begin
if EOF then Break; //а вдруг конец таблицы достигнем в цикле (спасибо Сергей М. за подсказку)
Delete;
Inc(cnt_Rec);
end else
begin
cnt_Rec := 0;
Next;
end;
end;
end;
Интересует как это всё завернуть в транзакции, где ставить StartTransaction и Commit?
Как реализовать это через IBQuery (и надо ли? будет ли какой-то выигрыш от перехода на IBQuery, если бд будет обрабатываться на сервере)?
Сергей М. (2009-10-28 17:36:00) [62]счетчик_последовательно_выдернутых_морковок = 0
подойти к началу грядки;
пока не конец грядки делать
начало
если счетчик_последовательно_выдернутых_морковок < 4 то
начало
выдернуть морковку (нос при этом автоматически уткнется или в следующую морковку или в конец грядки)
увеличить счетчик_последовательно_выдернутых_морковок на 1
конец
иначе
начало
счетчик_последовательно_выдернутых_морковок = 0
передвинуть нос к возможной следующей морковке
конец
конец
Dim!S (2009-10-28 17:16:00) [63]"все таки не прочитал ты статью по ссылке. Жаль" - прочитал... :) про x, y, z ... :) занятно...
отбор будет по критерию 4 выдернули одну оставили из всей таблицы. Возможно условие отбора будет изменено, но мне главное как корректно пройти всю таблицу на предмет прореживания. Пусть будет и не 4 выдернули одну оставили, а по условию проверки значения поля через if c несколькими ветками - неважно, главное как проредить всю таблицу - быстро и корректно.
Спасибо.
Сергей М. (2009-10-28 17:10:00) [64]
> Необходимо часть сведений из бд убирать
Так вот и интересно, по какому критерию требуется осуществлять "прореживание" ?
Четыре очередные морковки дергаем, следующую пятую оставляем, пока либо не подрали всю грядку либо количество этих телодвижений (4 дернули, одну оставили) не превысило 10000,
так что ли ?)
Sergey13 (2009-10-28 16:58:00) [65]> [14] Dim!S (28.10.09 16:42)
Все таки не прочитал ты статью по ссылке. Жаль.
Dim!S (2009-10-28 16:42:00) [66]действительно интересно? ;)
Необходимо часть сведений из бд убирать... Варианты есть разные... один из них - регулярное копирование и прореживание бд (хотя уже нарисовался и другой путь, но всё же интересно как реализовать алгоритм для указанной задачи по приведённому варианту)... область раскрывать не буду, цель, думаю, понятна... ;)
По теме можете что сказать?
Сергей М. (2009-10-28 16:07:00) [67]
> подскажите кусочек кода по оптимальному прореживанию БД
Просто интересно, кто же так густо засадил эту грядку, как часто придется ее прореживать и что потом делать с урожаем ?
Sergey13 (2009-10-28 15:48:00) [68]> [11] Dim!S (28.10.09 15:12)
> Форумчане, подскажите кусочек кода по оптимальному прореживанию БД. Спасибо.
delete from tablename
truncate table tablename
Dim!S (2009-10-28 15:12:00) [69]"флаг EOF ты проверяешь всего один раз перед каждой итерацией цикла" -
ну конечно же!!! Большое спасибо....
И всё-таки морковка... :)
Форумчане, подскажите кусочек кода по оптимальному прореживанию БД. Спасибо.
Сергей М. (2009-10-28 11:23:00) [70]
> как можно проредить базу данных?
Значит все-таки морковка)
Ну ты сам посуди - флаг EOF ты проверяешь всего один разперед каждой итерацией цикла. А в теле цикла ты беспардонно пытаешься удалить столько записей, сколько тебе захотелось, нисколько не задумываясь о том, что при очередном delete или next этот флаг может принять значение True !
Sergey13 (2009-10-28 11:21:00) [71]> [8] Dim!S (28.10.09 11:13)
Ты сначала глянь, а потом сформулируй вопрос. 8-)
Dim!S (2009-10-28 11:13:00) [72]Спасибо за ссылку, гляну...
И всё же, как можно проредить базу данных?
Или лучше создать новую и в неё каждую n-ю запись добавлять?
Sergey13 (2009-10-28 11:13:00) [73]> [6] sniknik © (28.10.09 11:00)
> http://www.delphimaster.ru/cgi-bin/forum.pl?id=1256632484&n=18
> в [28] там ссылка на хорошую статью.
Шикарно! 8-)
> [4] Dim!S (28.10.09 10:55)
> Не спрашивайте зачем ;)
Прочитай обязательно статейку!
Ты же просишь "изящный способ", но скрываешь условия. И где логика?
sniknik (2009-10-28 11:00:00) [74]> Не спрашивайте зачем ;)
> Я предполагаю так:
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1256632484&n=18
в [28] там ссылка на хорошую статью. мне понравилась. и ведь именно так все и есть...
Сергей М. (2009-10-28 11:00:00) [75]
> С реализацией туговато, ввиду отсутствия практического опыта
> работы с FireBird
Те же самые грабли хряснут по тому же самому месту и в Парадоксе.
СУБД здесь ни причем.
> грабли на таблице в 50 МБ (150 тыс) не бьют
Понатыкай в тело цикла вместо четырех 150 тыс. вызовов метода delete - лупанут всенепременно)
Dim!S (2009-10-28 10:55:00) [76]>Sergey13 а в чём чудность? Ну если так нао, именно каждые 4 или 5 или 6 записей оставляя следующую. Не спрашивайте зачем ;)
>Сергей М. грабли на таблице в 50 МБ (150 тыс) не бьют :) а вот больше засада...
>All Форумчане! Дайте, пожалуйста, намётки на реализацию этой задачи...Я предполагаю так:
начинаем транзакцию
удаляем (допустим 50 тыс. записей)
заканчиваем транзакцию
и это в цикле от первой записи до последней
С реализацией туговато, ввиду отсутствия практического опыта работы с FireBird...
Спасибо.
Сергей М. (2009-10-28 09:54:00) [77]
> Записей в таблице может быть миллион
А может быть и не миллион, а, скажем, всего дюжина.
И тогда грабли хлобыстнут еще больней, чем по out of memory
Sergey13 (2009-10-28 09:31:00) [78]Честно говоря, чуднее алгоритма удаления из таблицы я не встречал. Типа оставить только каждую пятую запись? Похоже на прореживание моркови на грядке.
А смысл этого действа, если не сложно, можешь рассказать?
sniknik (2009-10-28 09:02:00) [79]> Может лучше через IBQuery
неважно через что... главное запросом. (а то ты счас поменяешь компонент с IBTable1 на IBQuery а код оставиш неизменным...)