кеширование результатов поиска в сеансе и поддержание чистоты кучи больших объектов

Итак, я некоторое время работал над проектом ASP.NET, и, похоже, я сделал несколько неудачных дизайнерских решений, которые будут преследовать меня, поскольку проект становится все больше и больше с точки зрения содержащихся данных.

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

Итак, у меня есть (несколько дорогой запрос), который дает от 1 до 20000 результатов. При последующих запросах мы можем просто листать набор результатов, поэтому я сохраняю этот результат в сеансе. Сессия InProc. Мне любопытно:

  • Имеет ли смысл а) хранить результат б) в сеансе в) в процессе? Мне нужна скорость (а). Я не знаю, есть ли более эффективный способ, чем хранить его пользователем (b), и если я использую более сложный сервер состояний, не будет ли он работать медленнее (c)? Или это может быть решением, быстрее избавляющимся от этих больших объектов, вместо того, чтобы хранить последний набор результатов в ОЗУ до истечения срока действия сеанса?

  • Если какой-либо результирующий набор> ~ 20000 строк в конечном итоге потенциально испортит LOH, есть ли общий способ обойти это?

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


person Nicolas78    schedule 19.05.2011    source источник


Ответы (3)


Зачем возвращать всегда все записи?? Я думаю, что лучший способ ускорить ваш запрос - это вернуть только те данные, которые нужны пользователю.. так что только те данные, которые помещаются на странице!

Попробуйте поискать в Google ROW_NUMBER() (SQL Server) или LIMIT (mySQL).

Вот учебник по 2 товарам

1) блог СкоттГу

2) 15-секундное руководство

person 2GDev    schedule 19.05.2011
comment
Спасибо. До сих пор все ответы были очень полезными, но на самом деле это очень хорошо подходит для рассматриваемой проблемы. Мы начали с серверной части Access. Теперь мы собираемся перейти на SQL Server, однако я подумал, что если .NET-часть приложения не может справиться с нагрузкой на память, нет смысла в дорогостоящей миграции базы данных, если производительность не может заметно возрасти. Однако это может быть хорошим моментом, показывающим, как мы можем лучше оптимизировать часть .net с приличной базой данных за ней (при условии, что после короткого исследования Google это невозможно с доступом для произвольной сортировки?) - person Nicolas78; 19.05.2011
comment
на самом деле нашел способ разбиения на страницы в доступе stackoverflow.com/questions/1900635/, но, учитывая уродство решения по сравнению с правильной формулировкой sql, может быть еще точка для давно назревшей миграции - person Nicolas78; 19.05.2011
comment
одна вещь, которую вы можете сделать с доступом, - это попытаться выполнить пейджинг с помощью некоторого SQL, например: SELECT TOP (10) FROM Table1 ORDER BY Id ... Затем сохраните последний идентификатор в переменной, а затем вы можете сделать это: SELECT TOP (10) FROM Table1 Where Id › LastIdStored .... Но лучше всего мигрировать на другую БД! - person 2GDev; 19.05.2011
comment
да, у нас есть динамические критерии сортировки, это плохо кончится в доступе - person Nicolas78; 19.05.2011

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

Альтернативой является просто сохранение идентификаторов набора результатов для 20000 элементов. Таким образом, если вам нужно просмотреть их, вы можете просто быстро получить отдельные строки с помощью первичного ключа.

Наконец, возможно, вам следует рассмотреть возможность использования объекта Cache для хранения ваших результатов, а не сеанса. Таким образом, вы позволяете .NET решать, когда удалять объекты, и это не приводит к раздуванию сеанса.

person Keltex    schedule 19.05.2011
comment
Благодарю. В итоге я пометил ответ 2GDev для ссылки ROW_NUMBER(), но вы, ребята, в основном согласны, теперь у меня грядет серьезная перестройка;) - person Nicolas78; 20.05.2011

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

Если вы используете сеанс, определенно не используйте режим InProc, потому что по мере роста пользователей процесс будет потреблять память и в конечном итоге перезапускать, и сеансы пользователей будут потеряны, даже если время ожидания не истекло.

Попробуйте выполнить страницу с базой данных, как упомянул Keltex, только извлеките данные, которые вы отображаете.

person mikey    schedule 19.05.2011