Russian Qt Forum
Сентябрь 30, 2024, 18:30 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Кэширование данных, полученных с сервера  (Прочитано 4970 раз)
JamS007
Гость
« : Сентябрь 24, 2011, 10:54 »

Здравствуйте, прошу помощи в решении следующей задачи:

Есть сервер, который напрямую связывается с сервером БД (postgres) и выполняет роль посредника между всеми клиентами и самой БД. Такой механизм выбран по нескольким причинам и уже на 90% реализован, поэтому от него отказываться нельзя.

На стороне клиента должна отображаться таблица с товарами и их характеристиками в зависимости от выбранного раздела. Но, проблема в том, что товаров в выбранном разделе может быть очень много, и передать всю информацию про них из БД клиенту будет очень накладно по времени, да и нагрузка на сеть вырастет.

У меня уже есть несколько идей по оптимизации этого процесса:
1. Передавать клиенту только то, что уместиться в регион видимости QTableView, а если ползунок прокрутки спуститься - передать еще порцию информации. Тут проблема в том, как отследить какая информация уже передана на клиент, а какая еще нет. ведь если хранить на сервере список с переданными полями, то он очень быстро скушает всю оп. память, а диск его кидать = затормозить сервер.

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

Другие идеи также приветствоваться, спасибо.
Записан
asvil
Гость
« Ответ #1 : Сентябрь 24, 2011, 11:10 »

А почему бы не предоставить пользователю фильтрацию запрашиваемых данных?
Записан
JamS007
Гость
« Ответ #2 : Сентябрь 24, 2011, 11:15 »

Эта возможность есть, но даже она в теории может давать на выходе много данных, которые тоже желательно кеэшировать или показывать не все.
Записан
demiurg
Гость
« Ответ #3 : Сентябрь 24, 2011, 11:21 »

А что вам мешает на сервере с БД поставить APACH и запустить php скрипт. Сразу все проблемы отпадут... И на хост любой поставитьм можно... И клиенту не надо будет ставить какие то приложения... Всё из браузера посмотрит... 
Записан
JamS007
Гость
« Ответ #4 : Сентябрь 24, 2011, 11:26 »

demiurg, спасибо но данный вариант не подходит.
Записан
Rem Norton
Гость
« Ответ #5 : Сентябрь 24, 2011, 12:11 »

Под описаную задачу подходит QSqlQueryModel. Она засасывает 256 строк сразу, остальные по факту прокрутки View. НО есть ограничение: если резалтсет forwardOnly(), то она ничего не отобразит. Наступал на эти грабли только когда пытался подружить QSqlQueryModel с MS SQL. У MS, если резалтсет надо получить из хранимой процедуры, то в QSqlQuery надо ставить forwardOnly = true, а в коде QSqlQueryModel четко прописано, что с такими курсорами она не работает.  Возможно у Postgres (не проверял, не уверен) есть подобное ограничение при получении резалтсета из хранимой процедуры.
« Последнее редактирование: Сентябрь 24, 2011, 12:18 от Rem Norton » Записан
JamS007
Гость
« Ответ #6 : Сентябрь 24, 2011, 14:07 »

Rem Norton, да, я знаю что QSqlQueryModel подходит под описанную задачу, но, для ее работы нужен адрес хоста с БД, а мы имеем только адрес промежуточного сервера.

Возможно, покопаю исходники QSqlQueryModel. Спасибо.
Записан
Rem Norton
Гость
« Ответ #7 : Сентябрь 24, 2011, 19:19 »

Копать QSqlQueryModel не нужно. Если какая-то экзотика в подключении, то капать надо QSqlDriver. Все подключения только там, все остальное - надстройка.

Кстати QSqlDriver легко пишется самостоятельно при наличии документации на API нужной СУБД.
Записан
vlad-mal
Гость
« Ответ #8 : Сентябрь 30, 2011, 16:24 »

Здравствуйте, прошу помощи в решении следующей задачи:

Есть сервер, который напрямую связывается с сервером БД (postgres) и выполняет роль посредника между всеми клиентами и самой БД. Такой механизм выбран по нескольким причинам и уже на 90% реализован, поэтому от него отказываться нельзя.

На стороне клиента должна отображаться таблица с товарами и их характеристиками в зависимости от выбранного раздела. Но, проблема в том, что товаров в выбранном разделе может быть очень много, и передать всю информацию про них из БД клиенту будет очень накладно по времени, да и нагрузка на сеть вырастет.

У меня уже есть несколько идей по оптимизации этого процесса:
1. Передавать клиенту только то, что уместиться в регион видимости QTableView, а если ползунок прокрутки спуститься - передать еще порцию информации. Тут проблема в том, как отследить какая информация уже передана на клиент, а какая еще нет. ведь если хранить на сервере список с переданными полями, то он очень быстро скушает всю оп. память, а диск его кидать = затормозить сервер.

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

Другие идеи также приветствоваться, спасибо.
Совсем недавно решил подобную задачу, обычной двузвенкой. Основная идея:  клиенту информация передается только та, которая ему нужна (т.е., на которую он смотрит) Улыбающийся

1. Клиент, желая отобразить набор записей в нужном порядке, загружает только набор идентификаторов этих записей, в том же порядке (если использовать 4-байтное целое, то получается быстро и не накладно: 4МБ для миллиона записей).
2. Данные отображаются в табличке (ну или в дереве) со множеством столбцов, состав которых клиент, естественно, знает.
3. Перед выполнением перерисовки (по любой причине - скроллинг, ресайзинг и проч.) таблички формируется список идентификаторов, которые должны быть показаны в обновляемой области (причем, не обязательно она совпадает с клиентской областью).
4. Для полученного списка идентификаторов выполняется проверка наличия значений полей (записей) в локальном кэше. Для тех, которых в локальном кэше нет, данные подгружаются в кэш одним запросом.
5. Далее, при выполнении перерисовки элементов (ячеек) таблички, последняя извлекает данные из кэша.
~~~~~~~~~~~~
Все операции выполняются по инициативе элемента отображения (таблички).

При изменении данных на сервере локальные кэши клиентов сбрасываются и выполняется перерисовка видимой части таблички, и, если измененная информация попала в область видимости других клиентов - она сразу видна. Таким образом, в кэши грузится только то, на что смотрит пользователь. При удалении записи на других клиентах она не исчезает (ибо список идентификаторов не изменялся), а отображается пустой строкой серого цвета, что наглядно. Есть еще кнопа "Обновить", обновляющая список идентификаторов.
Отслеживание добавления записей реализовывать не стал по политическим причинам (при добавлении у других клиентов энейблится кнопка "Обновить" - что оказалось достаточно).

Трудность была, как ни странно, в реализации быстрого кэша (сказывались незнания основ). В общем, пригодились ассоциативные массивы в комбинации со связным списком (связный список - для того, чтобы ограничить рост кэша - хотя, если записей не более сотни тысяч, можно и не ограничивать).

...когда клиентов стало достаточно много, пришлось ввести небольшую случайную задержку для операции сброса кеша/перерисовки при модификации данных ну других клиентах, чтобы не перегружать сервер сотней одновременных запросов со всех клиентов.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.05 секунд. Запросов: 22.