discriminatorsで作業するときにSELECT + 1を避ける

私は項目の状態に対処するために弁別子を​​使用しています。私は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などのすべての項目を選択したときです。これは、各項目に対して1つの照会と各状態に対して5つの照会を発行します。私は非常に頻繁に私は非常に多くのクエリを実行しているアイテム(状態で)を照会しているので。

さて、プロファイラを見ると、最初の状態Iのクエリがクエリに6ms、マテリアライズするのに6msかかるため、問題の大部分がわかりません。他のすべての状態は、クエリーに0ms、マテリアライズに0msと表示されます。 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())
        .List();

溶液

犯人は

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

SELECT + 1の問題を解決するには、個々のIDではなく弁別者オブジェクトのリストで照会するだけです。

.Where(() => itemAlias.State.IsIn(new []{State.FooState, State.BarState}))
0
@hival:編集を参照してください。
追加された 著者 Nosila,
クエンティングコードを提供できますか?
追加された 著者 hival,

1 答え

それはあなた自身が熱心に状態をロードするように聞こえるので、最初のクエリは次のようなものです:

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

そして、あなたは各状態に対して1つずつ5つのクエリを持っています:

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

これは、状態の名前を熱心に読み込むために、最初のクエリで "項目"から "状態"への結合を指定する必要があります。そうでない場合は、Stateオブジェクトを遅延に設定します結果に識別子以外の情報が必要ない場合はロードされます。

1
追加された