パフォーマンスの問題で多くの検索を行い、さまざまなことを試しましたが、十分に速く動作するようには見えません。ここで私の問題は、最も単純なフォームです:CodeFirst読み込み1親が25,000人の子供にリンクされています
私はエンティティフレームワーク5を使用しています。私は、その親を選択したときに親の子インスタンスを遅延読み込みできるようにしたいので、全体をプルする必要はありませんデータベース。しかし、私は、子供の怠惰な読み込みでパフォーマンスの問題を抱えています。問題は、親と子の間のナビゲーションプロパティのアップです。私はこれが単純なケースだと信じているので、間違っていたものでなければならないと考えています。
私は問題を特定するために単一の遅延ロードをテストするプログラムを用意しました。ここで
はテストです:
私はPOCOの親クラスを作成し、子POCOクラス。親はn子供と子供は1親を持っています。 SQL Serverデータベースには1つのみの親があり、その単一の親には25,000の子があります。私はこのデータを読み込むためにさまざまな方法を試しました。同じDbContextで子と親のどちらかをロードすると、本当に時間がかかります。しかし、それらを異なるDbContextにロードすると、本当に高速にロードされます。しかし、それらのインスタンスを同じDbContextにしたい。ここで
は私のテスト・セットアップとあなたがそれを複製するために必要なすべてです:
POCOS:
public class Parent
{
public int ParentId { get; set; }
public string Name { get; set; }
public virtual List<Child> Childs { get; set; }
}
public class Child
{
public int ChildId { get; set; }
public int ParentId { get; set; }
public string Name { get; set; }
public virtual Parent Parent { get; set; }
}
DbContext:
public class Entities : DbContext
{
public DbSet<Parent> Parents { get; set; }
public DbSet<Child> Childs { get; set; }
}
TSQLスクリプトを作成しますデーターベースASEとデータ:
USE [master]
GO
IF EXISTS(SELECT name FROM sys.databases
WHERE name = 'PerformanceParentChild')
alter database [PerformanceParentChild] set single_user with rollback immediate
DROP DATABASE [PerformanceParentChild]
GO
CREATE DATABASE [PerformanceParentChild]
GO
USE [PerformanceParentChild]
GO
BEGIN TRAN T1;
SET NOCOUNT ON
CREATE TABLE [dbo].[Parents]
(
[ParentId] [int] CONSTRAINT PK_Parents PRIMARY KEY,
[Name] [nvarchar](200) NULL
)
GO
CREATE TABLE [dbo].[Children]
(
[ChildId] [int] CONSTRAINT PK_Children PRIMARY KEY,
[ParentId] [int] NOT NULL,
[Name] [nvarchar](200) NULL
)
GO
INSERT INTO Parents (ParentId, Name)
VALUES (1, 'Parent')
DECLARE @nbChildren int;
DECLARE @childId int;
SET @nbChildren = 25000;
SET @childId = 0;
WHILE @childId < @nbChildren
BEGIN
SET @childId = @childId + 1;
INSERT INTO [dbo].[Children] (ChildId, ParentId, Name)
VALUES (@childId, 1, 'Child #' + convert(nvarchar(5), @childId))
END
CREATE NONCLUSTERED INDEX [IX_ParentId] ON [dbo].[Children]
(
[ParentId] ASC
)
GO
ALTER TABLE [dbo].[Children] ADD CONSTRAINT [FK_Children.Parents_ParentId] FOREIGN KEY([ParentId])
REFERENCES [dbo].[Parents] ([ParentId])
GO
COMMIT TRAN T1;
アプリケーション。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add
name="Entities"
providerName="System.Data.SqlClient"
connectionString="Server=localhost;Database=PerformanceParentChild;Trusted_Connection=true;"/>
</connectionStrings>
</configuration>
テストコンソールクラス:ここ
class Program
{
static void Main(string[] args)
{
List<Parent> parents;
List<Child> children;
Entities entities;
DateTime before;
TimeSpan childrenLoadElapsed;
TimeSpan parentLoadElapsed;
using (entities = new Entities())
{
before = DateTime.Now;
parents = entities.Parents.ToList();
parentLoadElapsed = DateTime.Now - before;
System.Diagnostics.Debug.WriteLine("Load only the parent from DbSet:" + parentLoadElapsed.TotalSeconds + " seconds");
}
using (entities = new Entities())
{
before = DateTime.Now;
children = entities.Childs.ToList();
childrenLoadElapsed = DateTime.Now - before;
System.Diagnostics.Debug.WriteLine("Load only the children from DbSet:" + childrenLoadElapsed.TotalSeconds + " seconds");
}
using (entities = new Entities())
{
before = DateTime.Now;
parents = entities.Parents.ToList();
parentLoadElapsed = DateTime.Now - before;
before = DateTime.Now;
children = entities.Childs.ToList();
childrenLoadElapsed = DateTime.Now - before;
System.Diagnostics.Debug.WriteLine("Load the parent from DbSet:" + parentLoadElapsed.TotalSeconds + " seconds" +
", then load the children from DbSet:" + childrenLoadElapsed.TotalSeconds + " seconds");
}
using (entities = new Entities())
{
before = DateTime.Now;
children = entities.Childs.ToList();
childrenLoadElapsed = DateTime.Now - before;
before = DateTime.Now;
parents = entities.Parents.ToList();
parentLoadElapsed = DateTime.Now - before;
System.Diagnostics.Debug.WriteLine("Load the children from DbSet:" + childrenLoadElapsed.TotalSeconds + " seconds" +
", then load the parent from DbSet:" + parentLoadElapsed.TotalSeconds + " seconds");
}
using (entities = new Entities())
{
before = DateTime.Now;
parents = entities.Parents.ToList();
parentLoadElapsed = DateTime.Now - before;
before = DateTime.Now;
children = parents[0].Childs;
childrenLoadElapsed = DateTime.Now - before;
System.Diagnostics.Debug.WriteLine("Load the parent from DbSet:" + parentLoadElapsed.TotalSeconds + " seconds" +
", then load the children from Parent's lazy loaded navigation property:" + childrenLoadElapsed.TotalSeconds + " seconds");
}
using (entities = new Entities())
{
before = DateTime.Now;
parents = entities.Parents.Include(p => p.Childs).ToList();
parentLoadElapsed = DateTime.Now - before;
System.Diagnostics.Debug.WriteLine("Load the parent from DbSet and children from include:" + parentLoadElapsed.TotalSeconds + " seconds");
}
using (entities = new Entities())
{
entities.Configuration.ProxyCreationEnabled = false;
entities.Configuration.AutoDetectChangesEnabled = false;
entities.Configuration.LazyLoadingEnabled = false;
entities.Configuration.ValidateOnSaveEnabled = false;
before = DateTime.Now;
parents = entities.Parents.Include(p => p.Childs).ToList();
parentLoadElapsed = DateTime.Now - before;
System.Diagnostics.Debug.WriteLine("Load the parent from DbSet and children from include:" + parentLoadElapsed.TotalSeconds + " seconds with everything turned off");
}
}
}
は、これらのテストの結果は次のとおりです。DbSetから親だけ
ロード:0972秒の接続文字列を含む設定
DbSetからの子のみをロード:0,714秒onds
ロードDbSetから親:8,6026秒
ロードDbSetから子供:0,6864秒、その後、DbSetから親をロード:7,5816159 0001秒は、その後、DbSetから子どもを読み込みます秒
ロードDbSetから親:0秒、その後、親の遅延ロードされたナビゲーションプロパティから子供をロード:8,5644549秒
ロードDbSetとから子供から親が含まれます:8,6428788秒を
Loa DからDbSetと子供から親は、次のとおりです。すべてと9,1416586秒は、親と子供が同じDbContextであるときはいつでも、それは(9秒)長い時間がかかる
分析
をオフにすべてを結ぶ。私はプロキシの作成から遅延ロードまでのすべてを無効にしようとしましたが、無駄にしました。誰か助けてくれますか?
+1:大きな質問と分析! – Slauma