[英]How to work around slow joining queries in Entity Framework
我有一個MVC 4項目,該項目正在使用Code First和Entity Framework 6(由SQL Server 2008支持)。 我正在嘗試優化一個看起來像這樣的特別討厭的查詢:
var tops = Context.Top
.Include(t =>
t.Foo
.Select(f => f.FooChild1
.Select(c => c.Baz)))
.Include(t =>
t.Foo
.Select(f => f.FooChild3))
.Include(t =>
t.Foo
.Select(f => f.FooChild2))
.Include(t =>
t.Foo
.Select(f => f.FooChild1
.Select(c => c.Bar)))
.Where(t => t.Foo.Count > 0)
.ToList();
關系如下所示:
Top
1 ----> 0..N Foo
1 ----> 0..N FooChild1
1 ----> 0..N Bar
1 ----> 0..N Baz
1 ----> 0..N FooChild2
0..N ----> 1 FooChild3
如您所見,該查詢需要大量的加載,因此生成的查詢具有大量的聯接。 事實證明,對於我正在處理的結果數據,延遲加載太慢了。
在SQL Server上執行此查詢所生成的查詢大約需要2秒鍾,但是獲取我需要的數據的手寫查詢僅需要大約91毫秒。 有什么我可以做來改善的嗎?
我嘗試過的
我嘗試通過在需要的所有其他表上調用Load()
並擺脫所有Include
的方法來進行預加載。 我不確定為什么(也許這個技巧不適用於DbContext
),但是沒有效果。 導航屬性是延遲加載的。
我在考慮什么
我想到的一個選擇是手寫一個查詢所需數據的SQL視圖,並在Code First中將一個實體映射到該視圖。 不知道如何確切地做到這一點,但是我希望這樣做可以避免所生成查詢中的不良性能。
修改數據庫的設計,以便將我需要的信息緩存在Top
表中。 我不喜歡此選項中的數據重復,但是至少我不必遍歷那么多的導航屬性。
有指針嗎?
您可以使用預編譯查詢來提高性能。 諸如此類(來自msdn的示例,原因是我不知道您的類型):
static readonly Func<AdventureWorksEntities, Decimal, IQueryable<SalesOrderHeader>> s_compiledQuery2 =
CompiledQuery.Compile<AdventureWorksEntities, Decimal, IQueryable<SalesOrderHeader>>(
(ctx, total) => from order in ctx.SalesOrderHeaders
where order.TotalDue >= total
select order);
static void CompiledQuery2()
{
using (AdventureWorksEntities context = new AdventureWorksEntities())
{
Decimal totalDue = 200.00M;
IQueryable<SalesOrderHeader> orders = s_compiledQuery2.Invoke(context, totalDue);
foreach (SalesOrderHeader order in orders)
{
Console.WriteLine("ID: {0} Order date: {1} Total due: {2}",
order.SalesOrderID,
order.OrderDate,
order.TotalDue);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.