Question Count (*) vs Count (1) - SQL Server


Je me demandais si l'un d'entre vous utilisait Count(1) plus de Count(*) et s'il y a une différence notable dans la performance ou si c'est juste une habitude héritée qui a été avancée depuis des jours passés?

(La base de données spécifique est SQL Server 2005.)


610
2017-08-03 10:15


origine


Réponses:


Il n'y a pas de différence.

Raison:

Livres en ligne dit "COUNT ( { [ [ ALL | DISTINCT ] expression ] | * } )"

"1" est une expression non nulle: donc c'est la même chose que COUNT(*). L'optimiseur le reconnaît pour ce qu'il est: trivial.

Le même que EXISTS (SELECT * ... ou EXISTS (SELECT 1 ...

Exemple:

SELECT COUNT(1) FROM dbo.tab800krows
SELECT COUNT(1),FKID FROM dbo.tab800krows GROUP BY FKID

SELECT COUNT(*) FROM dbo.tab800krows
SELECT COUNT(*),FKID FROM dbo.tab800krows GROUP BY FKID

Même IO, même plan, les œuvres

Edit, août 2011

Question similaire sur DBA.SE.

Edit, déc 2011

COUNT(*) est mentionné spécifiquement dans ANSI-92 (chercher "Scalar expressions 125")

Cas:

a) Si COUNT (*) est spécifié, le résultat est la cardinalité de T.

Autrement dit, la norme ANSI reconnaît comme saignant ce que vous voulez dire. COUNT(1) a été optimisé par les fournisseurs de SGBDR car de cette superstition. Sinon, il serait évalué selon ANSI

b) Autrement, que TX soit la table à une seule colonne qui est la                 résultat de l'application de l'expression <value expression> à chaque ligne de T                 et en éliminant les valeurs nulles. Si une ou plusieurs valeurs nulles sont                 éliminée, une condition d'achèvement est levée: avertissement


516
2017-08-03 10:36



Dans SQL Server, ces instructions produisent les mêmes plans.

Contrairement à l'opinion populaire, dans Oracle, ils le font aussi.

SYS_GUID() dans Oracle est très fonction de calcul intensif.

Dans ma base de données de test, t_even est une table avec 1,000,000 rangées

Cette requête:

SELECT  COUNT(SYS_GUID())
FROM    t_even

fonctionne pour 48 secondes, puisque la fonction doit évaluer chaque SYS_GUID() retourné pour s'assurer que ce n'est pas un NULL.

Cependant, cette requête:

SELECT  COUNT(*)
FROM    (
        SELECT  SYS_GUID()
        FROM    t_even
        )

fonctionne pour mais 2 secondes, puisqu'il n'essaie même pas d'évaluer SYS_GUID() (malgré * être l'argument de COUNT(*))


64
2017-08-03 10:34



Il est clair que COUNT (*) et COUNT (1) toujours retourne le même résultat. Par conséquent, si l'un était plus lent que l'autre, il serait effectivement dû à un bug optimiseur. Puisque les deux formulaires sont utilisés très fréquemment dans les requêtes, il serait illogique qu'un SGBD permette à un tel bogue de rester non fixé. Par conséquent, vous constaterez que les performances des deux formes sont (probablement) identiques dans tous les principaux SGBD SQL.


49
2017-08-03 10:45



Dans la norme SQL-92, COUNT(*) signifie spécifiquement "la cardinalité de l'expression de table" (pourrait être une table de base, `VIEW, table dérivée, CTE, etc).

Je suppose que l'idée était que COUNT(*) est facile à analyser. L'utilisation de toute autre expression nécessite que l'analyseur s'assure qu'il ne référence aucune colonne (COUNT('a') où a est un littéral et COUNT(a) où a est une colonne peut donner des résultats différents).

Dans la même veine, COUNT(*) peut être facilement sélectionné par un codeur humain familiarisé avec les normes SQL, une compétence utile lorsque vous travaillez avec plus d'un fournisseur SQL offre.

En outre, dans le cas particulier SELECT COUNT(*) FROM MyPersistedTable;, la pensée est le SGBD est susceptible de contenir des statistiques pour la cardinalité de la table.

Par conséquent, parce que COUNT(1) et COUNT(*) sont sémantiquement équivalents, j'utilise COUNT(*).


18
2018-05-13 10:36



COUNT(*) et COUNT(1) sont les mêmes en cas de résultat et de performance.


15
2017-08-03 13:10



Je m'attendrais à ce que l'optimiseur veille à ce qu'il n'y ait pas de réelle différence en dehors des cas de bords bizarres.

Comme avec n'importe quoi, la seule vraie façon de dire est de mesurer vos cas spécifiques.

Cela dit, j'ai toujours utilisé COUNT(*).


12
2017-08-03 10:17



J'ai effectué un test rapide sur SQL Server 2012 sur une boîte hyper-v de 8 Go de RAM. Vous pouvez voir les résultats par vous-même. Je n'exécutais aucune autre application fenêtrée en dehors de SQL Server Management Studio lors de l'exécution de ces tests.

Mon schéma de table:

CREATE TABLE [dbo].[employee](
    [Id] [bigint] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
 CONSTRAINT [PK_employee] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

Nombre total d'enregistrements dans Employee table: 178090131 (~ 178 millions de lignes)

Première requête:

Set Statistics Time On
Go    
Select Count(*) From Employee
Go    
Set Statistics Time Off
Go

Résultat de la première requête:

 SQL Server parse and compile time: 
 CPU time = 0 ms, elapsed time = 35 ms.

 (1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 10766 ms,  elapsed time = 70265 ms.
 SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

Deuxième requête:

    Set Statistics Time On
    Go    
    Select Count(1) From Employee
    Go    
    Set Statistics Time Off
    Go

Résultat de la deuxième requête:

 SQL Server parse and compile time: 
   CPU time = 14 ms, elapsed time = 14 ms.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 11031 ms,  elapsed time = 70182 ms.
 SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

Vous pouvez remarquer qu'il existe une différence de 83 (= 70265 - 70182) millisecondes qui peut facilement être attribuée à la condition exacte du système au moment où les requêtes sont exécutées. De plus, j'ai fait une seule course, donc cette différence deviendra plus précise si je fais plusieurs courses et fais des moyennes. Si pour un tel ensemble de données, la différence arrive moins de 100 millisecondes, alors nous pouvons facilement conclure que les deux requêtes n'ont aucune différence de performance affichée par le moteur SQL Server.

Remarque : RAM atteint près de 100% d'utilisation dans les deux exécutions. J'ai redémarré le service SQL Server avant de démarrer les deux exécutions.


7
2017-08-20 03:54