0

Activity7 種類ほどの異なるモデルからモデルを取り込むモデルがあります。これらのモデルにも関係があり、必要な情報をアクティビティ フィードで表示できるようにする必要があります。これは、クエリに約 20 個のインクルードがあることを意味します。私はこれを8か月ほどしか行っていませんが、コンパイルされたクエリ、ストアドプロシージャ、およびそれらすべてのインクルードがおそらく私を殺している方法について読んだことがあります. また、遅延読み込みができるようにコード ファースト モデルを変更できることも読みましたvirtualが、大量のユーザーを獲得した場合、これらすべてのデータベース呼び出しによってサイトが停止するのではないかと心配しています。

まずはモデル

public class Activity
{
    public int ActivityID { get; set; }
    public int ActivityTypeID { get; set; }
    public int ContributorID { get; set; }
    public int UserID { get; set; }
    public int? ProjectID { get; set; }
    public int? ProjectDocID { get; set; }
    public int? CommentID { get; set; }
    public int? BookID { get; set; }
    public int? BookReviewID { get; set; }
    public DateTime DateCreated { get; set; }
    public Comment Comment { get; set; }
    public ProjectDoc ProjectDoc { get; set; }
    public Project Project { get; set; }
    public Book Book { get; set; }
    public BookReview BookReview { get; set; }
    public ActivityType ActivityType { get; set; }
    [ForeignKey("ContributorID")]
    public User Contributor { get; set; }
    [ForeignKey("UserID")]
    public User User { get; set; }
    public ICollection<ActivityLike> ActivityLike { get; set; }
    public ICollection<ActivityComment> ActivityComment { get; set; }
}

今、クエリ

 var activity = db.Activities
                .Include(i => i.Contributor.BookStatus)
                .Include(i => i.ActivityType)
                .Include(i => i.ActivityLike.Select(y => y.User))
                .Include(i => i.ActivityComment.Select(y => y.User))
                .Include(i => i.Project.ProjectFollower)
                .Include(i => i.Project.View)
                .Include(i => i.Project.ProjectType)
                .Include(i => i.Project.User)
                .Include(i => i.Project.ProjectTag.Select(v => v.Tag))
                .Include(i => i.Project.ProjectCategory.Select(v => v.Category))
                .Include(i => i.Project.ProjectCharacteristic.Select(v => v.Characteristic))
                .Include(i => i.Project.ProjectDoc.Select(v => v.ProjectDocVote))
                .Include(i => i.Project.ProjectDoc.Select(v => v.User))
                .Include(i => i.Comment.User)
                .Include(i => i.Book.Author)
                .Include(i => i.Book.BookReview.Select(v => v.User))
                .Include(i => i.Book.BookReview.Select(v => v.BookReviewVote))
                .Include(i => i.Book.BookCharacteristic.Select(v => v.Characteristic))
                .Include(i => i.Contributor.Followers)
                .Where(u =>
                    u.Contributor.Followers.FirstOrDefault(x => x.FollowerID == WebSecurity.CurrentUserId) != null
                )
                .OrderByDescending(d => d.DateCreated)
                .Skip(offset)
                .Take(results)
                .ToList();

これは最終的に 6600 行の SQL (またはそれが何であれ) のようになります。

これを初めて実行するときは、10 ~ 16 秒かかります。またSkip()、jquery で無限スクロールを使用しているため、最初の ajax 呼び出しごとに 10 ~ 12 秒かかります。したがって、一度に 10 件の結果が得られ、100 件の結果がある場合、100 秒を超える待機時間になります。これはひどいことです。次にユーザーがそのページに短時間でアクセスするときは、非常に迅速です。

では、このクエリをどのように改善すればよいのでしょうか。また、コンパイルされたクエリとそうでないものを理解するのが難しいため、具体的にその方法を提供して解決策を説明していただけますか。私がここまでたどり着くことができた唯一の理由は、EF によって簡単になったからです...これには明らかにコストがかかります。

用語の誤用をご容赦ください。

4

3 に答える 3

0

遅延読み込みに切り替えることにしました。これにより、読み込み時間が 70% 短縮されました。データベースの往復が増えるため、これは理想的ではないことはわかっていますが、サイトが大きくなった場合は心配になります。理想的ではありませんが、最初はパフォーマンスの方が心配です。要約すると、私は次のことを行いました

virtualナビゲーション プロパティに追加されました。非常に重みのあるクエリのほぼすべてのインクルードを削除しました

結果は、15 秒ではなく 2.5 秒の読み込み時間でした (SQL プロファイラーではなくブラウザーのタイムラインに基づく)。

于 2013-06-10T16:01:27.023 に答える
0

私の提案:

  1. データベースのインデックスが適切に調整されていることを確認してください。適切なインデックスを作成せずに結合すると、クエリ SQL の生成方法に関係なく、パフォーマンスが低下する可能性があります。SQL Server を使用している場合、これはデータベース エンジン チューニング アドバイザーで簡単に実行できます。まず、一般的な規則として、外部キー列にはインデックスを作成する必要があります。
  2. このクリティカル パス クエリをプレーンな古い SQL で記述することを検討してください。Entity Framework に取り組んだ短い時間で、かなりの数のトリックを習得しました。おそらく、これまでに行ったことを最適化する方法があると思いますが、これをスピードアップする確実な方法は次のとおりです。 up は ORM レイヤーをバイパスすることです。
于 2013-06-07T05:58:53.700 に答える
-1

私のプロジェクトでは、EFを使用するためのリポジトリを作成したので、次のように書きました

  public IQueryable<Company> Companies
    {
        get
        {
            return context.Companies.Include("BankAccounts").Include("CompanyContacts").Include("MyClients").Include("MyCompanies").Include("Address");
        }
    }

そして今、コード内のどこでも会社をインクルードせずに呼び出すことができます。

CompanyRepository comrep = new CompanyRepository();
var companies = comrep.Companies(c=>c.FullName == "Made in Azerbaijan").SingleOrDefault();

これがお役に立てば幸いです

于 2013-06-07T05:40:08.417 に答える