Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.12.02;
Скачать: CL | DM;

Вниз

Замедление DataSet.next   Найти похожие ветки 

 
wsv ©   (2007-07-13 10:28) [0]

Здравствуйте.
Столкнулся с проблемой при больших DataSet-ах с доступом к MySql с помщью компонентов Zeos.
В DataSet (точнее ZQuery, который наследник DataSet), выбирается большое количество данных, 50 тысяч строк и более.
При считывании результата запроса циклом while...do begin ... Dataset.next... происходит замеделение считывания, которое визуально отловлено простым прогрессором.

КАК ИЗБАВИТЬСЯ?

Может можно как-то другими способами скопировать результат в массив?

В частном случае копируются данные типа duoble в масив соотв. типа... В общем случае это вариантные данные.


 
Ega23 ©   (2007-07-13 10:34) [1]

зачем тебе 50 000 записей на клиенте?????


 
Johnmen ©   (2007-07-13 10:34) [2]


> выбирается большое количество данных, 50 тысяч строк и более.

Зачем иметь сразу столько данных на клиенте?


 
sniknik ©   (2007-07-13 10:49) [3]

> while...do begin ... Dataset.next... происходит замеделение считывания, которое визуально отловлено простым прогрессором.
имхо, все дело в волшебных пузырьках... т.е. точках, next не причем.
хотя, не зная особенностей Zeos, могу и ошибаться.

> КАК ИЗБАВИТЬСЯ?
исправить ошибку. сначала, а после задуматься "а нафига тебе столько данных на клиенте?" (если не исправить то притормаживание просто "смажется" малым количеством... останется но не будет так заметно)


 
Desdechado ©   (2007-07-13 10:59) [4]

Данные читаются и накапливаются. Вот и замедление. Используй однонаправленный датасет, если уж припекло читать столько много.


 
wsv ©   (2007-07-13 11:01) [5]


> Зачем иметь сразу столько данных на клиенте?


> зачем тебе 50 000 записей на клиенте?????


Это навигационные данные, которые поступают каждые 15-30 секунд.
Нужен отчет за период.
Границы периода неизвестны. Данные нужно обработать сначала.


 
Desdechado ©   (2007-07-13 11:03) [6]

> Нужен отчет за период. Границы периода неизвестны.
"Принеси то, не знаю что?"

> Это навигационные данные, которые поступают каждые 15-30 секунд.
А причем тут отчет?


 
Сергей М. ©   (2007-07-13 11:04) [7]


> Данные нужно обработать сначала


Почему бы не обработать их на стороне сервера ?


 
wsv ©   (2007-07-13 11:07) [8]


> "Принеси то, не знаю что?"

Период конечно известен. Это наше время. В общем случае - год-два-три...

> А причем тут отчет?

Отчет при том, что нужно сначала отловить обработкой заправки-сливы-остановки-стоянки, что уже сделано. На данных до 30 тыс. строк обработка (считывание+собственно поиск) занимает меньше секунды. Дальше, только передача данных из запроса в массив занимает уже десятки секунд. Например на 100 тыс записей - это 18 секунд передачи в массив.

Как выйти из положения?


 
wsv ©   (2007-07-13 11:08) [9]


> Почему бы не обработать их на стороне сервера ?


Ога... Вейвлет преобразование и фильтрация силами Мускула? :-D


 
sniknik ©   (2007-07-13 11:11) [10]

> Как выйти из положения?
общеизвестный выход из положения - родить. ;о)
в твоем случае разродиться исходной информацией... (сам, я так понимаю, ошибку найти не в состоянии)


 
Сергей М. ©   (2007-07-13 11:12) [11]


> Вейвлет преобразование и фильтрация силами Мускула?


Почему бы и нет ?

Я не в курсе, но разве Мускул не предоставляет механизма использования внешних пользовательских функций, подобного механизму UDF в IB ?

А если и не предоставляет, то все равно непонятно, нафига каждый раз тащить  все даннные, а не только вновь поступившие..


 
Плохиш ©   (2007-07-13 11:16) [12]


> Дальше, только передача данных из запроса в массив занимает
> уже десятки секунд. Например на 100 тыс записей - это 18
> секунд передачи в массив.

Ну а что хотели, дай догадаюсь, постоянные перераспределения размеров массива. Производительность современных вычислительных систем в любом случае конечна, а вы тут такие объёмы данных по системе таскаете...


 
wsv ©   (2007-07-13 11:17) [13]

Исходная информация. D7-Zeos-MySql.
Навиг. данные: очень частая пилА - топливный датчик, показания с которого нифига не интегрированы.
1. Получаем данные датчика за период.
2. Загоняем в массив.
3. Преобразуем вейвлетом.
4. Линеаризуем.
5. Приводим к тарировке датчика
6. Ищем сливы-заправки
7. Выводим график расхода по тарировке и вероятные сливы-заправки.

Проблема в п.2
Все остальное очень быстро робит.


 
wsv ©   (2007-07-13 11:18) [14]


> нафига каждый раз тащить  все даннные, а не только вновь
> поступившие..

не все. за период, указанный юзером.


 
sniknik ©   (2007-07-13 11:21) [15]

> Исходная информация. D7-Zeos-MySql.
это не то ... интересуют "волшебные пузырьки" в коде их [0], а именно как делаешь то что по твоему тормозит.


 
wsv ©   (2007-07-13 11:24) [16]


> а именно как делаешь то что по твоему тормозит.


i:=0;
dm.navdata.First;
while i<RowCount do
begin
fuelout[i]:=dm.navdata.fieldbyname("....").Value;
dm.navdata.Next;
inc(i);
pb.StepBy(1);
end;


 
wsv ©   (2007-07-13 11:25) [17]

А можно как-то по другому?
Вот и спрашиваю, чо... :-D


 
sniknik ©   (2007-07-13 11:26) [18]

меня например очень интересует используешь ли ты отключение контролов, как идет доступ к полям, и не используешь ли ты чего нибудь что вычисляется на основе рекордсета (либо может вычисляться, смотря от того как сделаны Zeos-ы, (тут, от незнания, могу только предполагать, что это))


 
wsv ©   (2007-07-13 11:27) [19]

Контролов связанных с датасетами нет вообще.
Все в массивах.


 
Сергей М. ©   (2007-07-13 11:27) [20]


> не все. за период, указанный юзером


Откуда тогда взялось значение RowCount ?


 
wsv ©   (2007-07-13 11:30) [21]


> Откуда тогда взялось значение RowCount ?

Блин... :-D
dm.navdata.close;
dm.navdata.sql.text:="Select ... from ... where...";
dm.navdata.open;

rowcount:=dm.navdata.rowcount;

:-D


 
sniknik ©   (2007-07-13 11:30) [22]

ага,  ну вот [16], более менее
отключения контролов нет, RowCount поменяй на not eof, fieldbyname вынеси за пределы цикла, и StepBy делай не на каждую итерацию, а на видимую часть (видиш к примеру 100 квадратиков в прогрессе, рассчитай так чтобы было 100 StepBy)
изменилось чтонибудь?


 
wsv ©   (2007-07-13 11:35) [23]


> fieldbyname вынеси за пределы цикла

Это как? :-)
можно сделать fieldvalues или fields.field[0]... но как "вынести за цикл"?


> RowCount поменяй на not eof

Делал. Тоже самое.


 
Сергей М. ©   (2007-07-13 11:37) [24]


> rowcount:=dm.navdata.rowcount


Я не в курсе, что там творится в потрохах Zeos, но глубоко сомневаюсь, что RowCount вернет истинное число записей в выборке.


 
wsv ©   (2007-07-13 11:38) [25]


> отключения контролов нет,


> Контролов связанных с датасетами нет вообще.


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


 
Плохиш ©   (2007-07-13 11:39) [26]


> wsv ©   (13.07.07 11:35) [23]
>
> > fieldbyname вынеси за пределы цикла
>
> Это как? :-)
> можно сделать fieldvalues или fields.field[0]... но как
> "вынести за цикл"?

var
     tmpField: T<xxx>Field;
...
 tmpField := dm.navdata.fieldbyname("....");
 while not dm.navdata.eof do
....


 
wsv ©   (2007-07-13 11:39) [27]


> RowCount вернет истинное число записей в выборке.


Возвращает правильно. Сомневаться не приходится, ибо инвалид поинтер оперэйшен... :-)


 
Desdechado ©   (2007-07-13 11:40) [28]

>  но как "вынести за цикл"?
FieldByName возвращает указатель на поле. Сохрани его до цикла. Это сильно влияет на скорость. Потом просто в цикле будет указатель.As...

Кроме того мне не понятно, зачем еще раз данные читать в массив, если они уже есть в датасете (тот же массив).


 
Плохиш ©   (2007-07-13 11:41) [29]

и окружить всё в

dm.navdata.DisableControls;
try
  // Твой код
finally
 dm.navdata.EnableControls;
end;


PS. Тормознутые эти zeos, я бы перешёл на адо :-)


 
sniknik ©   (2007-07-13 11:42) [30]

> Это как? :-)
> можно сделать fieldvalues или fields.field[0]... но как "вынести за цикл"?
var
 Fld: TField;
begin
 Fld:= dm.navdata.fieldbyname("....");
 while i<RowCount do
   Fld.Value;

у многих получение индекса поля по имени расчетное... т.е. тратит время.
> RowCount поменяй на not eof
> Делал. Тоже самое.
это просто более правильно, но когда писал не было этого
> rowcount:=dm.navdata.rowcount;
тут тебе можно просто for i:= 0 to ... поставить, этот цикл быстрее изза другого рода проверки выхода (а она каждый раз не нужна т.к. судя по всему рекордсет локальный)

а StepBy? возьми просто убери прогресс и засеки общее время, и контнролы отключи обязательно даже если их нет (проверка может быть на разных уровнях вложенности, отключенные тобой это самый первый уровень, быстрее всего)


 
wsv ©   (2007-07-13 11:43) [31]


> Кроме того мне не понятно, зачем еще раз данные читать в
> массив, если они уже есть в датасете (тот же массив).


Представь если еще бегать при линеаризации, тарировке и поиске заправок и сливов по датасету... :-D
Именно поэтому и массивы.


 
sniknik ©   (2007-07-13 11:44) [32]

> PS. Тормознутые эти zeos, я бы перешёл на адо :-)
точно знаеш? работал?


 
Сергей М. ©   (2007-07-13 11:45) [33]


> Возвращает правильно


С чего ты так уверен ?

Last после открытия НД ты явно не делаешь, делает ли это неявно Zeos ты тоже не знаешь, предоставляет ли эту "фичу" сам Мускул - тебе тоже неведомо..


> Сомневаться не приходится, ибо инвалид поинтер оперэйшен


Чевой-то ?)


 
sniknik ©   (2007-07-13 11:46) [34]

> Представь если еще бегать при линеаризации, тарировке и поиске заправок и сливов по датасету... :-D
а если не бегать? если составить запрос на обьеденение так чтобы все рядом было?


 
wsv ©   (2007-07-13 11:47) [35]


> С чего ты так уверен ?


Потому што при заполнении массива нет ошибок.


 
Плохиш ©   (2007-07-13 11:47) [36]


> sniknik ©   (13.07.07 11:44) [32]
> > PS. Тормознутые эти zeos, я бы перешёл на адо :-)
> точно знаеш? работал?

Хотел перейти, начитавшись рекламы :-) Переделал проект с адо на зеос и время обработки увеличилось в 4 раза, покрутил ещё там чего-то немного и забросил. Теперь пользуюсь стандартными проверенными технологиями :-)


 
wsv ©   (2007-07-13 11:50) [37]


> а если не бегать? если составить запрос на обьеденение так
> чтобы все рядом было?


Данные тарировки физически лежат в другой базе. На этапе разработки они просто загнаны в мемо (их около 10 строк всего). Они тоже читаются в массивчик и входные данные тарируются клиентом.

А с чем объединить еще, я не знаю. :-D


 
sniknik ©   (2007-07-13 11:51) [38]

> Потому што при заполнении массива нет ошибок.
а с чего им быть если rowcount вернул частичное значение количества на еще не полностью скачанном рекордсете, массив ты сформировал по этому размеру и перенос сделал по нему же, не обращая внимания что данных уже больше.
(я вообщето подумал что у тебя клиентский курсор, наподобие в ADO, и данные приходят все без докачек...)


 
Сергей М. ©   (2007-07-13 11:52) [39]


> Потому што при заполнении массива нет ошибок


А с какого перепугу они должны возникнуть ?

Открыв НД ты тут же прочитал св-во RowCount, пребывая в святой уверенности в том что получил действительное число записей в этом НД, после чего выделил соответствующую память под массив. Где здесь "криминал" ? Нету его) ... Засада же может поджидать тебя с совершенно иной сторона - число записей в НД в реальности больше, чем то что ты получил вот таким макаром.


 
Anatoly Podgoretsky ©   (2007-07-13 11:55) [40]

Это типичный однонаправленный набор данных!
И определение массива не приведено.


 
wsv ©   (2007-07-13 11:59) [41]

По количеству записей вопросов нет. :-D

Есть вопрос по скорости чтения результатов запроса... Ну или копированию этих результатов в массив...

ЗЫ. Данные выбираются ВСЕ. Это точно. Про баги с RowCount я знаю и проверял на начальном этапе....
ЗЗЫ. tfield выключил. DisableControls добавил. Немного ускорилось. Добавил к периоду неделю с приемлемой скоростью. За это СПАСИБО.


 
Сергей М. ©   (2007-07-13 12:00) [42]


> Это типичный однонаправленный набор данных


Это он использует его как однонаправленный.

А сам НД вполне может у него быть и двунаправленным, о чем он вероятно не подозревает и не задумывается.

Оттого и "тормоза" ощутимые (если не сказать основные) добавляются, плюс ко всем тем очевидным "кривостям" и неоптимальностям в коде, что он привел)


 
wsv ©   (2007-07-13 12:00) [43]


> Это типичный однонаправленный набор данных!
> И определение массива не приведено.


fuelin:array of double;

setlength (fuelin, rowcount);

while... do begin...end


 
wsv ©   (2007-07-13 12:03) [44]


> плюс ко всем тем очевидным "кривостям" и неоптимальностям
> в коде, что он привел)


Попробуйте еще как-то оптимизировать цикл while do begin end...
:-D


 
sniknik ©   (2007-07-13 12:05) [45]

> fuelin:array of double;
> setlength (fuelin, rowcount);
> while... do begin...end
ошибка. с учетом уже приведенного, у тебя теряется 2 записи. если конечно принять что курсор локальный и данные выбираются все сразу.


 
sniknik ©   (2007-07-13 12:06) [46]

> Попробуйте еще как-то оптимизировать цикл while do begin end...
я приводил то что оптимизирует этот цикл... только в данном случае конечно, но...


 
wsv ©   (2007-07-13 12:06) [47]


> ошибка. с учетом уже приведенного, у тебя теряется 2 записи.


> ЗЫ. Данные выбираются ВСЕ. Это точно. Про баги с RowCount
> я знаю и проверял на начальном этапе....
>


 
wsv ©   (2007-07-13 12:07) [48]


> я приводил то что оптимизирует этот цикл... только в данном
> случае конечно, но...
>

Эта реплика была не вам.

Вам:

> ЗЗЫ. tfield выключил. DisableControls добавил. Немного ускорилось.
>  Добавил к периоду неделю с приемлемой скоростью. За это
> СПАСИБО.


 
Сергей М. ©   (2007-07-13 12:08) [49]


> wsv ©   (13.07.07 11:59) [41]


Если известно максимальное кол-во записей, которое может оказаться в НД в рез-те выборки по известным критериям, следующие рекомендации наверняка устранят основные "тормоза":

1. Открыть однонаправленный НД.
2. Расчитать минимально необходимое кол-во памяти, необходимое для организации массива, куда будут считываться данные из НД. Выделить память.
3. В цикле while not eof do..next пройтись по НД от начала до конца, считывая данные из НД наиболее оптимальным способом и тут же подсчитывая число записей.
4. Имея фактическое число записей расчитать фактически используемую в массиве память и реаллокировать память под массив, уменьшив ее до фактического размера.


 
sniknik ©   (2007-07-13 12:12) [50]

wsv ©   (13.07.07 12:06) [47]
это к чему? потерять всего 2 записи типа для статистики неважно?
потому как если бы данные выбирались не все то потери шли бы на 0 - 98% от общего количества, в зависимости от исходного обьема.

> Эта реплика была не вам.
какая разница кому? теперь то ты говоришь
> Попробуйте еще как-то оптимизировать цикл while do begin end...
а пример подобной оптимизации уже был.


 
Anatoly Podgoretsky ©   (2007-07-13 12:30) [51]

> wsv  (13.07.2007 12:00:43)  [43]

С массивом порядок, дальше по выше приведенным рекомендация.
Однонаправленный набор, вывести инварианты за цикл, цикл сделать For и т.д.
На каждом шаге проводить измерение, что бы понять помог шаг или нет.


 
Anatoly Podgoretsky ©   (2007-07-13 12:31) [52]

> Сергей М.  (13.07.2007 12:08:49)  [49]

Пункт 4 у него выполнен до цикла.


 
Сергей М. ©   (2007-07-13 12:40) [53]


> Anatoly Podgoretsky ©   (13.07.07 12:31) [52]
>
> > Сергей М.  (13.07.2007 12:08:49)  [49]
>
> Пункт 4 у него выполнен до цикла.
>


Я это понимаю.

Но прогрессирующие "тормоза" могут быть связаны только с одним - с перераспределением BMM-памяти при каждой итерации, что ведет к ее интенсивной дефрагментации и, как следствие, прогрессирующим замедлением работы BMM.


 
Anatoly Podgoretsky ©   (2007-07-13 12:53) [54]

> Сергей М.  (13.07.2007 12:40:53)  [53]

прогрессирующие "тормоза" вызываются двунаправленным курсором.


 
Сергей М. ©   (2007-07-13 12:56) [55]


> Anatoly Podgoretsky ©   (13.07.07 12:53) [54]


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


 
Anatoly Podgoretsky ©   (2007-07-13 13:27) [56]

> Сергей М.  (13.07.2007 12:56:55)  [55]

Все может быть, на Zeos часто ругаются, в том числе и за скорость


 
Сергей М. ©   (2007-07-13 13:40) [57]

А таки любопытно, есть ли в Мускуле IBUDF-подобный механизм..

Гуглить, честно скажу, лень)

Просветите вкратце, кто в курсе ?


 
Anatoly Podgoretsky ©   (2007-07-13 13:42) [58]

> Сергей М.  (13.07.2007 13:40:57)  [57]

MySql это несколько тысяц опубликованых версий


 
Johnmen ©   (2007-07-13 14:29) [59]


> Сергей М. ©   (13.07.07 13:40) [57]

http://www.mysql.ru/docs/man/CREATE_FUNCTION.html
дельфисты отдыхают...:)


 
Сергей М. ©   (2007-07-13 14:39) [60]


> Johnmen ©   (13.07.07 14:29) [59]


> дельфисты отдыхают


Ну глянул я на это чудо)

Да, вижу:

Чтобы механизм UDF работал, функции должны быть написаны на C или C++

Копнул чуть глубже.
Вижу что это заявление слишком громкое)


 
Johnmen ©   (2007-07-13 14:44) [61]


> Сергей М. ©   (13.07.07 14:39) [60]

Возможно. Я не копал. Мне не интересно....


 
Сергей М. ©   (2007-07-13 14:47) [62]


> Мне не интересно


Мне тоже.
Ибо любопытство удовлетворил и сделал вывод - сабж возможен, и он по механизму аналогичен IB


 
wsv ©   (2007-07-15 06:47) [63]

ВСЕМ СПАСИБО ЗА ПОНИМАНИЕ И ПОМОЩЬ, ЧОУЖ...
Разбил выбранный период на интервалы. Испытания показали, что данные за неделю (а это, по максимуму, 24 часа х 120 записей в час х 7 дней = 20800 записей) выбираются приемлемо быстро. Поэтому целый период делим на 7 дней, выбираем понедельно, потом остаток от нецелой недели. При каждом переходе в новый интервал "обнуляю" и переизмеряю массивы. Получилась своего рода "подкачка" при выборке данных.
При этом увидел плюсы:
1. При обработке добавил возможность остановить обработку, если получнные в рез-те обработки данные УЖЕ удовлетворяют, то дальше, по application.messagebox yes/no, делаем вывод о необходимости продолжения обработки.
2. Тот злополучный прогрессор теперь кажет процесс так как он есть, что говорит юзеру о том, что программа не зависла, а продолжает работать.


 
atruhin ©   (2007-07-15 09:30) [64]

> При каждом переходе в новый интервал "обнуляю" и переизмеряю
> массивы.

1. Зачем массив обнулять, если новые данные его просто перепишут? Для верности?
2. Если тебе известно максимально возможное кол-во данных за неделю, зачем изменять размер?
Один раз выделяешь массив максимального размера и все, дальше используешь Arr[0] to RowCount....

> Тот злополучный прогрессор теперь кажет процесс так как он есть

Тебе не предлагили отказаться от прогрессбара. Предлагали сделать размер прогрессбора например RowCount div 100.
Далее if CurrentRow div 100 = 0 then pb.StepBy(1);
Это все твои тормоза.
Ну и самое важное, тебе все говорят про однонаправленный курсор, зачем игнорируешь?


 
Artyom789123 ©   (2007-07-25 02:23) [65]

to wsv ©
Проблема та же...
но есть отличия - всё гораздо хуже, поэтому хотелось бы больше подробностей.
>>что данные за неделю (а это, по максимуму, 24 часа х 120 записей в час х >>7 дней = 20800 записей) выбираются приемлемо быстро.
У неприемлимо медленно:

13000 - 37 секунд, 26200 - 153, 39600 - 362

Времена варьируюься в зависимости от мощности компьютера и mysql-сервера (localhost -задержка в доли секунды, DSL - десятки секунд).
Подробностями в данном случае я подразумеваю тип процессора, объём RAM, версию SQL и Zeos, размер строки таблицы и т.п.

to atruhin
>>Это все твои тормоза.

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



Страницы: 1 2 вся ветка

Текущий архив: 2007.12.02;
Скачать: CL | DM;

Наверх




Память: 0.66 MB
Время: 0.024 c
15-1194000098
de.
2007-11-02 13:41
2007.12.02
Cursor


11-1179477505
=BuckLr=
2007-05-18 12:38
2007.12.02
Вопрос по consoleOut


2-1194430383
allucard
2007-11-07 13:13
2007.12.02
Помогите по компоненту TComPort


4-1179507014
Bacardi
2007-05-18 20:50
2007.12.02
Очередь печати


2-1194632557
Alral
2007-11-09 21:22
2007.12.02
Turbo Delphi 2006, Indy components, TtcpServer