Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Удаление большого количества записей firebird 1.5 [D6, firebird]


Страницы:   1 2 3 4

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 а код оставиш неизменным...)


Страницы:   1 2 3 4

Наверх

Титульная страница Поиск, карта сайта Написать письмо