0

Customer テーブルを持つデータベースがあります。これらの顧客はそれぞれ、Installationテーブルへの外部キーを持ち、さらにAddressテーブルへの外部キーを持っています (テーブルは簡単にするために名前が変更されています)。

NHibernateでは、次のように Customer テーブルをクエリしようとしています。

ISession session = tx.Session;
var customers = session.QueryOver<Customer>().Where(x => x.Country == country);                               
var installations = customers.JoinQueryOver(x => x.Installation, JoinType.LeftOuterJoin);
var addresses = installations.JoinQueryOver(x => x.Address, JoinType.LeftOuterJoin);

if (installationType != null)
{
    installations.Where(x => x.Type == installationType);
}

return customers.TransformUsing(new DistinctRootEntityResultTransformer()).List<Customer>();

次のような SQL クエリが生成されます ( NHibernate Profilerによってキャッチされます)。

SELECT *
FROM   Customer this_
       left outer join Installation installati1_
         on this_.InstallationId = installati1_.Id
       left outer join Address address2_
         on installati1_.AddressId = address2_.Id
WHERE  this_.CountryId = 4
       and installati1_.TypeId = 1

上記の SQL クエリをMicrosoft SQL Server Management Studioで実行すると、約 5 秒で実行されますが、約 200.000 レコードが返されます。それにもかかわらず、コードの実行時にListを取得するのに多くの時間がかかります。結果なしで10分間待っていました。デバッグ ログは、オブジェクト階層が原因で、多くのオブジェクトが構築され、開始されたことを示していました。このパフォーマンスの問題を解決する方法はありますか?

4

2 に答える 2

1

何をしようとしているのかわかりませんが、OR マッパーを介して 200000 レコードを読み込んで保存することはできません。200000 個のオブジェクトを作成するには、多くのメモリと時間がかかります。目的に応じて、それらをページにロードするか、データベースで直接更新クエリを作成する (sp または名前付きクエリ) ことで、パフォーマンスを修正できます。バッチ処理は次の方法で実行できます。

criteria.SetFirstResult(START).SetMaxResult(PAGESIZE);
于 2013-03-11T12:32:31.527 に答える
0

NHibernate Profiler は、duration 列 x/y に 2 つの時間を示します。x はクエリを実行する時間であり、y はオブジェクトを初期化する時間です。最初のステップは、問題がどこにあるかを特定することです。クエリが遅い場合は、SQL プロファイラー (SQL Server を想定) を使用してデータベースに送信された実際のクエリを取得し、SSMS でそのパフォーマンスを確認します。

ただし、問題はログ レベルにあると思われます。ログ レベルを DEBUG に設定すると、NHibernate は非常に詳細なログを生成し、パフォーマンスに大きな影響を与えます。

200000 件のレコードでうまく機能させることができたとしても、意味のある方法でユーザーに表示できる量を超えています。結果セットのサイズを小さくするには、ページング/フィルタリングを使用する必要があります。

于 2013-03-11T13:33:19.073 に答える