Избегайте SELECT + 1 при работе с дискриминаторами - PullRequest
0 голосов
/ 06 февраля 2012

Я использую дискриминаторы для обработки состояний элементов. Я использую NHibernate Profiler и замечаю, что мое приложение довольно затрудняет выбор моих штатов. У меня всего 8 штатов, и NHibernate продолжает запрашивать так:

SELECT state0_.State_id         as State1_10_0_,
       state0_.Name             as Name10_0_
FROM   States state0_
WHERE  state0_.State_id = **3** /* @p0 */

Что вызывает этот SELECT + 1, когда я выбираю все элементы, где состояние, например, равно 1, 2, 3, 4 или 5. Это выдаст один запрос для моих элементов, а также 5 запросов для каждого состояния. Поскольку я очень часто запрашиваю элементы (с состоянием), я выполняю очень много запросов.

Теперь, глядя на профилировщик, я не уверен, что это большая проблема, потому что первое запрашиваемое состояние занимает 6 мс для запроса и 6 мс для материализации. Все остальные состояния отображаются как принятые 0 мс для запроса и 0 мс для материализации. NHibernate Profiler по-прежнему отображает это как пресловутую проблему SELECT + 1.

Из моего общего сопоставления корней у меня есть:

        References(x => x.State)
            .Not.Nullable()
            .Not.LazyLoad();

Для моего отображения дискриминатора состояний у меня есть:

        Id(x => x.Id, "State_id").GeneratedBy.Assigned();
        Map(x => x.Name).Not.Nullable();

        DiscriminateSubClassesOnColumn("State_id");

Есть что-то, чего я не понимаю в отношении дискриминаторов?

Вот запрос, вызывающий проблему:

var items =
    session.QueryOver(() => itemAlias)
        .SelectList(x => x
                             .Select(xx => xx.Id).WithAlias(() => sentTo.Id)
                             .Select(xx => xx.State).WithAlias(() => sentTo.State)
                             .Select(xx => xx.Status).WithAlias(() => sentTo.Status)
        )
        .JoinAlias(() => itemAlias.State, () => stateAlias)
        .WhereRestrictionOn(() => stateAlias.Id).IsInG(filters)
        .Where(() => itemAlias.Status == Status.InProgress)
        .TransformUsing(Transformers.AliasToBean<SentToDto>())
        .List<SentToDto>();

Решение

виновник был

.WhereRestrictionOn(() => stateAlias.Id).IsInG(filters)

Чтобы решить мою проблему SELECT + 1, мне просто нужно запросить список объектов-дискриминаторов, а не отдельных идентификаторов.

.Where(() => itemAlias.State.IsIn(new []{State.FooState, State.BarState}))

1 Ответ

1 голос
/ 06 февраля 2012

Звучит так, будто вы стремитесь загрузить сами состояния, поэтому ваш первый запрос выглядит примерно так:

SELECT * FROM Items where StateID IN (1,2,3,4,5)

И затем у вас есть пять запросов по одному для каждого состояния:

SELECT Name FROM State WHERE StateID = 1
SELECT Name FROM State WHERE StateID = 2
....

Это позволяет загружать имя состояния, поэтому во избежание этого вы должны в своем первом запросе указать соединение ваших «элементов» с «состояниями», чтобы вы получили имя, в противном случае установите объект State как ленивый.загружен, если вам не нужна другая информация, кроме идентификатора в вашем результате.

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