2

私はEntityFramework4(データベースファースト)を使用して映画データベースアプリに取り組んでおり、リストに約8,200行をロードするのに30秒かかります。関連するテーブルは3つあり、.Include()を使用すると、パフォーマンスがさらに低下します。8,200行をロードするのに約3分かかります。これは苦痛です。一度にたくさんのテクノロジーを学んでいることを考えると、簡単な修正があることを望んでいます。詳細は次のとおりです。

表1-ビデオ

これは、約7,800行のビデオについて31列の大きなテーブルです。主キーとしてGuidを使用します。

表2-ActorsVideos(ジャンクションテーブル)

このテーブルには、(1)VideoID列と(2)ActorID列の2つの列があります。両方の列はGUIDであり、それぞれVideoテーブルとActorテーブルへの外部キーです。このテーブルは、両方の列が主キーとして機能する複合主キーを使用します。EF4はこのテーブルをモデル化しません。ただし、ナビゲーションプロパティを作成します。このテーブルを使用すると、ユーザーは任意の数の俳優を映画に割り当てることができます。

表3-アクター

約400行の16列があります。繰り返しますが、主キーはGuidです。

コードでは、Videosテーブルの約10列を読み取ってから、関連するActorsテーブルの列を読み取ります。

C#コードは次のようになります。

var videos = context.Videos
foreach (var video in videos)
{
    // retrieve 10 or so properties from 'video'

    if (video.Actors.Count > 0)
    {
        foreach (var actor in video.Actors)
        {
            // retrieve some properties on the actor
        }
    }
}

context.Videosの後に.Include( "Actors")を追加してみましたが、前述のように、パフォーマンスはひどいものから恐ろしいものになりました。

インクルードで生成されるSQLを見てきましたが、ビデオテーブルにある列の数を考えると、約2Kのテキストです。

マスター/詳細パターンを使用してビデオテーブルを分割する必要がありますか?次のステップは、actorsテーブルをキャッシュし、navigation/associationプロパティを完全に回避することです。これを高速化するための他の提案はありますか?私の意見では、5〜6秒以内に実行されるはずです。

編集:データベースはSQL ServerCE3.5です。

4

2 に答える 2

3

Entity Frameworkに、そのすべてのアクターと一緒にビデオをロードするように要求し、次にアプリケーションコードでフィルタリングを実行します。一般的に、必要以上のデータを取得しています。SQL Server(または使用しているDB)を事前にフィルター処理します。

var videos = context.Videos;
var results = from video in videos
              where video.Actors.count > 10
              group video.Actors by video.VideoID into grouping
          select new
          {
              video.VideoID,
              video.Actors
          };

foreach (var group in results)
{
    foreach (var actor in group.Actors)
    {
        // do stuff
    }
}

ビデオテーブルの関連する行とともに、最大8200行の読み込みは非常に高速である必要があります。私は自分の仕事でいくつかの開発を行い、5テーブル結合で7000万行以上のテストデータテーブルを処理する必要がありました。これは30分ほどで実行されました。

しかし、それがあなたがしていることよりもはるかに速く実行された理由は、私がSQLServerの内部でフィルタリングしていたからです。EFを使用する同等の「手続き型」プログラムは、データベースから行をプルした後にフィルタリングを行っていたため、数分かかりました。

このように考えてください。データベース内のすべての行を要求するだけでなく、何度も実行する必要のないデータを取得することになります

于 2012-07-13T01:06:58.680 に答える
0

積極的な読み込みを使用してみてください:

var videos = context.Videos.Include(v=>v.Actors);
foreach (var video in videos)
{
    foreach (var actor in video.Actors)
    {
    }
}

:クエリは遅延実行を使用することに注意してください。つまり、複数回繰り返すと、クエリも複数回実行されます。複数回繰り返す場合は、繰り返す.AsEnumerable()前にローカルで使用して割り当てます。また、データベースをプロファイリングして実行されているクエリを確認すると、他に何を熱心にフェッチする必要があるかを判断するのに役立ちます。EFに不要なエンティティをロードさせている可能性があります。その場合、クエリは必要なデータのみを(使用してSelect(x=> new {...stuff you need... }))投影する必要があります。

編集: MicrosoftによるとInclude()、プロジェクションと組み合わせることはできないため、その場合は別の方法でクエリを作成する必要があります。

于 2012-07-13T00:56:11.500 に答える