Entity Framework 4 – Generiertes SQL besser, aber nicht immer (Engpass TPT)

Während unserer Vorbereitungen auf die ORM Präsentation, habe ich für die Beispiele der Vererbungsstrategien Table per hierarchy (TPH), Table per type (TPT) und Table per conrete class (TPC) natürlich den SQL-Profiler laufen lassen.

Im Netz gibt es für die TPT-Strategie genügend Beispiele, die die Performanceschwachpunkte im Entity Framework darstellen. Die Zeitmessungen gehen dabei aber so gut wie gar nicht auf die Ressourcen ein, welche die Datenbank für sich beansprucht. Als Grund für die Wahl von TPT wird häufig auch die Ästhetik angeführt, weil diese sich wie OO anfühlt. Genau hier greift der ORM impedance mismatch und vermutlich die Folge des Versprechens, dass man mit ORM kein SQL beherrschen muss, darunter gehört auch wie ein RDBMS funktioniert.

Ein vernünftiges Argument für TPT ist bspw. die Releasetauglichkeit bei Standardlösungen, damit Individualerweiterungen den Kern der Anwendung nicht negativ beeinflussen.

Hinzu kommt zurzeit auch die Tatsache, dass das generierte SQL bei TPT suboptimal ist.

Aus diesem Grund bevorzuge ich, wenn möglich die TPH-Strategie, da diese bei Performanzüberlegungen die bessere Alternative darstellt. Auf dem Blog vom ADO.NET-Team gibt es zudem einen Blogbeitrag mit dem Versprechen, das generierte SQL für TPT zu verbessern, aber auch mit diesen Verbesserungen bleibt TPH für die Datenbank ressourcenschonender.

Bei TPH ist das generierte SQL gelegentlich redundant. Bezogen auf unserem Beispiel, haben wir folgende Vererbungshierarchie, die in der Datenbank innerhalb einer Tabelle gespeichert werden.

Abbildung 1
Abbildung 1 Vererbungshierarchie der Entities

Dieses Beispiel existiert in den Formen TPH, TPT und TPC. In einen Test frage ich ab, wie viele Bücher existieren. Dafür erzeugt die folgende Linq-Abfrage:

C# (Linq)
using (var ctx = new ORMSamplesEntities())
{
    var count = ctx.Products.OfType<Book>().Count();
    Assert.AreEqual(2, count);
 }

je nach Strategie folgende SQL-Abfragen

T-SQL bei TPH
SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
	COUNT(1) AS [A1]
	FROM [TablePerHierarchie].[Product] AS [Extent1]
	WHERE ([Extent1].[ProductTypeNbr] IN ( CAST( '1' AS int), CAST( '2' AS int))) AND ([Extent1].[ProductTypeNbr] IN (1,2))
)  AS [GroupBy1]

In diesem Beispiel ist ersichtlich, dass die Diskriminator-Spalte 2 -mal gefiltert wird. Das ADO.NET – Team kann hier also auch noch Optimierungen vornehmen. ;-)

Bei TPT sieht das erzeugte SQL so aus:

T-SQL bei TPT
SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
	COUNT(1) AS [A1]
	FROM    (SELECT 
		[Extent1].[HardcoverId] AS [HardcoverId]
		FROM [TablePerType].[Hardcover] AS [Extent1]
	UNION ALL
		SELECT 
		[Extent2].[EBookId] AS [EBookId]
		FROM [TablePerType].[EBook] AS [Extent2]) AS [UnionAll1]
	INNER JOIN [TablePerType].[Product] AS [Extent3] ON [UnionAll1].[HardcoverId] = [Extent3].[ProductId]
	INNER JOIN [TablePerType].[Book] AS [Extent4] ON [UnionAll1].[HardcoverId] = [Extent4].[BookId]
)  AS [GroupBy1]

Das Ganze wird hier schon umfangreicher. Handgeschrieben würde ich in diesem Fall nur die Book-Tabelle abfragen und die Platzierung würde anders ausfallen.

Bei TPC wird hingegen folgendes SQL generiert:

T-SQL bei TPC
SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
	COUNT(1) AS [A1]
	FROM  (SELECT 
		1 AS [C0]
		FROM [TablePerClass].[EBook] AS [Extent1]
	UNION ALL
		SELECT 
		1 AS [C0]
		FROM [TablePerClass].[Hardcover] AS [Extent2]) AS [UnionAll1]
)  AS [GroupBy1]

Dieses SQL sieht, den Umständen entsprechend, verständlicher aus.

Bevor wir jetzt die Stoppuhr im Code ansetzen, wäre es zuerst mal interessant zu wissen, welche Ressourcen der Datenbankserver bei der jeweiligen Strategie benötigt, um diesen Faktor besser berücksichtigen zu können. Dafür stellen wir die 3 Abfragen gegenüber und lassen uns den Ausführungsplan anzeigen.

Das Ergebnis überrascht dann eigentlich nicht wirklich:

Abbildung 2
Abbildung 2 Abfragekosten in Relation zur jeweiligen Strategie

Welche Strategie bevorzugt nun unser Datenbankserver in diesem Szenario?

  • Auf Platz 1 TPH (17%)
  • Platz 2 TPC (33%)
  • und auf Platz 3 TPT (50%)

Sollte jetzt die gewählte TPT-Strategie zu starken Performanzengpässen führen, dann wäre eine Migration - unter Berücksichtigung der Nachteile und Einbezug des DBA‘s - zu TPH denkbar. Auf das Entity-Modell würde es faktisch keine Auswirkungen haben.

  •  
  • 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