Страница 1 из 3

Blob and update

Добавлено: 20 июн 2006, 14:14
CCB
При апдейте поля типа BLOB происходит замедление этого самого апдейта. Изменяются примерно 100-300 записей по одной, на первых 20-30-ти работает нормально, а потом постепенно начинаются тормоза и после 50-70 записей тормоза просто жуткие. В чем может быть проблема?
Размер одной записи около килобайта с блобом.
FireBird 1.5, Delphi 6, IBX.

Добавлено: 20 июн 2006, 15:27
kdv
скорее всего в использовании датасета для вставки блобов. используй IBSQL или IBQuery с оператором insert.

Добавлено: 20 июн 2006, 15:37
CCB
kdv писал(а):скорее всего в использовании датасета для вставки блобов. используй IBSQL или IBQuery с оператором insert.
использую IBQuery (пробовал и IBSQL). зачем инсерт? тогда нужно предварительно убивать запись? при вставке наверняка индексы будут перестраивацца...

Добавлено: 20 июн 2006, 16:24
kdv
зачем инсерт?
если обновляешь - тогда update. Ты читал
www.ibase.ru/devinfo/impexp.htm ? У тебя случай "импорта" данных, раз ты пишешь что
Изменяются примерно 100-300 записей
соответственно при движении по датасету у тебя скорее всего происходит перечитывание всего запроса. Это самая естественная причина замедления при выполнении идентичных операций.

Добавлено: 21 июн 2006, 08:09
CCB
kdv писал(а):
зачем инсерт?
если обновляешь - тогда update. Ты читал
www.ibase.ru/devinfo/impexp.htm ? У тебя случай "импорта" данных, раз ты пишешь что
Изменяются примерно 100-300 записей
соответственно при движении по датасету у тебя скорее всего происходит перечитывание всего запроса. Это самая естественная причина замедления при выполнении идентичных операций.
сцылку почитал.
вот как у меня реализовано:
(пробовал и IBSQL вместо IBQuery)

while not IBQueryMain.Eof do
begin
IBQueryUPD.SQL.Clear;
IBQueryUPD.SQL.Add('update Objects set Info=:ParamInfo where ID='+IBQueryMain.FieldByName('IDObj').AsString);
Stream:=TStringStream.Create(StrStream);
Stream.WriteComponent(Info);
Stream.Seek(0, soFromBeginning);
IBQueryUPD.ParamByName('ParamInfo').LoadFromStream(Stream, ftBlob);
IBQueryUPD.ExecSQL;
Stream.Free;
IBQueryMain.Next
end;


в поле Info типа Blob сохраняются свойства объектов, иногда (крайне редко) эти свойства нужно изменить сразу у 100-300 объектов и тут начинаецца описаное выше...
честно признаюсь - при чем тут импорт/экспорт не понимаю...

Добавлено: 21 июн 2006, 10:17
CCB
AlexandrS писал(а):Глупый конечно вопрос, но все же. Индекс на поле IDObj стоит? Если нет, то поставьте.
primary key

Добавлено: 21 июн 2006, 11:51
WildSery
AlexandrS писал(а):Думаю вот так по быстрее должно быть, хотя не проверял:
Создание/удаление объекта TStream настолько быстрая процедура, что на работу не повлияет.

Добавлено: 21 июн 2006, 11:59
CCB
WildSery писал(а):
AlexandrS писал(а):Думаю вот так по быстрее должно быть, хотя не проверял:
Создание/удаление объекта TStream настолько быстрая процедура, что на работу не повлияет.
я канешна сильно звиняюсь, но вопрос не про стрим, а то мы щас уползем совсем в другую сторону... кстати? этот код из старой версии, реально используецца не TStringStream, а TMemoryStream...

Добавлено: 21 июн 2006, 12:09
WildSery
CCB писал(а):я канешна сильно звиняюсь, но вопрос не про стрим, а то мы щас уползем совсем в другую сторону... кстати? этот код из старой версии, реально используецца не TStringStream, а TMemoryStream...
Никто никуда не уползает. Был дан совет переделать без создания TStream, что мол будет быстрее. Я ответил, что быстрее не будет, совет практически бесполезен. Какой именно поток используется, блобу до лампочки, это всё потомки от TStream.

Если коммит каждого изменения делать? Или это недопустимо логикой алгоритма?

Добавлено: 21 июн 2006, 12:34
CCB
WildSery писал(а):Если коммит каждого изменения делать? Или это недопустимо логикой алгоритма?
щас именно так и делается, но пробовал разные варианты - т.к. обекты принадлежат разным классам, то, по логике программы, изменение скажем объекта верхнего уровня влечет за собой изменение нескольких, принадлежащих ему, объектов, так вот пробовал делать коммит после изменения объектов верхнего уровня, потом после измения объекта нижнего уровня, уровней этих, если быть более конкретным, три... так же пробовал делать коммит после всех изменений...

Добавлено: 21 июн 2006, 13:26
Merlin
CCB писал(а): сцылку почитал.
Хреново почитал.
CCB писал(а): not IBQueryMain.Eof do
begin
IBQueryUPD.SQL.Clear;
IBQueryUPD.SQL.Add('update Objects set Info=:ParamInfo where ID='+IBQueryMain.FieldByName('IDObj').AsString);
Stream:=TStringStream.Create(StrStream);
Stream.WriteComponent(Info);
Stream.Seek(0, soFromBeginning);
IBQueryUPD.ParamByName('ParamInfo').LoadFromStream(Stream, ftBlob);
IBQueryUPD.ExecSQL;
Stream.Free;
IBQueryMain.Next
end;
Во-первых, смысл? (C) Штирлиц. Собирать один и тот же запрос с параметром в цикле и как результат на каждом шагу его препарить. Вместо того, чтоб собрать один раз перед циклом с двумя параметрами и в цикле только вызывать? Но это так, лирика. Основная твоя проблема - на клиенте кончается память, которую сжирает IBQueryMain, буферизуя всё прочитанное. Поставь ей UniDirectional=True и будет тебе щастье. И это ведь всё разжевано там где ты "почитал".

Добавлено: 21 июн 2006, 14:04
CCB
Merlin писал(а):Во-первых, смысл? (C) Штирлиц. Собирать один и тот же запрос с параметром в цикле и как результат на каждом шагу его препарить. Вместо того, чтоб собрать один раз перед циклом с двумя параметрами и в цикле только вызывать? Но это так, лирика.
с этим смогласен...
Основная твоя проблема - на клиенте кончается память, которую сжирает IBQueryMain, буферизуя всё прочитанное. Поставь ей UniDirectional=True и будет тебе щастье. И это ведь всё разжевано там где ты "почитал".
а ты это щастье пробовал? попробуй... нихрена это не помогает... скорость падает примерно с тем же ускорением...

Добавлено: 21 июн 2006, 15:46
CCB
завтра расскажу, как я пытался исправить ситуацию...

Добавлено: 22 июн 2006, 07:54
CCB
кароче:
я убрал цикл while - нужные данные загружаю в динамический массив и хожу по массиву; TIBQuery заменил на TIBSQL, запрос строю именно так, как написал Merlin; пробовал TIBSQL создавать динамически в каждой итерации... ничего не помогает - скорость работы постепенно падает... так что пока остаецца грешить на сервер, чего-то он там делает мне неизвестное...

Добавлено: 22 июн 2006, 08:39
CyberMax
Какой размер базы? И дай-ка статистику по ней =)

Добавлено: 22 июн 2006, 08:53
CCB
размер около 900 мб

только што сделал бэкап\рестори

Database header page information:
Flags 0
Checksum 12345
Generation 1036
Page size 4096
ODS version 10.1
Oldest transaction 1026
Oldest active 1027
Oldest snapshot 1027
Next transaction 1030
Bumped transaction 1
Sequence number 0
Next attachment ID 0
Implementation ID 16
Shadow count 0
Page buffers 0
Next header page 0
Database dialect 3
Creation date Jun 22, 2006 8:35:22
Attributes force write

Variable header data:
Sweep interval: 20000
*END*

Добавлено: 22 июн 2006, 09:06
CyberMax
Настораживает Page buffers 0, Attributes force write и Page size 4096.
1. Как-нибудь попробуй сделать page size = 8192. Должно повлиять на производительность.
2. Сними Force Writes.
3. Поставь Page Buffers = 1024.
Скажи результат.
Какая ось и размер оперативки на компе?

Добавлено: 22 июн 2006, 09:12
CCB
1. Вот только што была 16384, при последнем рестори сделал 4096
2. Только вчера вечером установил в ON
3. Это попробую

WinXP SP2, 512

Добавлено: 22 июн 2006, 09:22
CyberMax
Кстати, не проверял, в каком месте программы тормозит? Точно после ExecSQL? Создай экземпляр TStringList, закидывай в него текущее время в разных точках кода (например, в начале цикла, перед и после ExecSQL), а потом сохрани все в файл. Изучи цифры.