Повышение производительности уровня доступа к данным nHibernate - PullRequest
4 голосов
/ 18 апреля 2010

Я работаю над повышением производительности DataAccess Layer существующего веб-приложения Asp.Net. Сценарии.

  1. Это веб-приложение в Asp.Net.
  2. Уровень DataAccess построен с использованием NHibernate 1.2 и предоставляется в качестве службы WCF.
  3. Класс Entity помечен DataContract.
  4. Ленивая загрузка не используется, и из-за тщательного извлечения отношений огромное количество объектов базы данных не загружается в память. Нет попаданий в базу данных также высока. Например, я профилировал приложение, используя NHProfiler, и было около 50+ вызовов sql для загрузки одного из объектов Entity с использованием первичного ключа.
  5. Я также не могу сильно изменить код, так как это существующее приложение без тестовых примеров NUnit.

Пожалуйста, могу ли я получить некоторые предложения здесь?

РЕДАКТИРОВАТЬ 1: я пытался использовать отложенную загрузку, но проблема в том, что, поскольку сущность также используется как DataContract, она запускает отложенную загрузку во время сериализации. Использование DTO-объектов - вариант, но это огромное изменение, поскольку ни один из объектов не является огромным. Без тестовых случаев это потребует огромного количества ручного тестирования.

РЕДАКТИРОВАТЬ 2: проект был написан давно без гибкости для написания модульных тестов Например Сам объект содержит операцию CRUD и использует NHibernate Session.

class SampleEntity : ICrudOperation
{
   //fields and properties

   public IList<SampleEntity> Update()
    {

       //perform business logic (which can be huge and call the ICrudOperation of 
       //other entities

       ISession session = GetSessionFromSomewhere();
       session.Update(this); 

    }

}

Это просто пример для обновления. И существует около 400 сущностей, которые взаимозависимы. Есть ли способ написать модульный тест для этого

Ответы [ 5 ]

3 голосов
/ 18 апреля 2010

Кажется, что здесь можно улучшить архитектуру.

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

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

Стоит изучить вопрос обновления до последней версии NHibernate, хотя без юнит-тестов это, вероятно, будет страшно, но определенно стоит.

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

3 голосов
/ 19 апреля 2010

Предложение 1

  1. Включить Ленивая загрузка
  2. Используйте обычай NhibernateDataContractSerializerSurrogate удалить прокси, прежде чем они отправлено через WCF ( проверить Аллан Ответ Ричи здесь )

Эта комбинация уменьшит количество исходных соединений SQL и уменьшит размер графа вашего объекта.

Однако , это приведет к следующей проблеме:

Ваши потребители / клиенты не будут иметь доступа ко всем данным. Им нужно будет сделать несколько звонков на сервер, чтобы получить дочерние объекты / коллекции.

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

Предложение 2

Ваши SQL-соединения медленные? Вы можете попробовать заменить fetch = join на fetch = select и посмотреть, ускорит ли это все.

Предложение 3

Определите время, затрачиваемое на SQL , против времени, потраченного на отправку данных по сети . Вы можете подумать о сжатии графа объектов, прежде чем отправлять его по проводам.

Предложение 4

Поменяйте местами любые ленивые прокси-серверы Nhibernate с вашими собственными пользовательскими прокси-серверами с отложенной загрузкой перед возвратом графа объектов потребителю. Ваши пользовательские прокси будут лениво загружать данные через WCF / Web-сервисы (вместо вызова db). Я добился определенного успеха, используя эту технику на богатом клиенте.

Теоретически, это должно позволить вашему клиентскому коду оставаться как есть. Здесь есть нить вдоль этих линий.

Надеюсь, это поможет.

2 голосов
/ 27 апреля 2010

Возможно, сначала вам следует перейти на последнюю стабильную версию NHibernate (2.1.2, AFAIK), хотя я сам предпочитаю использовать альфа-версию 3.0. Более поздние версии, как правило, имеют более высокую стабильность и производительность, чем более ранние. И я думаю, что API NHibernate достаточно обратно совместим, чтобы сделать это.

Итак, мое рекомендуемое решение для вас это:

Если вам ДЕЙСТВИТЕЛЬНО требуется энергичная загрузка, количество запросов, используемых для возврата объекта вместе с полным графом объектов, будет по-прежнему огромным, но не беспокойтесь, есть надежда !

NHibernate - это ORM уровня предприятия, что означает, что он очень хорошо масштабируется. Он может использовать различные стратегии кэширования для различных сценариев.

Имеет внутренний кеш для:

  • Сущность
  • Коллекция
  • Запросы
  • Timestamps

И у него есть два уровня:

  • Кэш первого уровня: кэширует данные для одного ISession экземпляра. Он включен по умолчанию.
  • Кэш второго уровня: кеширует вещи для всего того же ISessionFactory. По умолчанию он выключен.

Приведенное выше описание является для меня очень простым, но это именно то, что вам нужно. Вы можете найти больше информации на эту тему в nhibernate.info и блоге Айенде , , нескольких вопросах в StackOverflow , а также в других местах.

Вам нужно сделать две вещи:

  • Убедитесь, что все ваши ISession получены от одного и того же ISessionFactory
  • Включить кэш второго уровня (вышеупомянутые ссылки помогут вам в этом)

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

1 голос
/ 27 апреля 2010

В дополнение к предложениям других людей вы рассматривали возможность профилирования своего приложения с помощью NHibernate Profiler ? (Есть 30-дневная пробная версия)

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

0 голосов
/ 18 апреля 2010

настройка стратегии кэширования внутри NHibernate ....

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...