36 votes

COUNT (*) dans SQL Server est-il une opération à temps constant? Si non pourquoi pas

J'ai lu cette discussion dans un autre post où cette question a été posée par quelqu'un d'autre. Avant la lecture de la discussion, j'ai toujours pensé que SQL Server (et d'autres SGBD) de tenir un compte global de lignes de chaque table, quelque part dans les métadonnées, mais le débat semble indiquer que ce n'est pas le cas. Pourquoi? Count(*) (sans filtrage) étant communs à l'opération de l'obtenir énorme coup de pouce si elle est O(1). Même pas tenu compte de l' COUNT(*), le nombre total de lignes dans une table est une pièce essentielle de l'information. Pourquoi ne pas garder une note de celui-ci?

En outre, pourquoi avons-nous besoin de "charger" des lignes entières (comme indiqué dans le post, j'ai mis en lien) juste pour compter? Ne devrait pas l'index ou en PKs etc. être suffisante pour compter?

56voto

Remus Rusanu Points 159382

Non, COUNT(*) n'est pas une constante de temps de l'opération. Un COUNT(*) doit retourner un nombre de lignes qui sont conformes à la numérisation en cours de prédicat (ie. WHERE clause), de sorte que seule en fait le retour d'un des métadonnées de propriété non valide. Mais même si vous n'avez pas de prédicats, le COMTE a encore pour satisfaire l'isolement des transactions en cours à la sémantique, c'est à dire. renvoyer le nombre de lignes visibles (par exemple. commis). Donc, COUNT doit l'être, et sera, dans SQL Server, fait balayer et de compter les lignes. Certains systèmes permettent le retour de la plus rapide "estimation" compte.

Aussi, comme un autre commentaire, en s'appuyant sur rows en sys.partitions n'est pas fiable. Après tout, si ce nombre serait garanti précises que nous n'aurions pas besoin DBCC UPDATEUSAGE(...) WITH COUNT_ROWS. Il y a plusieurs scénarios qui, historiquement, serait la cause de ce compteur à la dérive en dehors de la réalité (surtout journalisées insérer restaurations), tout ce que je sais de sont fixes, mais qui laisse tout de même les problèmes de 1) tables de mise à niveau à partir de versions antérieures qui avaient les bugs et 2) d'autres, pas encore découvert, de bugs.

En outre, pourquoi avons-nous besoin de "charger" des lignes entières (comme indiqué dans le post, j'ai mis en lien) juste pour compter? Ne devrait pas l'index ou en PKs etc. être suffisante pour compter?

Ce n'est pas vrai à 100%. Il y a au moins 2 scénarios qui ne sont pas de "charger des lignes entières':

  • étroit rowstore indices de charge juste l'index de ligne, qui peut être beaucoup plus faible
  • columnstore chargements de données simplement les segments de la colonne

Et la plupart de ce que je dis ci-dessus ne s'appliquent pas pour Hekaton tables.

21voto

Damien_The_Unbeliever Points 102139

pourquoi avons-nous besoin de "charger" des lignes entières

Nous n'avons pas. SQL Server a tendance à utiliser le plus petit indice qu'il peut utiliser qui peut satisfaire la requête.

Count(*) (sans filtrage) d'une telle opération commune

Je pense que vous sur-estimation de sa prévalence. Je ne me souviens pas la dernière fois que j'ai soigné sur le nombre total de lignes dans une table unique plutôt qu'une vue filtrée ou de compter sur un plus complexe rejoint l'opération.

Il serait exceptionnellement étroit d'optimisation qui ne pouvait que bénéficier à un style unique de la requête, et comme je l'ai dit, je pense que vous avez surestimé souvent il se produit.

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