2009-11-22 5 views
7

J'ai comparé deux requêtes qui récupèrent des données assez volumineuses à partir d'une table de base de données. Pour la première question, j'ai utilisé Linq To Sql et pour l'autre, j'utilise passthrough SQL via ADO.NET. Je sais que Linq To Sql doit faire beaucoup de travail dans les coulisses, mais que fait-il réellement? Les deux requêtes récupèrent la même quantité de données, mais la requête Linq To Sql est plus lente de plus de 5 secondes et utilise 150 Mo de RAM de plus!Pourquoi la liaison de données Linq To Sql vers gridview est-elle beaucoup plus lente que le SQL direct?

Voici mon code de test:

LINQ Pour 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(); 
    } 

Passthrough SQL + 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

Avez-vous testé cela lorsque le processus n'est pas attaché au débogueur? –

+0

J'ai rencontré des problèmes similaires avec NHibernate. Je ne suis pas sûr de ce qu'est le big secetet "derrière l'écran" mais je suppose que les outils ORM sont lents .... – Dani

+1

@Dani - "Les outils ORM sont lents" ne découlent pas des essais de performance de databinding. C'est une déclaration ** très ** générale (et, à mon humble avis, trompeuse). – TrueWill

Répondre

8

Linq2Sql retourne des objets fortement typés alors que l'ensemble de données se peuplaient avec ce qui revient essentiellement à table de hachage.

Dans Linq, la population des données et la liaison de ces données à un GridView utilise beaucoup de réflexion pour générer les résultats souhaités. Dans la deuxième partie du code, les données sont chargées dans un ensemble de données et liées à un GridView. Ceci charge essentiellement une hashtable avec des données et des recherches à lier.

Les opérations de hachage vont toujours être plus rapides que la réflexion. Avec une petite quantité de données, il n'y aura pas de différence notable, mais pour beaucoup de données, vous verrez l'impact de la réflexion dans Linq.

+0

Merci pour votre réponse. J'ai besoin d'une réponse. Qu'est-ce que la réflexion? – Poku

+1

La réflexion est le processus de découverte par programmation des propriétés, des méthodes, des événements d'un objet ou d'un type. Découvrez l'espace de noms System.Reflection sur MSDN. C'est ce que Linq doit faire pour affecter les valeurs renvoyées par la requête aux propriétés de l'objet tDokument. Il est beaucoup plus lent que l'affectation directe des propriétés. – Jason

4

Avez-vous regardé le SQL réel d'être envoyé à SQL Server avec Profiler?

Dans ce cas, je suppose que c'est la façon dont le client le gère (DataSet vs List) qui cause la différence, mais je suis loin d'être un expert C#.

+0

L'ensemble de données aura plus de frais généraux que la liste générique, donc cela ne devrait pas être le problème. – Jason

+0

@Jason: merci. J'ai supposé que la liste le ferait. – gbn

1

Votre mesure ne peut pas être précis, s'il vous plaît utiliser la classe System.Diagnostics.StopWatch pour la mesure du temps:

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

Conseils judicieux (mais devrait probablement être un commentaire). De toute évidence, le Thread.Sleep peut provoquer un arrêt du thread pendant plus de 100 ms. – RichardOD

+0

Oui, mais quand j'ai couru le programme ci-dessus le résultat imprimé était légèrement inférieur à 100ms –

+0

Un commentaire ne permettrait pas la mise en forme du code –

3

Capturez et analysez les instructions SQL qui sont envoyées sur le réseau dans votre exemple Linq To Sql. SQL Profiler fera l'affaire.

Exécutez les deux instructions de l'exemple 1 et 2 directement sur votre serveur SQL à l'aide de Management Studio. Vous ne verrez probablement pas de différence substantielle dans le plan de requête.

Je pense que la majorité du temps est consacré à la construction des objets C# (Jason's answer nails it, je pense).

2

Linq to Sql doit déterminer à partir de votre code quel type de requête exécuter sur la base de données puis il doit traduire les résultats de la requête en objets fortement typés, ce qui signifie que la conversion aura lieu. C'est deux choses que votre version de DataSet ne fait pas.

Si vous êtes intéressé par les performances Linq to Sql, vous pouvez utiliser compiled queries, ce qui supprime le besoin d'interprétation lors de l'exécution.