Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Живые данные

3.2K
14 октября 2007 года
nikipelovav
152 / / 12.04.2006
Вопрос об механизме одновременного отображения данных.

Ситуация: открыто два или более окна с таблицами данных. Добавляем запись в одном окне. Эта запись может подходить по условиям запроса данных в других окнах, а может и нет. Как реализовать механизм "живые данные", который бы автоматически обновлял данные в других окнах? Варианты отображения окон: 1-е во весь экран либо все окна расположены пропорцинально (т.е. все видны).

Я реализовал подобный механизм. Всё работает.
Но:
1) после обработки 20-30 добавленых записей возникает огромное торможение в работе. Даже простой поиск "как черепаха"
2) сознательно, пока, не говорю как зделал это, чтобы услышать Ваши личные мнения.

Спасибо.

PS: база данных BDE, таблицы Paradox.
2.1K
14 октября 2007 года
mainigor
151 / / 21.10.2005
может быть используется refresh ? и еще TTable.
А по какому событию соседнее окно узнает, что запись добавилась / модифицировалась ? может в этом причина ?
Если запросы по таймеру и частые, то вполне вероятно что при увеличении базы скорость запросов падает.
11
15 октября 2007 года
oxotnik333
2.9K / / 03.08.2007
на TTable::AfterPost посылать всем окнам Refresh таблиц, это если напрямую таблицы отображаются, или TQuery::Active = false/true; если через запросы.
по идее тормозить не должно, даже при большом количестве записей.
К стати, для MSSQLServer заметил что Refresh криво работает, т.е. старые записи обновляет, а новые не показывает, только Close/Open помогает, но это тормоза большие.
3.2K
15 октября 2007 года
nikipelovav
152 / / 12.04.2006
Цитата:

по идее тормозить не должно, даже при большом количестве записей.


Это конечно вопрос филосовский. ;)

Начну по порядку.

Моя программа предназначена для ведения бухгалтерии небольшого ЧП по продаже автозапчастей. Основа программы - мой исходник в разделе "Другое" ProjBeam. В основном, каждая таблица данных отображается в отдельном (MDI) окне (документе). Я чаще всего работаю с тремя типами документов: каталог-ценник, заказ и отчёт о работе. В таблице "каталог-ценник" 7200 записей, получаемые SQL запросом из двух таблиц: фиксированный каталог товара и временной со статистическими данными ( есть в наличии, продано за период, в текущих заказах, в текущих кредитах ). Таблица заказов содержит 25000 записей, также получаемых SQL запросом из двух таблиц: журнал заказов ( когда, кому, для кого) и списка заказа ( наименования, номера, количество заказанное, полученное ). Естественно, что при работе с отдельным заказом отображаються не 25000 записей, но ведь они обрабатываються SQL запросом! К томуже, скорость обработки данных зависит от драйвера БД. Например BDE отображает 7200 записей "каталога-ценника" примерно за 1 секунду, а вот Accuracer уже за 5 ;( Представляете что произойдёт при Query->Refresh() 25000 записей.

Теперь об "живых даных".

Я попытался организовать обработку собственных сообщений в отдельном потоке TThread. Сазу замечу, что поток TThread получает процессорное время для работы как часть времени основного VCL потока приложения. В общем это "псевдо-параллельная" работа потока. Если Вы где-то вывели диалог, то пока не нажмёте [Ok] вся остальная работа стоит! ( Это так, плачь в желетку ... ;) ) Когда в документе (таблице, класс BDocument) происходит создание/изменение/удаление записи, посылается сообщение "проводнику документов" (класс BExplorer). Обработчик сообщений void __fastcall BExplorer::ReceiveMessage ( BMessageStruct* pMS ) выполняется в потоке TThread. В нём всем документам (в цикле) передаётся сообщение о операции с записью и выполняется его обработка. Если окно документа, который пытается обработать сообщение не отображается, то сообщение добавляется в очередь (список) и будет обработано по факту "окно отобразилось". Это уменьшает "тормоза" в работе.

Теперь рассмотрим реальную работу с данными.

Открыты два окна: Каталог-ценник и Заказ. В "каталоге" по правой клавише над записью о товаре вызываю пункт меню "Перенести в заказ". Вызывается диалог "Заказ->Добавить запись". Нажимаю "Ok". Запись добавлена. Послано соответствующее сообщение. Окно "каталога" активно, поэтому оно обрабатывает это сообщение.

Объясню, зачем "каталогу" отслеживать изменения в "заказе". Посмотрите на скриншот окна "каталога". Для удобства формирования заказа в сетке таблицы приведены колонки: "Есть", "Продано", "Заказано", "Кредит". Эти данные облегчают анализ и принятие решения "заказывать или нет". Дополнительно, в панели "Заказ" отображается подробная информация о текущих заказах этого товара. Поэтому, по факту изменения записи в заказе необходимо отследить изменение "количество в заказе" и если необходимо - изменить значение в колонке "Заказано" документа "Каталог-ценник".

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

Поэтому мне приходится делать следующее:

1) поиск по номеру изделия в отображаемых данных. Если найдена запись и изменилось количество "Заказано" - записываю новое значение.

2) поиск по номеру изделия во временной таблице. Если найдена запись и изменилось количество "Заказано" - записываю новое значение.

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

Как Я уже писал, примерно после 20-30 добавленых в заказ записей программа начинает тормозить! Поиск в "Каталоге" работает очень медленно.

Возможно как-то увеличивается кэш множественнх модификаций, а драйвер БД ищет и в нём? Как очищать кэш? Что делать? ;)

11
15 октября 2007 года
oxotnik333
2.9K / / 03.08.2007
могу предложить при таком количестве инфы перейти на SQL сервер, и делать все операции исключительно на нем, а результаты уже отображать при помощи своей софтины.
Как осуществыляется
Цитата:
поиск по номеру

3.2K
15 октября 2007 года
nikipelovav
152 / / 12.04.2006
Вот код метода "Обработка сообщений" для документа "Каталог-ценник". Смотри ;)
11
15 октября 2007 года
oxotnik333
2.9K / / 03.08.2007
к стати, насчет ускорения запросов:
SELECT * FROM Table_Name WHERE ...
сильно проигрывает в скорости
SELECT (только нужные поля) FROM Table_Name WHERE ...
3.2K
15 октября 2007 года
nikipelovav
152 / / 12.04.2006
Цитата:

к стати, насчет ускорения запросов:



Спасибо, учту. Но не везде в программе. Я описал процесс автоматического сохранения новых и изменённых данных. Он основан на отслеживании текущих и новых данных в событиях BeforEInsert, BeforeEdit, AfterPost, BeforePost И т.п. Если в SQL запросе не будет всех полей, которые модифицируются в диалоге "Добавить/Изменить запись" то эта схема работать не будет. А уж больно удобная. ;) Неважно какую новую таблицу я добавлю в БД, сохранение данных уже работает ;).

11
15 октября 2007 года
oxotnik333
2.9K / / 03.08.2007
по поводу кода:
1. if ( pSrc->Locate( t_PartExt_F_LineCode , OrderCode, Opts ) ) я бы заменил на SQL ("SELECT COUNT FROM pSrc WHERE pSrc = OrderCode"). если > 0
2.
 
Код:
for ( int i = 0; i < pSrcCEF->RecordCount; i++)
            {
              OrderNow += pSrcCEF->FieldByName( t_Order_F_QuantOrder )->AsInteger - pSrcCEF->FieldByName( t_Order_F_QuantSale )->AsInteger;
              pSrcCEF->Next();
            }

заменил бы опять же на SQL: "SELECT SUM (t_Order_F_QuantOrder - t_Order_F_QuantSale ) FROM pSrcCEF"
3.
 
Код:
str  = "SELECT * FROM \"" + t_Order_TableName + "\" O ";
            str += " WHERE ( O.\"" + t_Order_F_Creater     + "\" = \"" + pSrcCEF->FieldByName( t_PartList_F_Creater     )->AsString + "\" )";
            str += " AND ( O.\"" + t_Order_F_NumberC + "\" = \"" + pSrcCEF->FieldByName( t_PartList_F_NumberC )->AsString + "\" )";
            str += " AND ( O.\"" + t_Order_F_Actual + "\" = TRUE )";
            str += " AND ( O.\"" + t_Order_F_QuantOrder + "\" > O.\"" + t_Order_F_QuantSale + "\" )";

заменил бы параметризированным запросом
4. Связку TTable::Edit|Post аналогично в запрос "UPDATE Table_Name SET (Fields_Names) AS (Values) WHERE ..."
3.2K
15 октября 2007 года
nikipelovav
152 / / 12.04.2006
Про способы оптимизации кода - спасибо, попробую на досуге.
Но ведь это ( возможно ) не ответ на мой вопрос - почему именно через определённое время ( 20 - 30 операций ) начинает тормозить? Что "в моём подходе" к решению вопроса не так?
11
15 октября 2007 года
oxotnik333
2.9K / / 03.08.2007
возможно CachedUpdates замусоривается
т.к. таблицы редактируются Edit/Post
а вообще BDE давно умерло как СУБД, может как раз и из за этого
3.2K
15 октября 2007 года
nikipelovav
152 / / 12.04.2006
Цитата:

а вообще BDE давно умерло как СУБД, может как раз и из за этого



Не надо хоронить BDE. Для локальной БД очень хорошо работает.
Дело в том, что сейчас (и уже 7 лет) с таким же объёмом данных работает моя старая программа и всё "летает". Возможно Я просто мало знаю о "нюансах" в работе с источниками данных TDataSet? Поэтому мой подход в новой программе приводит к "тормозам".

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог