Compter (*) vs Compter (1)

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

(La database spécifique est SQL Server 2005.)

    Il n'y a pas de différence.

    Raison:

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

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

    EXISTS (SELECT * ... à 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 (searchz " 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 en raison de cette superstition. Sinon, il serait évalué selon ANSI

    b) Sinon, soit TX la table à une seule colonne qui est le 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ées, une condition d'achèvement est déclenchée:

    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 une fonction de calcul intensif.

    Dans ma database de test, t_even est une table avec 1,000,000 lignes

    Cette requête:

     SELECT COUNT(SYS_GUID()) FROM t_even 

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

    Cependant, cette requête:

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

    fonctionne pendant 2 secondes, car il n'essaie même pas d'évaluer SYS_GUID() (malgré que * soit l'argument de COUNT(*) )

    Clairement, COUNT (*) et COUNT (1) returnneront toujours 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 restr non fixé. Par conséquent, vous constaterez que les performances des deux forms sont (probablement) identiques dans tous les principaux SGBD SQL.

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

    Je suppose que l'idée était que COUNT(*) est facile à parsingr. L'utilisation de toute autre expression nécessite que l'parsingur s'assure qu'il ne reference aucune colonne ( COUNT('a')a est un littéral et COUNT(a)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 standards SQL, une compétence utile lorsque l'on travaille avec plus d'un fournisseur SQL.

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

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

    COUNT(*) et COUNT(1) sont identiques en cas de résultat et de performance.

    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(*) .

     SET STATISTICS TIME ON select count(1) from MyTable (nolock) -- table containing 1 million records. 

    Temps d'exécution SQL Server:
    Temps CPU = 31 ms, time écoulé = 36 ms.

     select count(*) from MyTable (nolock) -- table containing 1 million records. 

    Temps d'exécution SQL Server:
    Temps CPU = 46 ms, time écoulé = 37 ms.

    J'ai couru ceci des centaines de fois, en effaçant le cache chaque fois. Les résultats varient de time en time car la charge du server varie, mais presque toujours count (*) a le time plus élevé de cpu.

    Comme cette question revient encore et encore, voici une réponse de plus. J'espère append quelque chose pour les débutants s'interrogeant sur les «meilleures pratiques» ici.

    SELECT COUNT(*) FROM something count les loggings, ce qui est une tâche facile.

    SELECT COUNT(1) FROM something récupère un 1 par logging et que count les 1 qui ne sont pas null, ce qui est essentiellement count des loggings, seulement plus compliqué.

    Cela dit: Les bons dbms remarquent que la seconde déclaration aboutira au même nombre que la première déclaration et la réinterpréteront en conséquence, pour ne pas faire de travail inutile. Ainsi, les deux instructions aboutissent généralement au même plan d'exécution et prennent le même time.

    Cependant, du sharepoint vue de la lisibilité, vous devez utiliser la première déclaration. Vous voulez countr les loggings, donc countr les loggings, pas les expressions. Utilisez COUNT (expression) uniquement lorsque vous souhaitez countr les occurrences non nulles de quelque chose.

    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'loggings dans la table Employee : 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 comstack 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 comstack 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 comstack 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 comstack 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 atsortingbué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 set de données, la différence arrive less 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 : La 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.

    Facile à démonter COUNT (*) vs COUNT (<certains col>) –

     USE tempdb; GO IF OBJECT_ID( N'dbo.Blitzen', N'U') IS NOT NULL DROP TABLE dbo.Blitzen; GO CREATE TABLE dbo.Blitzen (ID INT NULL, Somelala CHAR(1) NULL); INSERT dbo.Blitzen SELECT 1, 'A'; INSERT dbo.Blitzen SELECT NULL, NULL; INSERT dbo.Blitzen SELECT NULL, 'A'; INSERT dbo.Blitzen SELECT 1, NULL; SELECT COUNT(*), COUNT(1), COUNT(ID), COUNT(Somelala) FROM dbo.Blitzen; GO DROP TABLE dbo.Blitzen; GO