Здравствуйте, прошу помощи в решении следующей задачи:
Есть сервер, который напрямую связывается с сервером БД (postgres) и выполняет роль посредника между всеми клиентами и самой БД. Такой механизм выбран по нескольким причинам и уже на 90% реализован, поэтому от него отказываться нельзя.
На стороне клиента должна отображаться таблица с товарами и их характеристиками в зависимости от выбранного раздела. Но, проблема в том, что товаров в выбранном разделе может быть очень много, и передать всю информацию про них из БД клиенту будет очень накладно по времени, да и нагрузка на сеть вырастет.
У меня уже есть несколько идей по оптимизации этого процесса:
1. Передавать клиенту только то, что уместиться в регион видимости QTableView, а если ползунок прокрутки спуститься - передать еще порцию информации. Тут проблема в том, как отследить какая информация уже передана на клиент, а какая еще нет. ведь если хранить на сервере список с переданными полями, то он очень быстро скушает всю оп. память, а диск его кидать = затормозить сервер.
2. Все ранее принятые записи писать в кэш, и загружать данные в первую очередь из кэша, а уже потом обращаться к серверу. В этом случае проблема в том, чтобы синхронизировать информацию между несколькими клиентами, так как каждый клиент имеет право удалить или изменить запись, а все другие клиенты должны об этом "знать", чтобы обновить свой кэш.
Другие идеи также приветствоваться, спасибо.
Совсем недавно решил подобную задачу, обычной двузвенкой. Основная идея: клиенту информация передается только та, которая ему нужна (т.е., на которую он смотрит)
1. Клиент, желая отобразить набор записей в нужном порядке, загружает только набор идентификаторов этих записей, в том же порядке (если использовать 4-байтное целое, то получается быстро и не накладно: 4МБ для миллиона записей).
2. Данные отображаются в табличке (ну или в дереве) со множеством столбцов, состав которых клиент, естественно, знает.
3. Перед выполнением перерисовки (по любой причине - скроллинг, ресайзинг и проч.) таблички формируется список идентификаторов, которые должны быть показаны в обновляемой области (причем, не обязательно она совпадает с клиентской областью).
4. Для полученного списка идентификаторов выполняется проверка наличия значений полей (записей) в локальном кэше. Для тех, которых в локальном кэше нет, данные подгружаются в кэш одним запросом.
5. Далее, при выполнении перерисовки элементов (ячеек) таблички, последняя извлекает данные из кэша.
~~~~~~~~~~~~
Все операции выполняются по инициативе элемента отображения (таблички).
При изменении данных на сервере локальные кэши клиентов сбрасываются и выполняется перерисовка видимой части таблички, и, если измененная информация попала в область видимости других клиентов - она сразу видна. Таким образом, в кэши грузится только то, на что смотрит пользователь. При удалении записи на других клиентах она не исчезает (ибо список идентификаторов не изменялся), а отображается пустой строкой серого цвета, что наглядно. Есть еще кнопа "Обновить", обновляющая список идентификаторов.
Отслеживание добавления записей реализовывать не стал по политическим причинам (при добавлении у других клиентов энейблится кнопка "Обновить" - что оказалось достаточно).
Трудность была, как ни странно, в реализации быстрого кэша (сказывались незнания основ). В общем, пригодились ассоциативные массивы в комбинации со связным списком (связный список - для того, чтобы ограничить рост кэша - хотя, если записей не более сотни тысяч, можно и не ограничивать).
...когда клиентов стало достаточно много, пришлось ввести небольшую случайную задержку для операции сброса кеша/перерисовки при модификации данных ну других клиентах, чтобы не перегружать сервер сотней одновременных запросов со всех клиентов.