114 votes

L'ordre de LINQ fonctions de la matière?

Dans le fond, la question des états... l'ordre de LINQ fonctions de la matière en termes de performance? Évidemment, les résultats doivent être identiques encore...

Exemple:

myCollection.OrderBy(item => item.CreatedDate).Where(item => item.Code > 3);
myCollection.Where(item => item.Code > 3).OrderBy(item => item.CreatedDate);

Les deux m'a fait les mêmes résultats, mais sont dans un autre LINQ commande. Je me rends compte que la réorganisation de certains éléments vont entraîner des résultats différents, et je ne suis pas préoccupé par celles-ci. Ce que ma principale préoccupation est de savoir si, en obtenant les mêmes résultats, la commande peut influer sur les performances. Et, non seulement sur les 2 LINQ appels, j'ai fait (OrderBy, Où), mais sur toutes les requêtes LINQ appels.

147voto

Jon Skeet Points 692016

Il dépendra du fournisseur LINQ en cours d'utilisation. LINQ to Objects, qui pourrait certainement faire une énorme différence. Supposons que nous avons maintenant:

var query = myCollection.OrderBy(item => item.CreatedDate)
                        .Where(item => item.Code > 3);

var result = query.Last();

Qui exige que l' ensemble de la collection à être triés et puis filtré. Si nous avions un million d'articles, dont un seul avait un code supérieur à 3, nous aimerions être en train de perdre beaucoup de temps à commander des résultats qui seraient jetés.

Comparez cela avec l'opération inverse, le filtrage d'abord:

var query = myCollection.Where(item => item.Code > 3)
                        .OrderBy(item => item.CreatedDate);

var result = query.Last();

Cette fois, nous ne commandent les résultats filtrés, ce qui, dans le cas d'exemple de "juste un seul élément correspondant au filtre" sera beaucoup plus efficace à la fois dans le temps et dans l'espace.

Il a également pu faire une différence dans la nature de la requête s'exécute correctement ou pas. Considérer:

var query = myCollection.Where(item => item.Code != 0)
                        .OrderBy(item => 10 / item.Code);

var result = query.Last();

C'est très bien - nous savons que nous ne serons jamais de diviser par 0. Mais si nous exécutons la commande avant le filtrage, la requête renvoie une exception.

17voto

Jeremy McGee Points 13826

Oui.

Mais exactement ce que la différence de performance est dépend de la façon dont le sous-jacent arborescence d'expression est évaluée par le fournisseur LINQ.

Par exemple, votre requête peut très bien exécuter plus vite la deuxième fois (avec la clause where de la première) pour LINQ-to-XML, mais plus rapide la première fois de LINQ-to-SQL.

Pour savoir précisément ce que la différence de performance est, vous aurez plus de chances de vouloir le profil de votre application. Comme toujours avec ce genre de choses, cependant, l'optimisation n'est généralement pas la valeur de l'effort -- vous découvrirez peut-être d'autres questions que LINQ performance sont de plus en plus important.

5voto

LukeH Points 110965

Dans votre exemple, il peut faire une différence dans la performance.

Première question: Votre OrderBy appel doit parcourir l' ensemble de la séquence source, y compris les articles où l' Code est de 3 ou moins. L' Where clause doit également effectuer une itération de la totalité de la séquence ordonnée.

Deuxième question: La Where appel limites de la séquence pour que les éléments où l' Code est supérieur à 3. L' OrderBy appel, puis il suffit de traverser la réduction de la séquence retournée par l' Where appel.

3voto

CodesInChaos Points 60274

Dans Linq-To-Objets:

Le tri est plutôt lent et les utilisations O(n) de la mémoire. Where sur l'autre main est relativement rapide et utilise constamment la mémoire. Ce faisant, Where le premier sera le plus rapide, et pour les grandes collections de manière beaucoup plus rapide.

La réduction de la pression sur la mémoire peut être importante aussi, car les affectations sur le tas d'objets volumineux(avec leur collection) sont relativement chers en mon expérience.

1voto

m-y Points 12871

Il est intéressant de noter que vous devez être prudent lorsque l'on considère la façon d'optimiser une requête LINQ. Par exemple, si vous utilisez la version déclarative de LINQ pour effectuer les opérations suivantes:

public class Record
{
    public string Name { get; set; }
    public double Score1 { get; set; }
    public double Score2 { get; set; }
}


var query = from record in Records
            order by ((record.Score1 + record.Score2) / 2) descending
            select new
                   {
                       Name = record.Name,
                       Average = ((record.Score1 + record.Score2) / 2)
                   };

Si, pour quelque raison que ce soit, vous avez décidé, pour "optimiser" la requête par le stockage de la moyenne dans une variable, tout d'abord, vous n'obtiendrez pas les résultats escomptés:

// The following two queries actually takes up more space and are slower
var query = from record in Records
            let average = ((record.Score1 + record.Score2) / 2)
            order by average descending
            select new
                   {
                       Name = record.Name,
                       Average = average
                   };

var query = from record in Records
            let average = ((record.Score1 + record.Score2) / 2)
            select new
                   {
                       Name = record.Name,
                       Average = average
                   }
            order by average descending;

Je ne sais pas beaucoup de gens utilisent déclarative LINQ pour les objets, mais c'est une bonne nourriture pour la pensée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X