Entity Framework – Performanz mit Compiled Query

Um im Entity Framework die Performanz verbessern zu können, besteht seit EF 1 die Möglichkeit der kompilierten Abfrage. Dieser Ansatz lohnt sich bei komplexen Abfragen, da der Expression Tree nicht jedes Mal abgearbeitet wird, um daraus das SQL-Statement zu generieren. Alternativ dazu kann auch eSQL oder im EF 4 ExecuteStoreQuery genutzt werden. Was mit dieser Funktionalität nicht erreicht werden kann, die Datenbank – SQL Server oder Oracle – kann die Abfrage nicht schneller oder besser ausführen.

Zum Beispiel könnte eine Abfrage so aussehen:

C#
public List<Mandator> GetMandatorsWithBusinessUnits()
{
    int minCount = 10;

    var result = from m in this.Mandators.Include("BusinessUnits")
                 where m.BusinessUnits.Count > minCount
                 select m;

    return result.ToList();
}

In meinem Beispiel sieht das SQL-Statement dazu folgendermassen aus:

T-SQL
exec sp_executesql N'SELECT 
[Project2].[maAutoID] AS [maAutoID], 
[Project2].[maName] AS [maName], 
[Project2].[maSubDirectory] AS [maSubDirectory], 
[Project2].[maBKBeforeRBK] AS [maBKBeforeRBK], 
[Project2].[maBKPercent] AS [maBKPercent], 
[Project2].[maImprint] AS [maImprint], 
[Project2].[maPhone] AS [maPhone], 
[Project2].[maStreet] AS [maStreet], 
[Project2].[maPOBox] AS [maPOBox], 
[Project2].[maPC] AS [maPC], 
[Project2].[maCity] AS [maCity], 
[Project2].[maURL] AS [maURL], 
[Project2].[maVendorAccount] AS [maVendorAccount], 
[Project2].[maAccountingCostCenter1] AS [maAccountingCostCenter1], 
[Project2].[maAccountingCostCenter2] AS [maAccountingCostCenter2], 
[Project2].[C1] AS [C1], 
[Project2].[buAutoID] AS [buAutoID], 
[Project2].[buMandatorAutoID] AS [buMandatorAutoID], 
[Project2].[buName] AS [buName], 
[Project2].[buInactive] AS [buInactive]
FROM ( SELECT 
	[Project1].[maAutoID] AS [maAutoID], 
	[Project1].[maName] AS [maName], 
	[Project1].[maSubDirectory] AS [maSubDirectory], 
	[Project1].[maBKBeforeRBK] AS [maBKBeforeRBK], 
	[Project1].[maBKPercent] AS [maBKPercent], 
	[Project1].[maImprint] AS [maImprint], 
	[Project1].[maPhone] AS [maPhone], 
	[Project1].[maStreet] AS [maStreet], 
	[Project1].[maPOBox] AS [maPOBox], 
	[Project1].[maPC] AS [maPC], 
	[Project1].[maCity] AS [maCity], 
	[Project1].[maURL] AS [maURL], 
	[Project1].[maVendorAccount] AS [maVendorAccount], 
	[Project1].[maAccountingCostCenter1] AS [maAccountingCostCenter1], 
	[Project1].[maAccountingCostCenter2] AS [maAccountingCostCenter2], 
	[Extent3].[buAutoID] AS [buAutoID], 
	[Extent3].[buMandatorAutoID] AS [buMandatorAutoID], 
	[Extent3].[buName] AS [buName], 
	[Extent3].[buInactive] AS [buInactive], 
	CASE WHEN ([Extent3].[buAutoID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
	FROM   (SELECT 
		[Extent1].[maAutoID] AS [maAutoID], 
		[Extent1].[maName] AS [maName], 
		[Extent1].[maSubDirectory] AS [maSubDirectory], 
		[Extent1].[maBKBeforeRBK] AS [maBKBeforeRBK], 
		[Extent1].[maBKPercent] AS [maBKPercent], 
		[Extent1].[maImprint] AS [maImprint], 
		[Extent1].[maPhone] AS [maPhone], 
		[Extent1].[maStreet] AS [maStreet], 
		[Extent1].[maPOBox] AS [maPOBox], 
		[Extent1].[maPC] AS [maPC], 
		[Extent1].[maCity] AS [maCity], 
		[Extent1].[maURL] AS [maURL], 
		[Extent1].[maVendorAccount] AS [maVendorAccount], 
		[Extent1].[maAccountingCostCenter1] AS [maAccountingCostCenter1], 
		[Extent1].[maAccountingCostCenter2] AS [maAccountingCostCenter2], 
		(SELECT 
			COUNT(1) AS [A1]
			FROM [dbo].[tbBusinessUnit] AS [Extent2]
			WHERE [Extent1].[maAutoID] = [Extent2].[buMandatorAutoID]) AS [C1]
		FROM [dbo].[tbMandator] AS [Extent1] ) AS [Project1]
	LEFT OUTER JOIN [dbo].[tbBusinessUnit] AS [Extent3] ON [Project1].[maAutoID] = [Extent3].[buMandatorAutoID]
	WHERE [Project1].[C1] > @p__linq__0
)  AS [Project2]
ORDER BY [Project2].[maAutoID] ASC, [Project2].[C1] ASC',N'@p__linq__0 int',@p__linq__0=10

Wenn Abfragen in dieser Form sehr häufig ausgeführt werden, kann der Einsatz der kompilierten Abfragen etwas bringen.

Der Code erfordert eine Anpassung, damit der Expression Tree nur einmal ausgewertet wird. Hierbei gefällt mir der Aufwand nicht, da es negative Auswirkungen auf die Lesbarkeit des Codes hat. 

C#
private static Func<ContentEntities, int, IQueryable<Mandator>> COMPILEDMANDATOR;

public List<Mandator> GetMandatorsWithBusinessUnitsCompiled()
{
    int minCount = 10;

    if (COMPILEDMANDATOR == null)
    {
        COMPILEDMANDATOR = CompiledQuery.Compile<ContentEntities, int, IQueryable<Mandator>>(
            (ctx, minCountParameter) => from m in ctx.Mandators.Include("BusinessUnits")
                        where m.BusinessUnits.Count > minCountParameter
                        select m);
    }

    return COMPILEDMANDATOR.Invoke(this, minCount).ToList();
}

Diese Form der Abfrage braucht ein geübtes Auge, jedoch wird das Ziel erreicht, wenn die statische Variable deklariert ist, wird der Expression Tree nicht mehr ausgewertet.

Wie bereits erwähnt, kann dieses Feature keine Verbesserungen auf Seite der Datenbank bewirken, wenn das Problem also beim generierten SQL-Statement liegt, wird dieses Feature keine Verbesserung bringen.

  •  
  • 0 Kommentar(e)
  •  

Mein Kommentar

Über jeden weiteren Kommentar in diesem Post benachrichtigen.

Zurück

Translate this page

Kategorien

  • [-].NET Development (215)
  • [-]Datenbank (26)
  • HTML (1)
  • Konfiguration (12)
  • Mind Map (10)
  • Off-topic (9)
  • Open Source (3)
  • Qualität (7)
  • Sharepoint (6)
  • Sicherheit (2)

Archiv

Social Bookmarking

Bookmark bei: Mr. Wong Bookmark bei: Webnews Bookmark bei: Icio Bookmark bei: Oneview Bookmark bei: Linkarena Bookmark bei: Favoriten Bookmark bei: Seekxl Bookmark bei: Favit Bookmark bei: Social Bookmarking Tool Bookmark bei: Power Oldie Bookmark bei: Bookmarks.cc Bookmark bei: Newskick Bookmark bei: Newsider Bookmark bei: Linksilo Bookmark bei: Readster Bookmark bei: Folkd Bookmark bei: Yigg Bookmark bei: Digg Bookmark bei: Del.icio.us Bookmark bei: Reddit Bookmark bei: Simpy Bookmark bei: StumbleUpon Bookmark bei: Slashdot Bookmark bei: Netscape Bookmark bei: Furl Bookmark bei: Yahoo Bookmark bei: Spurl Bookmark bei: Google Bookmark bei: Blinklist Bookmark bei: Blogmarks Bookmark bei: Diigo Bookmark bei: Technorati Bookmark bei: Newsvine Bookmark bei: Blinkbits Bookmark bei: Ma.Gnolia Bookmark bei: Smarking Bookmark bei: Netvouz Information