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

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

После апдейт SQL запросов - тормозит скроллинг [Firebird]


Страницы:   1 2

Anthony ©   (2010-12-30 00:38:00) 

Кто опытен, помогите пожалуйста разобраться в таком обстоятельстве:

DBGridEh прицепленный к DataSet (от FIBPlus), отображает примерно 92тыс.записей
В таблице 3 поля: ID (целое), FLAG (char[1]) и NUM (целое)
И вот - нужно сделать апдейт числового поля группы записей,
размещённых между теми записями, у которых FLAG - не пуст.
У каждой очередной группе записей, размещённых между записями с непустым флагом: нужно изменить поле NUM (просто в это поле записывается следующий по порядку номер - и всё).

Так вот интересный эффект,
Если эту задачу решать, просматривая в цикле сам DataSet:

iCounter := 1;
iPrevRec := 1;
DS.First;
while not DS.Eof do begin
 if DS.FieldByName('FLAG').AsString <> '' then Inc(iCounter);
   DS.Edit;
   DS.FieldByName('NUM').AsInteger := iCounter;
   DS.Post;  
   DS.Next;
end;
DS.FullRefresh;

- то после этой операции - в прицепленном к Dataset гриде записи нормально скроллируются, как и до апдейта,
но - пройти "пешком" 92тыс. записей - долго...

Тогда я переписал код, используя SQL запросы:

iCounter := 1;
iPrevRec := 1;
QueryFetch.SQL.Text := 'SELECT ID FROM TAB WHERE FLAG <> '''''
QueryFetch.ExecQuery; // - мы сразу на 1 записи...
QueryFetch.Next;
while not QueryFetch.Eof do begin  // скачем по записям с флагом
 QueryUpdate.SQL.Text := 'UPDATE TAB SET NUM = ' + IntToStr(iCounter) + 'WHERE ID >=' + IntToStr(iPrevRec) + ' AND ID < ' + QueryFetch.Fields[0].AsString;
 QueryUpdateVerses.ExecQuery; // апдейт поля NUM у группы записей
 Inc(iCounter);  // увеличили счётчик
 iPrevRec := QueryFetch.Fields[0].AsInteger; // запомнили ID для использ. в след. итерации
 QueryFetch.Next;
end;
// после цикла - апдейт последней группы, но это не важно...

Так вот - теперь собственно сам казус - почему-то после этого варианта кода - грид, отображающий эту таблицу стал просто жутко тормозить!!
Я ради интереса провёл один эксперимент: попробовал делать апдейт с помощью SQL запросов не всех записей таблицы, а только части, оказалось, чем меньше записей обновлялось,
тем меньше потом тормоза!..

Может кто-нибудь подсказать - что это за "глюк" такой?


Виталий Панасенко   (2010-12-30 17:43:00) [21]


> adigozelov ©

MS SQL тут не причем


Виталий Панасенко   (2010-12-30 17:37:00) [22]

куча мелких запросов - много медленнее, чем ОДИН "большой запрос


adigozelov   (2010-12-30 17:13:00) [23]

ID  FLAG  NUM
1     >      0
2             0
3             0
4     >      0
5     >      0
6             0
7     >      0
А после апдейта поля NUM должно быть так:
ID  FLAG  NUM
1     >      1
2             1
3             1
4     >      2
5     >      3
6             3
7     >      4


Napisi eta procedur adocommand.commantext i palucish resultat

declare
@i int

 set @i=0

update tab
set   @i=Num=@i+1
where flag<>''

set @i=0

update tab
set @i=Num=@i+1
where flag=''


Sergey13   (2010-12-30 16:09:00) [24]

Я может чего не понял после шампанского и фуршета, но разве нельзя одним запросом все сделать?
UPDATE TAB SET NUM = NUM+1 WHERE FLAG<>''

ЗЫ: 92 тыс записей со стуктурой  ID (целое), FLAG (char[1]) и NUM (целое) в гриде - это жесть! 8-)


Anatoly Podgoretsky   (2010-12-30 10:58:00) [25]

> Anthony  (30.12.2010 02:21:07)  [7]

Это не шутка, а как не смешно частая ошибка.


Anatoly Podgoretsky   (2010-12-30 10:58:00) [26]

> Anthony  (30.12.2010 02:16:06)  [6]

Где там у тебя никого не интересует, здесь оперируем только приведеным
кодом.


Max Zyuzin   (2010-12-30 10:50:00) [27]

>Anthony ©   (30.12.10 02:35) [11]
Вы кстати уверены что пользователь в состоянии просмотреть все 92 тысячи записей?
И как ваша программа должна действовать в случае, если НД будет банально отсортирован?
Я так понял, что пользователь, просматривая записи "отмечает" "пограничные" записи а не сразу всю группу?


sniknik   (2010-12-30 10:40:00) [28]

> а во-втором - начинаются жуткие тормоза!..
while not QueryFetch.Eof do begin  
 QueryUpdate.SQL.Text := 'UPDATE TAB SET NUM = ' + IntToStr(iCounter) + 'WHERE ID >=' + IntToStr(iPrevRec) + ' AND ID < ' + QueryFetch.Fields[0].AsString;
 //про параметры тебе уже говорили. опять не "обратил внимания"?

QueryUpdate Verses.ExecQuery; //??? пере запрос чего?  говорил вроде что туже самую таблицу правишь... а тут + Verses, т.е. запрос меняется у одного выполняется другой?

Inc(iCounter);  // увеличили счётчик
iPrevRec := QueryFetch.Fields[0].AsInteger; // запомнили ID для использ. в след. итерации
QueryFetch.Next;
end

это карма, тут запросы тут совершенно лишние, сначала делать изменение запросом в базе после пере запрос... вариант с кешированными изменениями лучше... сначала все исправили в рекордсете на клиенте, после "сбросили" это в базу, и никаких лишних "телодвижений".


Anthony   (2010-12-30 02:35:00) [29]


> А я понял, автор бегает по одному набору, а смотрит в гриде
> в другом.

Нет-нет. Если Вы не пошутили, конечно же речь идёт об одном и том же DataSet.
Я просто никак не пойму, почему в первом случае кода - после окончания апдейта - всё в порядке, а во-втором - начинаются жуткие тормоза!..


Anthony   (2010-12-30 02:32:00) [30]


> Что за задача, что надо перелопачивать

Да простая вобщем то задача. Я просто не упомянул, чтобы не усложнять, что в каждой записи ещё присутствует текстовое поле, довольно объёмное, и вся ценность - именно в нём. Все текстовые поля имеют одну характерную особенность, по которой их нужно разбить на соотв.группы. Пользователь, просматривая всю таблицу (в гриде) - помечает записи, являющиеся началами этих групп, а после окончания пометки - записи в группах должны пронумероваться... Вот и всё. Нормальная задача.

> С запросом, может и такое можно сделать, если подумать.

Так я его и привёл уже в примере! Один запрос - скачет по записям с ненулевым флагом - а другой - апдейтит записи между ними. Разве Вы сможете предложить что-то проще?..


Inovet   (2010-12-30 02:29:00) [31]

> [7] Anthony ©   (30.12.10 02:21)
> > А я понял, автор бегает по одному набору, а смотрит в гриде в другом.
>
> Это шутка?..

Нет. Я так понял из

> [0] Anthony ©   (30.12.10 00:38)
> Если эту задачу решать, просматривая в цикле сам DataSet:
> DS.First;
...
> Тогда я переписал код, используя SQL запросы:
>
> QueryFetch.SQL.Text := 'SELECT ID FROM TAB WHERE FLAG <>
> QueryUpdate.SQL.Text := 'UPDATE TAB SET NUM = ' + IntToStr(iCounter)


Inovet   (2010-12-30 02:23:00) [32]

> [4] Anthony ©   (30.12.10 02:10)
> > когда один раз/иногда по каким-то причинам надо такое, но
> > постоянно.
>
> - а вот эту фразу я вообще не понял, поясните, что вы имели ввиду.

Что за задача, что надо перелопачивать и перенумеровывать постоянно, судя по теме с прогрессбаро. Т.е. не косяк ли в архитектуре.

С запросом, может и такое можно сделать, если подумать.


Anthony   (2010-12-30 02:21:00) [33]


> А я понял, автор бегает по одному набору, а смотрит в гриде
> в другом.

Это шутка?..


Anthony   (2010-12-30 02:16:00) [34]


> DataSet.DisableControls;

Вы имеете ввиду, что я в коде забыл запретить перерисовку Control-ов,
связанных с DataSet?..

У меня используется DisableControls, просто я упростил пример, и не внёс туда
эти строки, потому что и так понятно, что лучше не скроллировать DataSet без такого приёма...


Inovet   (2010-12-30 02:14:00) [35]

> [3] Ega23 ©   (30.12.10 02:07)
> Это не глюк, это дурная голова.
> DataSet.DisableControls;

А я понял, автор бегает по одному набору, а смотрит в гриде в другом.


Anthony   (2010-12-30 02:10:00) [36]

Спасибо за участие, да - это в продолжение вопроса о прогрессбаре,
с ним разобрался, и вот - двигаюсь дальше..

> Один запрос на обновление с этим условием + генератор

Вы меня не поняли. Записи в таблице выглядят примерно так:
ID  FLAG  NUM
1     >      0
2             0
3             0
4     >      0
5     >      0
6             0
7     >      0
А после апдейта поля NUM должно быть так:
ID  FLAG  NUM
1     >      1
2             1
3             1
4     >      2
5     >      3
6             3
7     >      4
Поэтому то что Вы предлагаете с генератором - сюда вроде не подходит.

> когда один раз/иногда по каким-то причинам надо такое, но
> постоянно.

- а вот эту фразу я вообще не понял, поясните, что вы имели ввиду.

...Мне в принципе интересно, почему начало тормозить перемещение по Dataset, если в SQL запросах на апдейт я вроде не накосячил.

Извините, если мои вопросы "не на уровне", я новичёк...


Ega23   (2010-12-30 02:07:00) [37]


> Может кто-нибудь подсказать - что это за "глюк" такой?

Это не глюк, это дурная голова.
DataSet.DisableControls;
try
 DataSet.Firest;
 while not DataSet.Eof do
   try
      ......
   finally
     DataSet.Next;
   end;
finally
 DataSet.EnableControls;
end;


Inovet   (2010-12-30 01:25:00) [38]

Это в продолжение твоей темы о прогрессиндикаторе?

Выбрать с непустым флагом и пронумеровать? - Один запрос на обновление с этим условием + генератор, и желательно индекс по полю с флагом, и никаких циклов не надо. Но что-то это странное, я ещё согласен, когда один раз/иногда по каким-то причинам надо такое, но постоянно.


Anthony   (2010-12-30 00:41:00) [39]


> QueryUpdateVerses.ExecQuery; // апдейт поля NUM у группы
> записей

здесь я ошибся, должно быть:

QueryUpdate.ExecQuery; // апдейт поля NUM у группы записей


Страницы:   1 2

Наверх

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