6
votes

Requête Linq Prendre trop de temps

Je me demande si quelqu'un peut m'aider avec ça. J'ai une requête Linq - aucun problème avec elle, mais il faut beaucoup trop de temps pour renvoyer des données xxx

très simple, l'idée que l'utilisateur tape, utilisant Ajax, il renvoie un ensemble de 15 matchs possibles.

Le problème est, il y a 1,6 million d'enregistrements

exécutant le code suivant dans Management Studio prend environ 3 secondes xxx

où en cours d'exécution du code suivant prend moins d'une seconde xxx

existe une façon de faire quelque chose de similaire dans Linq sans utiliser .take () ?


11 commentaires

Que voulez-vous dire par "quelque chose de similaire ... sans utiliser .take ()"? Demandez-vous si vous pouvez effectuer une top 15 de requête sans utiliser .take ()?


Toute raison particulière que vous ne voulez pas utiliser '.take ()'?


Pouvez-vous poster la requête SQL créée et envoyée?


@Matt Hamilton: Il demande comment il peut rendre Linq utiliser le SQL Fast SQL (= "... Top 15 ...") plutôt que le SQL lent (= quel que soit le linq fait maintenant). Apparemment, LINQ n'utilise pas le top 15 actuellement, même si prend (15) est utilisé.


@Matt, avez-vous essayé de mettre cette requête Linq dans Linqpad et de voir quelle requête est générée. Pour autant que je sache, lorsque vous utilisez une prise, vous obtiendrez un sommet dans votre relevé en réalité SQL.


Quel est le type de "contexte.paf_wgs84"?


J'espère qu'il y a un index sur code aussi :)


LINQPAD RAN TOP (15) et couru dans l'heure à laquelle je m'attendrais - utiliser un index sur le code. Je viens d'ajouter un identifiant d'incrémentation automatique et de définir ceci sur la clé primaire - n'a fait aucune différence si je suis honnête. Mon application n'a aucun moyen d'utiliser de la même manière pour exécuter le SQL car il prend la même heure avec la sélection normale. Peut avoir à essayer EFProf


@Matt, vous pouvez essayer des requêtes pré-compilées, mais utilisez EFProf, cela devrait vous dire ce qui va faire quoi. De plus, les requêtes pourraient être plus rapides sur le studio de gestion de la direction après la première exécution qu'ils sont mises en cache.


@Matt Vous n'arrivez pas à avoir un "ordonnance" dans votre requête EF? C'est un moyen courant de tuer la performance des premières questions.


J'ai modifié la déclaration en résultat var = context.paf_wgs84.Où (c => c.poscode.startswith (code postal)). Prendre (10) .Sélectionnez (C => C.Postcode) .touparay (); Je pense que le chercher à ajouter à une matrice de cordes prenait la performance. Merci pour tous les aides.


4 Réponses :


3
votes

Vous pouvez essayer quelque chose comme ça. Cela ne renverra qu'une colonne.

/*
-- Region Parameters
DECLARE @p0 VarChar(1000) = '%s%'
-- EndRegion
SELECT TOP (15) [t0].[code]
FROM [paf_wgs84] AS [t0]
WHERE [t0].[code] LIKE @p0
*/


2 commentaires

En effet, cela fait - problème, c'est que la requête prend moins d'une seconde à compléter, mais prend 4 secondes pour revenir en tant que liste du service. Le service ralentit-il le processus? Est-ce le framework ASP.NET AJAX qui prend son temps doux?


@Matt, c'est un peu différent q. Il y a quelques choses que je suggérerais. Tout d'abord, utilisez-vous MVC ou simplement ASP.NET? Vous pouvez ensuite utiliser MVC-Mini-Profiler pour profiler à la fois les requêtes et le code DB, je serrais chaque section de mon code lorsque je crée le service, appelez le service et renvoyer les valeurs, elle peut également être utilisée dans votre page ASPX. De cette façon, vous obtiendrez un bon résultat grainé de ce qui prend exactement le plus de temps. Une fois que vous avez cette information, vous devriez avoir un chemin plus direct.



1
votes

Le problème peut être que votre méthode contienne dans le StateMNT, il n'est pas mappé sur une déclaration similaire dans SQL et vous finissez par obtenir toutes les lignes dans SQL, puis effectuez une recherche de COTAINES dans votre niveau Web au lieu de faire la même chose. Dans votre dB.

Utilisez SQLMéthods pour la même chose .. Somethig comme suit: P>

SqlMethods.Like(c.Postcode, string.Format("%{0}%",postcode));


0 commentaires

0
votes

J'ai modifié la déclaration à

var result = Context.paf_wgs84.Where(c => c.Postcode.StartsWith(postcode)).Take(10).Select(c => c.Postcode).ToArray();


0 commentaires

0
votes

La performance de ces types de requêtes a été considérablement améliorée dans SQL Server 2012 à l'aide des nouvelles déclarations de récupération et de compensation (bien que je n'ai pas vu de nombreuses données d'analyse comparative à ce jour ...).

Le problème est que ef n'utilise pas encore ces nouvelles fonctionnalités.

Une solution possible consiste à utiliser SQL Server 2012 et à écrire une SPROC avec extraction / décalage, puis cibler cela à l'aide de EF. Certainement pas une solution à court terme, mais je voulais signaler cette option.


0 commentaires