2010-02-12 7 views
6

J'utilise la classe PagedList dans mon application Web que beaucoup d'entre vous connaissent peut-être si vous avez fait quelque chose avec ASP.NET MVC et LINQ to SQL. Il a été blogué par Rob Conery, et une incarnation similaire a été inclus dans des choses comme Nerd Dinner, etc Cela fonctionne très bien, mais mon DBA a soulevé des préoccupations sur les futurs problèmes de performance potentiels.Pagination LINQ to SQL et COUNT (*)

Sa question est autour du SELECT COUNT (*) qui obtient émis à la suite de cette ligne:

TotalCount = source.Count(); 

Toute action qui a paginée données déclencher une requête supplémentaire (comme ci-dessous) à la suite de l'appel de méthode IQueryable.Count():

SELECT COUNT(*) AS [value] FROM [dbo].[Products] AS [t0] 

y at-il une meilleure façon de gérer cette situation? J'ai envisagé d'utiliser la propriété Count de la classe PagedList pour obtenir le nombre d'éléments, mais je me suis rendu compte que cela ne fonctionnerait pas car il ne compte que le nombre d'éléments actuellement affichés (pas le nombre total).

Quelle sera l'incidence sur les performances de cette application lorsque la base de données contient beaucoup de données?

Répondre

8

iirc ce truc fait partie des statistiques de l'index et devrait être très efficace, vous devriez demander à votre administrateur de base de répondre à ses préoccupations, plutôt que d'optimiser prématurément.

+2

upvoted si dur je me suis cassé l'Internet. ;) Si une requête de comptage supplémentaire va réduire les performances de votre base de données, vous avez de sérieux problèmes. – jfar

1

Certaines bases de données (Oracle, Postgresql, SQL Server je pense) conservent un enregistrement du nombre de lignes dans les tables système; bien que ceux-ci ne soient parfois précis qu'au moment où les statistiques ont été actualisées pour la dernière fois (Oracle). Vous pouvez utiliser cette approche, si vous avez seulement besoin d'une métrique assez précise mais non exacte.

Quelle base de données utilisez-vous ou est-ce que cela varie?

+0

SQL Server 2005 –

2

En fait, c'est un problème assez commun avec Linq.

Oui, les statistiques d'index seront utilisées si l'instruction était seulement SELECT COUNT(*) AS [value] FROM [dbo].[Products] AS [t0] mais 99% du temps elle contiendra également des instructions WHERE.

Donc, fondamentalement, deux instructions SQL sont exécutées:

  1. SELECT COUNT(*) AS [value] FROM [dbo].[Products] AS [t0] WHERE blah=blah and someint=500

  2. SELECT blah, someint FROM [dbo].[Products] AS [t0] WHERE blah=blah and someint=500

Vous commencez des problèmes de réception si la table est souvent mis à jour comme COUNT(*) retourné dans la première déclaration ne correspond pas à la deuxième déclaration ... cela peut renvoyer un message d'erreur 'Ligne non trouvée ou modifiée.'

1

(PS Je sais que vous parlez MsSQL cependant)

Je ne suis pas DBA, mais le nombre (*) dans MySQL est un succès réel de la performance. Le simple fait de changer cela en compte (ID) améliore vraiment la vitesse.

Je suis tombé sur ceci lorsque j'interrogeais une table avec de très grandes données GLOB (Images). L'outil de requête environ 15 secondes pour charger. Changer la requête à count (id) réduit la requête à 0.02. Encore un peu lent mais beaucoup mieux.

Je pense que c'est ce que veut dire le DBA. J'ai remarqué alors quand déboguer Linq la déclaration qui compte prend beaucoup de temps (1 seconde) pour passer à l'instruction suivante.

Sur la base de ma conclusion, je suis d'accord avec les conserns du DBA ...