2010-09-17 2 views
0

J'ai fait quelques profilage sur un programme que je suis en cours d'exécution et la chose qui prend le plus de temps est d'obtenir les résultats de la requête LINQ:Foreaching à travers les résultats groupq linq est incroyablement lent, des conseils?

var Results = 
    from a in Table 
    group a by a.Value into b 
    select new {Group = b}; 

foreach(var Result in Results) 
{ 
    //Do calcs 
} 

Toutes les idées sur la façon dont je peux accélérer ce?

+2

Je ne pense pas qu'il y ait assez d'informations ici. Qu'est-ce que Table? Est-ce qu'il fait des appels de base de données? Qu'est-ce qui prend beaucoup de temps? Juste la boucle foreach? Ou ce qui est dans le foreach? – Bryan

+1

On dirait que 'select new {Group = b}' pourrait être juste 'select b' mais cela ne l'accélèrera pas. –

+0

Regroupement peut être une opération coûteuse. Si Table est dans une base de données, a-t-il un index sur Value? –

Répondre

2

Je pense que vous confondez l'objet de requête avec les résultats de cette requête. Votre première variable ne contient pas les résultats, elle contient un objet de requête. À ce stade, la requête n'a pas été exécutée. L'exécution est retardée jusqu'à ce que vous ayez réellement besoin des résultats, et dans votre exemple ceci est fait quand vous itérez dans la boucle de foreach. C'est pourquoi la première instruction s'exécute rapidement mais l'itération est lente.

Si vous souhaitez stocker les résultats de la requête dans results afin qu'ils soient déjà calculés au moment où vous démarrez la boucle foreach, ajoutez un appel à ToList().

var results = 
    (from a in Table 
    group a by a.Value into b 
    select new {Group = b}).ToList(); 
+0

Mais cela rendrait-il (tout le code affiché) plus rapide? –

+1

J'en doute, mais pour être sûr que vous devriez mesurer. Ce qu'il va faire, c'est prendre le coût d'exécution à l'avance afin que l'itération soit plus rapide. Il me semble que la préoccupation de l'OP était plus que l'itération était étonnamment lente plutôt que l'exécution totale du code soit lente. Si vous n'êtes pas sûr de ce qui se passe dans les coulisses, vous pouvez vous attendre à ce que la première ligne soit lente et la boucle rapide. –

+1

J'ai une liste avec 128000 articles. Avait le groupe par productid. Fait un Où sur la clé et a couru si cela. Il a fallu 0,10 sec. Après avoir fait un ToList sur le IEnumerable > le temps était 0,0002 sec. Ne sachez pas que cela se passe à l'écran. Mais ça fait un gros diffents. – mimo

0

Si vous utilisez .NET 4, un coup d'oeil à P-LINQ ou Parallel ForEach boucles. Cela devrait considérablement augmenter les performances.

Vous ne pouvez pas vraiment dire sur la base de l'information donnée, mais il peut être une requête SQL prend trop de temps?

Si c'est la boucle ForEach qui cause le goulot d'étranglement, alors le Parallel ForEach sera votre meilleur pari.

+0

Si c'est lié aux E/S (base de données), quelques threads supplémentaires n'aideront pas beaucoup. Je pense que cela dépend (sur les détails indisponibles). –

+0

Cela n'aura qu'une amélioration potentielle pour LINQ to Objects, mais si vous utilisez un IQueryable , cela n'aidera pas (beaucoup), puisque le goulot d'étranglement est probablement dans le backend. –

+0

@Reed, oui, c'est comme Henk dit, il est entièrement basé sur les détails indisponibles.Si le Calcs étant fait dans la boucle de foreach est le problème, ceci aiderait, ou même si l'instruction LINQ est contre une collection d'objet, mais nous ne savons pas de l'information donnée. –

0

J'ai rencontré le même problème avec seulement 2000 enregistrements SQLite (indexés) utilisés pour un MSChart, apparemment cela est dû à l'instruction de groupe LINQ interrogeant tous les enregistrements.

La seule solution que j'ai trouvée était de revenir à SQL natif et le graphique rendu instantanément au lieu de 2 secondes en utilisant LINQ avec SQlite.

Questions connexes