1

この質問は、その質問の続編のようなものです。

ある種のデータで動作するWCFサービスを構築したい場合、それを高速かつ効率的にしたいのは当然です。これを実現するには、SQL Serverなどのデータストレージバックエンドから、そのデータを要求したWCFクライアントまで、データロードトリップのすべてのセグメントが可能な限り高速に機能するようにする必要があります。

その前の質問に対する答えを探している間、コメントを通じて貢献したSlaumaや他の人たちのおかげで、Entity Frameworkの(最初の)大規模なクエリの時間のかかる部分は、オブジェクトの具体化と、データベースが返されます。後続のクエリでは、すべてがはるかに高速に動作することがわかりました。

MergeOptionこれらの大規模なクエリが読み取り専用操作として使用されると仮定すると、EFをに設定してNoTracking、最初のクエリのパフォーマンスを向上させることができるという結論に達しました。私たちが行ったことはNoTracking、データベースから取得したレコードごとに、同じキーを持っている場合でも、個別のオブジェクトを作成するようにEFに指示することでした。クエリにステートメントがある場合、これにより追加の処理が発生.Include()し、はるかに大きなサイズのデータ​​が返されます。

データが非常に大きいため、簡単に自問することができます-クエリを高速化した場合でも、オプションを使用して本当に原因を解決できましたか(ステートメントNoTrackingの数によっては、最初の1つだけでした。後続のクエリでは、オプションがないためです。複数のステートメントを使用すると、データがサーバーから返されるときにオプションによってより多くのオブジェクトが作成されるため、より高速に実行されます)?.Include()NoTracking.Include()NoTracking

最大の問題は、この量のデータを効率的にシリアル化し、クライアントで逆シリアル化する方法です。シリアル化はすでに同じくらい遅いので(EF 4.xで生成されたPOCOをクライアントに送信しているためにsetで使用DataContractSerializerしています)、さらに多くのデータを生成したいですか(のおかげで)?正直なところ、クライアント側に到達するを介して取得されたナビゲーションプロパティを含まない〜11.000オブジェクトのオプションを使用したクエリから発生したデータはまだ見ていません。前回これを実行しようとしたときに、00:10:00のタイムアウトがトリガーされました(!)PreserveObjectReferencestrueNoTrackingNoTracking.Include()

それで、あなたがまだこのテキストの壁を読んでいるなら、あなたはこの状況を解決する方法を私に教えてください。許容できる結果を達成するために使用するシリアライザーはどれですか?現在、このオプションを使用しない場合、ローカルマシンでのカスタムバインディングのようにNoTracking、最大​​11.000のシリアル化、転送、および逆シリアル化にwsHttpBinding約5秒かかります。私にとって怖いのは、この大きなテーブルには、最終的には最大500.000レコードが含まれる可能性が高いということです。

4

3 に答える 3

3

オブジェクトのビュー モデルを作成し、select ステートメントでプロジェクションを実行することを検討しましたか。それははるかに高速になるはずです:

 var result = from person in DB.Entities.Persons
    .Include("District")
    .Include("District.City")
    .Include("District.City.State")
    .Include("Nationality")
    select new PersonViewModel()
    {
        Name = person.Name, 
        City = person.District.City, 
        State = person.District.City.State
        Nationality = person.Nationality.Name
    };

これには、ViewModel クラスを作成して、PersonViewModel のフラット化されたデータを保持する必要があります。

データベース ビューを作成し、Entity Framework がそこから直接選択できるようにすることで、さらに高速化できる場合があります。

フロントエンドでグリッドに 500.000 レコードを入力する必要がある場合は、Web サービス レイヤーを完全に削除し、DataReader を使用してプロセスを高速化します。Entity Framework と WCF は、適切なパフォーマンスでデータを変換するのには適していません。ここで基本的に行っていることは次のとおりです。

データベース -> TDS -> .NET オブジェクト -> XML -> プレーン テキスト -> XML -> .NET オブジェクト -> UI

これは次のように簡単に削減できますが、

データベース -> TDS -> UI

次に、EntityFramwork を使用して、ビジネス ロジック内のエンティティへの変更を処理します。これは、コマンドとクエリの分離パターンに沿っています。データの高性能クエリに適したテクノロジを使用し、それをアプリに直接リンクします。次に、コマンド戦略を使用してビジネス ロジックを実装します。

また、OData サービスは、UI をデータに直接リンクするためのより良い方法を提供する場合もあります。これは、ユーザーが気付かないうちに迅速なフィルタリングを実装できるように、データをすばやくクエリするために使用できるためです。

セキュリティ設定で、OData を介した直接クエリまたは SQL データベースへの直接アクセスが禁止されている場合は、オブジェクトを自分で実体化することを検討してください。ビューまたはクエリから直接データを選択し、を使用しIDataReaderて ViewModel に直接入力します。それはおそらくあなたに最高のパフォーマンスを提供します。

特に EF は大規模なデータセットに適していないため、Entity Framework に代わる多くの方法が作成されています。FluentData DapperDotNetMassiveまたはPetaPocoを参照してください。これらをエンティティ フレームワークと並べて使用して、大規模でフラットなデータ クエリを処理することができます。

于 2012-04-04T19:33:02.143 に答える
0

私はRIAアプリケーションでJson.NetのBsonの実装を使用しています。詳細はこちら。

データベースから読み取り、行をシリアル化すると、IEnumerableが返されます。速度は許容範囲内であることがわかり、約20のプロパティを持つエンティティを返します。このアプローチでは、サーバーでの同時メモリ使用を最小限に抑える必要があります。

于 2012-04-04T19:40:33.023 に答える
0

さまざまなレビューとパフォーマンス ベンチマークを調べて収集したものに基づいて、protobuf-netをシリアライザーとして選択します。サービス構成にプラグインできるかどうかは設計の問題です。詳細については、こちらをご覧ください。

この質問に対する完全な回答ではありませんが、jessehouwingが最良の回答をしたので、承認済みとしてマークします。

于 2012-04-07T07:02:29.073 に答える