| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Для новичков > Контейнер с быстрым поиском по разным полям |
| Автор: kami 9.6.2013, 21:51 | ||||
| Доброго времени суток, господа! Есть класс (очень упрощенно):
И контейнер:
Элементов всего - около 10 тысяч. Часто приходится искать и обрабатывать элементы как по индексу, так и по какому-либо из перечисленных полей, причем - пакетно, по несколько штук. Поиск по полю выполняется простым перебором. Такого, чтобы искать сразу по нескольким полям - не бывает. Проблема: поиск длится долго. AQTime Standart выдает безумные значения в колонке HitCount на TList<TmyItem>.GetItem Вопрос: как бы это ускорить? Пока - единственное, что приходит в голову - создать в TItemContainer три "внутренних" TDictionary с ключами по полям ID, Name и ShortName. В Notification TMyItemContainer добавлять/удалять элементы из этих словарей, ну и в функциях GetItemBy... обращаться непосредственно к соответствующему TDictionary... Не слишком ли я полез в дебри? Может, есть проще способы? Заранее всем спасибо! |
| Автор: northener 10.6.2013, 01:46 |
| А использовать БД никак? |
| Автор: kami 10.6.2013, 08:42 |
Тут всплывают дополнительные проблемы я практически не умею работать с БД (простейшие операторы DML не в счет), да и кроме того - обращение на каждый "чих" к БД - затратная операция. Да, изначально все активные элементы считываются из БД (на самом деле их гораздо больше 10к, но активных - примерно столько). Но в дальнейшем это становится слишком накладно. Кроме того - изначальная архитектура приложения (тут уж я бессилен) не терпит кучи открытых датасетов (тем более, что у таблиц куча взаимосвязей 1:много). Поэтому - можно считать, что никак. |
| Автор: Illusion Dolphin 11.6.2013, 21:37 |
| Ну тогда делать как БД, т.е. сделать индекс (можно просто по убыванию/возрастанию расположить) по каждому полю и обновлять его по вставке. Поиск - по индексу бинарнм поиском. |
| Автор: Akella 11.6.2013, 21:55 |
| А зачем куча открытых датасетов? Может можно 1 или 2? Я бы тоже рекомендовал БД. Всё-таки там многое уже реализовано. Не сегодня, так завтра опять пригодится работа с БД. Может лучше потратить время на изучение SQL? На самом деле там всё не так уж и сложно. |
| Автор: kami 13.6.2013, 14:20 | ||
Я, наверное, неправильно выразился. Вернее, не наверное, а точно неправильно Моих знаний по SQL (если быть более точным - то по T-SQL и диалекту MySQL) вполне хватает, чтобы создать нужные таблицы/триггеры/ключи/индексы, выдернуть нужные мне данные и занести новые/изменить существующие. Правильнее будет сказать, что я не умею работать с БД из Delphi. Как я действую на текущий момент: 1. Общая архитектура - трехзвенка. Клиент - сервер приложений общаются между собой по TCP (собственная многослойная надстройка) 2. Клиент, после авторизации, запрашивает у сервера приложений актуальные данные. Тот запрашивает БД, читает в TmyItems кучу всего и вся и отдает это "всё и вся" клиенту. Сразу после чтения датасеты закрываются, но контейнер остается жить со всем прочитанным. 3. Клиент что-то там меняет, изменения приходят на сервер приложений, записываются в БД и автоматом рассылаются всем подключенным клиентам, которым эти изменения интересны. Причем - отправляются только изменения, полностью данные не перечитываются, датасеты не открываются. Вся проблема - в этой рассылке изменений. Потому что сервер приложений (каждое подключение - отдельный поток, вообще ничего не знающий о других) действует так: ага, мне пришло изменение TmyItem с вот таким ID. Он у меня есть? Если нет - создаем новый и Assign его. Если есть - то просто Assign. Потом - отправка клиенту. Пока экземпляров TmyItem было в районе 150 - это (поиск элемента с таким ID/Name/ShortName) было очень быстро, на несколько порядков быстрее, чем обращаться к БД (такие изменения, требующие рассылки, происходят очень часто, тем более что контейнер TmyItems был свой для каждого подключения. Это было признано более оправданным, чем иметь один на всех и тормозить на синхронизации потоков). Но вот я решил оттестироваться на 10тыс. элементов и понял, что система нагрузку не держит. Вообще. Я понимаю, что это (в глобальном смысле) неправильный подход для работы с базой. А вот как это было бы идеологически верно и политически правильно - не понимаю. Ибо все прочитанные книги и статьи рассказывают (по большому счету) как подключиться к БД, открыть датасет и отобразить его в DBControls. А про идеологию - ни слова. Резюмируя: менять архитектуру мне никто не позволит, остаются только сортировки и Dictionary. Всем спасибо за участие, но если есть какие-либо мысли/ссылки - буду благодарен. |
| Автор: PointerToNil 17.6.2013, 18:49 |
| TDictionary - куда уж проще-то? (если кто-то и написал специальный класс как раз под эту задачу, то он его не распространяет, т.к. задача не общая, а специфическая) разве что знаешь более быстрые реализации хэш-таблиц - тогда используй их |