Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум на Исходниках.RU > Visual Basic: Общие вопросы > Ускорение отрисовки графика |
Автор: Penumbra 22.09.16, 20:14 |
[attach=#0][/attach]Доброго времени суток Я строю график по данным из БД. в БД сохранены 222200 записей ( напряжение с шагом 2 секунды) если я строю график за промежуток в пару часов график прорисовывается довольно быстро, но если я запрашиваю данные за период в 5-6 суток то график строится 2-3 минуты! :!: может можно как-то увеличить скорость построения графика? файл Скрытый текст |
Автор: Akina 22.09.16, 20:42 |
Когда ты строишь график за длительный промежуток, то в одной пиксельной колонке экрана у тебя "совмещается" несколько значений, а отрисовывается , видимо, по самому большому из них. Посему предлагаю заранее спросить контрол, сколько же нужно будет реально рисовать колонок в пикселах, и в запросе соответствующим образом сгруппировать исходные данные для отрисовки, типа <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> select ..., max(value) as value from ... where ... group by fix(@pixel_cols_count * (dt - @start_dt) / (@end_dt - @start_dt)) Т.е. даже на самом широком мониторе при самом диком разрешении в полноэкранном режиме тебе придётся отрисовывать только несколько (вряд ли более 4) тысяч значений. |
Автор: VisualProg 23.09.16, 08:08 |
Цитата график строится 2-3 минуты Для суточных выборок, можно отбросить часть данных, а не перестраивать запрос к ним. Например, делаете выборку 60 000 записей (DataCount). Отрисовать их все - невозможно, значит, берём ширину полотна Width (они определяют число допустимых точек в графике, пускай в тестовом примере, это будет полотно шириной в 1024 пикселя), и получаем шаг, с которым будим пропускать данные: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> int step = DataCount/Width; // 60 000 / 1 024 = 58 Это число (58) показывает что из 60 000 записей визуально можно воспринять только каждую пятьдесят восьмую точку (то есть 57 точек можно отбросить). Поэтому, перебирать такие данные в цикле надо с учётом, что интересная информация лежит только в каждом 58 элементе: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> for(int i=0;i<DataCount;i+=58){ // только каждый 58 элемент! ... } <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> For i=0 to DataCount ... i = i+57 next i Так отрисовка явно ускорится, даже если вы возьмёте график за год или за 2 года. Однако, если брать данные за год, надо смотреть в сторону предложения Akina, потому что в его варианте это учитывается (тоесть, не ускоряется отрисовка, а сама выборка формирует меньше данных, беря их тем же образом сразу из базы данных) Так же, можно не отбрасывать эти 57 значений, а провести "сглаживание" и собрать из 58 значений 1 точку, а уже по этим собранным точкам составить интерполированный график. |
Автор: Akina 23.09.16, 08:18 |
Отбрасывать нельзя. Значения в данных идут группами. Запросто вся группа может оказаться среди этих отброшенных 57 значений - итог очевиден. Сглаживание лучше... а вот какой тип сглаживания больше подходит, решать ТС. |
Автор: Penumbra 23.09.16, 10:00 |
Akina, печально, но я не могу разобраться в Вашем запросе, тк я в sql не силен я запрос из бд делаю: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> str = "select * From tabl1 where dat between #" & Format(dt1, "mm\/dd\/yyyy hh:mm:01") & "# and #" & Format(dt2, "mm\/dd\/yyyy hh:mm:02") & "# order by dat ;" |
Автор: Akina 23.09.16, 12:14 |
Penumbra А чего там разбираться? Вот есть у тебя N колонок пикселов. Если начальные дата-время (пусть А), и конечные (пусть В). Ты знаешь дату-время какой-то точки (пусть Х). В какую колонку M эта точка попадёт? M = N*(Х-А)/(В-А) - чистой воды арифметика... вот для всех точек мы и считаем этот номер колонки, и по нему группируем. А из всех попавших в колонку точек берём максимальное (вот единственное, что имеет смысл обсуждать и над чем думать) значение. |
Автор: Penumbra 24.09.16, 22:39 |
ага, вроде бы получилось! сделал запрос <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> rcount = dt / xx3 str = "select cdate(avg(dat)) as dat_sr, max(param) as param_mx, min(param) as param_mn From tabl1 where dat between #" _ & Format(dt1, "mm\/dd\/yyyy hh:mm:01") & "# and #" & Format(dt2, "mm\/dd\/yyyy hh:mm:02") & "# group by fix(cdbl(dat)/cdbl(timeserial(0,0," & rcount & "))) ;" вроде нормально график строит, правда точность не проверял из значений беру максимальное и минимальное строю эти две точки сразу на графике и соединяю прямой теперь график отрисовывается быстро, хотя сам запрос при выборке данных за 5-6 суток обрабатывается секунд 15-20 |
Автор: Akina 25.09.16, 13:45 |
Сделай предрасчётную укрупнёнку в отдельную таблицу. Например, минимум и максимум поминутно. На точности графика при построении за сутки или более это практически не скажется, а считать запросу куда как меньше... |