2009-11-22 4 views
7

Ich habe zwei Abfragen verglichen, die einige ziemlich große Daten aus einer Datenbanktabelle abrufen. Für die Abfrage eins verwendete ich Linq To Sql und für die andere verwende ich Passthrough SQL über ADO.NET.Warum ist Linq To Sql die Datenbindung an Gridview wesentlich langsamer als an Pass-Through-SQL?

Ich weiß, dass Linq To Sql hinter den Kulissen viel arbeiten muss, aber was macht es eigentlich? Die zwei Abfragen rufen die gleiche Menge an Daten ab, aber die Linq To Sql-Abfrage ist mehr als 5 Sekunden langsamer und benötigt 150 MB mehr RAM!

Hier ist mein Testcode:

Mit LINQ to SQL:

public void MakeList() 
    { 
     int start = Environment.TickCount; 
     var document = from d in _dm.tDokuments select d; 

     List<tDokument> documentList = document.ToList(); 
     int end = Environment.TickCount; 

     GridView1.DataSource = documentList; 
     GridView1.DataBind(); 

     Label1.Text = (end - start).ToString(); 
    } 

SQL Pass-Through + ADO.NET:

public void MakeList() 
    { 

     int start = Environment.TickCount; 
     SqlCommand sqlCommand = new SqlCommand("SELECT * FROM tDokument", _connection); 
     SqlDataAdapter da = new SqlDataAdapter(sqlCommand); 

     DataSet ds = new DataSet(); 
     da.Fill(ds); 
     int end = Environment.TickCount; 

     GridView1.DataSource = ds; 
     GridView1.DataBind(); 

     Label1.Text = (end - start).ToString(); 
    } 
+2

Haben Sie dies getestet, wenn der Prozess nicht mit dem Debugger verbunden ist? –

+0

Ich habe ähnliche Probleme mit NHibernate gefunden. Ich bin nicht sicher, was ist das große Seceret "hinter dem Bildschirm", aber ich denke, ORM-Tools sind langsam .... – Dani

+1

@Dani - "ORM-Tools sind langsam" folgt nicht aus Databinding-Performance-Studien. Das ist eine sehr allgemeine (und irreführende) Erklärung. – TrueWill

Antwort

8

Linq2Sql kehrt Objekte stark typisiert, wo, wie der Datensatz mit bevölkert wird immer was zu einem wesentlichen Mengen Hash-tabelle.

In Linq verwendet die Population der Daten und die Bindung dieser Daten an eine GridView viel Reflexion, um die gewünschten Ergebnisse zu generieren.

Im zweiten Teil des Codes werden die Daten in ein Dataset geladen und an ein GridView gebunden. Dies bedeutet im Wesentlichen das Laden einer Hashtabelle mit Daten und Suchen zum Binden.

Hashtable-Operationen werden immer schneller sein als Reflektionen. Mit einer kleinen Menge an Daten wird es keinen bemerkbaren Unterschied geben, aber für viele Daten werden Sie die Auswirkungen von Reflektion in Linq sehen.

+0

Vielen Dank für Ihre Antwort. Ich brauche eine Antwort tho. Was ist Reflexion? – Poku

+1

Reflexion ist das Verfahren, um die Eigenschaften, Methoden, Ereignisse eines Objekts oder Typs programmatisch zu ermitteln. Überprüfen Sie den System.Reflection-Namespace in MSDN. Dies muss Linq tun, um die Werte, die von der Abfrage zurückgegeben werden, den Eigenschaften des tDokument-Objekts zuzuweisen. Es ist viel langsamer als direkte Eigenschaft Zuweisung. – Jason

4

Haben Sie bei der aktuellen SQL sah gesendet werden SQL Server mit Profiler?

In diesem Fall vermute ich, es ist, wie der Client es behandelt (DataSet vs List), die den Unterschied verursacht, aber ich bin nirgends in der Nähe eines C# -Experten.

+0

Der Dataset wird mehr Overhead zugeordnet als die generische Liste, also sollte dies nicht das Problem sein. – Jason

+0

@Jason: Danke. Ich nahm an, die Liste würde. – gbn

1

Ihre Maßnahme möglicherweise nicht korrekt, bitte die System.Diagnostics.Stopwatch Klasse für die Zeitmessung verwenden:

static void Main(string[] args) 
{ 
    var sw = Stopwatch.StartNew(); 
    Thread.Sleep(100); 
    Console.WriteLine(sw.Elapsed.ToString()); 
    Console.Read(); 
} 
+0

Kluger Rat (sollte aber wohl ein Kommentar sein). Offensichtlich kann der Thread.Sleep dazu führen, dass der Thread länger als 100 ms schläft. – RichardOD

+0

Ja, aber wenn ich das Programm oben lief das gedruckte Ergebnis war etwas kleiner als 100ms –

+0

Ein Kommentar würde nicht die Code-Formatierung aktivieren –

3

Erfassen und analysieren Sie die SQL-Anweisungen, die über das Kabel in Ihrem Linq To Sql-Beispiel gesendet werden. SQL Profiler wird den Trick machen.

Führen Sie diese Anweisungen von Beispiel 1 und 2 direkt mit Ihrem SQL Server mithilfe von Management Studio aus. Wahrscheinlich werden Sie keinen wesentlichen Unterschied im Abfrageplan sehen.

Ich denke, dass die meiste Zeit in der Konstruktion der C# -Objekte verbracht wird (Jason's answer nails it, denke ich).

2

Linq to Sql muss aus Ihrem Code herausfinden, welche Art von Abfrage für die Datenbank ausgeführt werden soll, dann müssen die Ergebnisse der Abfrage in stark typisierte Objekte übersetzt werden, was bedeutet, dass Casting ausgeführt wird. Das sind zwei Dinge, die Ihre DataSet-Version nicht tut.

Wenn Sie an Linq zu Sql Leistung interessiert sind, gibt es die Möglichkeit, compiled queries zu verwenden, die die Notwendigkeit für die Interpretation zur Laufzeit entfernt.