2010-02-14 5 views
2

J'ai entrepris d'écrire une méthode dans mon application C# qui peut renvoyer un sous-ensemble ordonné de noms d'une table contenant environ 2000 noms commençant par le 100ème nom et renvoyant les 20 noms suivants. Je le fais afin que je puisse remplir un WPF DataGrid dans mon interface utilisateur et faire une pagination personnalisée. J'ai utilisé LINQ to SQL, mais j'ai rencontré un problème avec cette longue requête d'exécution, donc j'examine le SQL que la requête LINQ utilise (requête B ci-dessous)."Trier par" dans LINQ-to-SQL Provoque des problèmes de performances

la requête A fonctionne bien:

SELECT TOP (20) 
[t0].[subject_id] AS [Subject_id], 
[t0].[session_id] AS [Session_id], 
[t0].[name] AS [Name] 

FROM [Subjects] AS [t0] 
WHERE (NOT (EXISTS(
    SELECT NULL AS [EMPTY] 
    FROM (
     SELECT TOP (100) [t1].[subject_id] 
     FROM [Subjects] AS [t1] 
     WHERE [t1].[session_id] = 1 
     ORDER BY [t1].[name] 
     ) AS [t2] 
    WHERE [t0].[subject_id] = [t2].[subject_id] 
    ))) AND ([t0].[session_id] = 1) 

Recherche B prend 40 secondes.

SELECT TOP (20) 
[t0].[subject_id] AS [Subject_id], 
[t0].[session_id] AS [Session_id], 
[t0].[name] AS [Name] 

FROM [Subjects] AS [t0] 
WHERE (NOT (EXISTS(
    SELECT NULL AS [EMPTY] 
    FROM (
     SELECT TOP (100) [t1].[subject_id] 
     FROM [Subjects] AS [t1] 
     WHERE [t1].[session_id] = 1 
     ORDER BY [t1].[name] 
     ) AS [t2] 
    WHERE [t0].[subject_id] = [t2].[subject_id] 
    ))) AND ([t0].[session_id] = 1) 
ORDER BY [t0].[name] 

Quand j'ajoute le [nom] ORDER BY [t0] à la requête externe, il ralentit bas de la requête.

Comment puis-je améliorer la deuxième requête?


C'était mon truc LINQ Nick

int sessionId = 1; 
int start = 100; 
int count = 20; 

// Query subjects with the shoot's session id 
var subjects = cldb.Subjects.Where<Subject>(s => s.Session_id == sessionId); 

// Filter as per params 
var orderedSubjects = subjects 
     .OrderBy<Subject, string>(
        s => s.Col_zero 
        );     

var filteredSubjects = orderedSubjects 
     .Skip<Subject>(start) 
     .Take<Subject>(count); 
+0

est ORDER BY [t0]. [Col_one] destiné à lire ORDER BY [t0]. [Nom]? – spender

+0

yes sorry mon erreur de copier-coller – Grokodile

+0

Avez-vous essayé d'inspecter le plan de requête généré par SQL Server pour les deux requêtes? –

Répondre

4

index manquant sur [Subjects].[name]?

+0

Oui merci, je n'avais pas (blush) réalisé que j'avais besoin de configurer des index, maintenant Query B ne prend que 0.07 secondes! – Grokodile

0

Si vous pouviez modifier la séquence de .OrderBy dans la requête LINQ, vous pourriez obtenir des performances. c'est-à-dire que vous interrogez des données paginées (non ordonnées), puis effectuez OrderBy. Cela va injecter votre requête A, pour faire le tri pour in-memory-data.

0

Votre requête sélectionne le TOP 20, mais quand vous ajoutez ORDER BY à la requête TOP, cela signifie qu'il faut trier la table entière par Name puis exécutez cette ligne par ligne sous-requête. Donc, bien que le changement peut sembler anodin, la deuxième requête est en réalité très différente, car il a maintenant beaucoup plus de 20 lignes à traiter. C'est mauvais en termes de performance, et pire encore si vous n'avez pas d'index sur la colonne Name.

Si vous essayez de faire la radiomessagerie, vous pouvez regarder this question. Bien que ce soit quelque chose que vous ne feriez jamais dans une base de données multi-utilisateur, SQL Server CE est mono-utilisateur et pour les requêtes de pagination, il est souvent (presque toujours) plus rapide d'utiliser soit un accès direct à la table pour ce type de chose ou un curseur statique (SqlCeResultSet) qui peut rechercher en arrière.

+0

Merci pour le lien – Grokodile

Questions connexes