![]() |
| ||
|
|
Новости |
Поиск |
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-29 05:05:00) [41]если перейду к firebird то буду пользоваться только IBQuery (FBPlus - рекомендуют). :)
Есть ли задачи где query не эффективен или мало эффективен по сравнению с table?
P.S. программирование не является приоритетным направлением, есть несколько разработанных локальных БД на paradox... по большей части для души...
Inovet (2009-10-29 04:56:00) [42]> [37] Dim!S (29.10.09 04:48)
Тут шикник часто пишет про костыли в АДО Table, Query к IBX это тоже применимо - не пользуйся TIBTable
Dim!S (2009-10-29 04:48:00) [43]>PEAKTOP Спасибо за код и книги... Первая у меня есть только под Delphi 4.
Не помню где (постараюсь найти), но при поиске инфы по IBTable встретил, что при работе с локальной БД FireBird этот компонент не хуже IBQuery. Так как имел опыт только с Table (Paradox), то решил его использовать, и при обработке получил out of memory - пришлось обратиться к помощи форума, т.к. не хвататает знаний как использовать IBTransaction с IBTable (тем более с IBQuery). Интересует транзакцию можно поставить на весь проход таблицы (думаю не стоит этого делать) или на какой-то блок (по N записей)...
В приведённом коде транзакция охватывает всю обработку таблицы за один проход, так? Какие могут быть проблемы с большими НД (сотни тысяч записей)?
P.S. Всем большое спасибо, но думаю тема не закрыта :)
PEAKTOP (2009-10-29 04:09:00) [44]> На "исходниках" уж очень скушно.
А ты на sql.ru в ветку Firebird зайди. Там Delphi никто не знает :)
А на Королевстве - всё зашорено.
Я помню описание сего ресурса данное HORRIFIC-ом в журнале XAKEP спец №4 еще в марте 2000 года: "сразу видно, что проект ведет женщина" и что ресурс развивается в сторону своего полного вырождения.
Кстати, страницей ранее тот же автор предсказывал TORRY.NET долгие лета. Как видно, он оказался прав в обоих случаях.
PEAKTOP (2009-10-29 03:48:00) [45]> Как реализовать это через IBQuery (и надо ли? будет ли какой-
> то выигрыш от перехода на IBQuery, если бд будет обрабатываться
> на сервере)?"
Читать для понимания работы с БД вообще и с особенностями Firebird в часности.
1) http://www.ozon.ru/context/detail/id/97142/
2) http://www.ozon.ru/context/detail/id/2496996/
Когда дойдешь до команд SQL, смотри русскоязычную справку c учетом версий сервера Firebird, некоторые команды в InterBase и в Firebird отличаются, некоторых в InterBase вообще нет, а некторорые появились только в недавних версиях сервера и не будут работать, например, в Firebird 1.5/
http://firebirdsql.su/
PEAKTOP (2009-10-29 03:40:00) [46]> P.S. с удовольствием готов пойти по правильному пути, только
> зная почему нужно делать так, а не иначе...
пилять...
procedure DeleteRecords;
var
lkTr :TIBTransaction;
lkSQL :TIBSQL;
begin
lkTr := TIBTransaction.Create(nil);
lkTr.DataBase := IBDataBase1;
lkTr.Params.Clear;
lkTr.Params.Add('isc_tpb_consistency');
lkTr.Params.Add('isc_tpb_write');
lkSQL := TIBSQL.Create(lkTr);
lkSQL.DataBase := lkTr.DataBase;
lkSQL.Transaction := lkTr;
lkSQL.SQL.Text := 'DELETE FROM MYTABLE TB1 WHERE (TB1.FIELD = ...) AND (TB1.FIELD2 = ...)';
lkTr.StartTransaction;
try
lkSQL.ExecSQL;
except
Dialogs.MessageDlg('Не удалось удалить ....', mtError, [mbOk],0);
lkTr.Rollback;
end;
if lkTr.InTransaction then
lkTr.Commit;
lkTr.Free; // lkSQL.Free будет вызван автоматически, т.к. его Owner = lkTr
end;
Dim!S (2009-10-29 03:02:00) [47]1. if cnt_Rec < 4 then
begin
if EOF then Break; //а вдруг конец таблицы достигнем в цикле (спасибо Сергей М. за подсказку)
Delete;
Inc(cnt_Rec);
end else
begin
cnt_Rec := 0;
Next;
end; //после этого места возвращаемся к началу ветки if
и пытаемся удалить очередные 4 записи
На деле будет такая ситуация:
в таблице 8 записей
после первого прохода осталось 4 записи курсор встал на 2 запись;
во время второго прохода после удаления 4 записи (2 шаг цикла) мы пытаемся удалить 5 - не существующую запись! - получаем ошибку. Для исключения ошибочной ситуации и проверяем остижение конца таблицы...
2. ну так я ещё в первм посте писал "Может лучше через IBQuery ии есть более изящный способ?" - но конкретного ответа не получил, а именно:
"Интересует как это всё завернуть в транзакции, где ставить StartTransaction и Commit?
Как реализовать это через IBQuery (и надо ли? будет ли какой-то выигрыш от перехода на IBQuery, если бд будет обрабатываться на сервере)?"
3. Чем всё-таки плох IBTable в данной ситуации по сравнению с IBQuery?
P.S. с удовольствием готов пойти по правильному пути, только зная почему нужно делать так, а не иначе...
Германн (2009-10-29 02:43:00) [48]
> PEAKTOP © (29.10.09 02:33) [31]
>
> Весело здесь у вас, ребята...
> Не, ну правда.
"Дорогая передача!
Во субботу, тут, не плача
Вся Канатчикова дача..."
И т.д.
Тем и живём. :)
На "исходниках" уж очень скушно. А на Королевстве - всё зашорено.
PEAKTOP (2009-10-29 02:33:00) [49]Весело здесь у вас, ребята...
Не, ну правда.
Топикстартер задает вопрос, почему его велосипед с квадратными колесами не едет ? При этом все дружно начинают давать советы, вплоть до того, что мол попробуй треугольные колеса или пятиугольные.
На 12(!) посте была попытка намекнуть на то, что пора бы уже открыть для себя SQL-оператор DELETE, но все присутствующие ее упорно игнорируют и продолжают рассматривать варианты с шести и семиугольными колесами...
На 29(!) посте наконец-то кому-то все-таки приходит мысль: о, блин, точно ! оператор DELETE! Но это не останавливает участников обсуждения и рассматривается вариант: а может на велосипед поставить гусеницы ? а то с колесами у него говорят баги...
Я фигею, дорогая редакция... :(
Германн (2009-10-29 01:39:00) [50]
> Есть бд на Firebird 1.5
Были какие-то похожие глюки с 1.5.
Стоит поискать на ibase.ru сведения о багах версий 1.5.x
P.S. Но все предыдущие замечания знатоков работы с БД, я не отрицаю.
Amoeba (2009-10-29 01:20:00) [51]
> А не проще используя SQL-запрос
> типа delete from table where [твое условие]
И не просто проще, а только так и не иначе.
SergP (2009-10-28 21:10:00) [52]
> Пусть будет и не 4 выдернули одну оставили, а по условию
> проверки значения поля через if c несколькими ветками -
> неважно, главное как проредить всю таблицу - быстро и корректно.
>
А не проще используя SQL-запрос
типа delete from table where [твое условие]
?
Сергей М. (2009-10-28 20:17:00) [53]
> while not(EOF) do
> if cnt_Rec < 4 then
> begin
> if EOF then Break; //а вдруг конец таблицы
> достигнем в цикле (спасибо Сергей М. за подсказку)
С какого перепугу этот "а вдруг" может приключиться ?
sniknik (2009-10-28 19:26:00) [54]> - прочитал... :) про x, y, z ... :) занятно...
ага.
- вы алгебру вообще читали?
- читал, а как же, ее еще в конце убили...
на на свою ситуацию эти x, y, z переложить не в силах? ведь один в один все получается... если счас сказать как-же все таки сделать, то пойдешь ты радостно доделывать своего монстра (и как там дальше по тексту?)
а запросы (правильный z путь) попросту игнорируешь (не понимаешь что это/понимаешь неправильно, а считаешь что совет неправильный, и т.д. неважно по какой причине, но сделал вид, что никто ничего про них не говорил... точно как в статье).
Dim!S (2009-10-28 18:51:00) [55]памяти добавлять не вариант и так 2 гига, да и не верный это путь... надо с алгоритмом мудрить чтобы не зависело от аппаратной части...
Я правильно понимаю что большой НД (больше 100 тыс. записей (ну ещё кол-во и тип полей нужно учитывать)) нельзя пройти за раз в цикле на удаление?
Неужели нельзя удалить из базы все записи кроме некоторых (по условию)? - что-то мне подсказывает что можно, но мой уровень общения с firebird не говорит как это сделать...
Dim!S (2009-10-28 18:45:00) [56]Unidirectional=True - как я понял при удалении записей некорректно себя ведёт IBTable c этим параметром в true... Скачет по таблице не по порядку или я заблуждаюсь...
Виталий Панасенко(дом) (2009-10-28 18:37:00) [57]обойти нехватку памяти.. попробуй Unidictional=True, добавить памяти, увеличить своп
Виталий Панасенко(дом) (2009-10-28 18:23:00) [58]вот именно, накладно...
Dim!S (2009-10-28 18:20:00) [59]Сколько можно максимум обработать (удалить) записей за одну транзакцию? Как обойти ошибку Out Of Memory на больших НД? Наврядли нужно каждую запись удалять через транзакцию - слишком накладно будет...
Виталий Панасенко(дом) (2009-10-28 18:16:00) [60]странный вопрос... где тебе нужно, там и ставь.. только от Out of memory На больших НД это тебя вряд ли спасет