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


Solo me pregunto si alguno de ustedes usa Count(1) sobre Count(*) y si hay una diferencia notable en el rendimiento o si esto es solo un hábito heredado que ha sido traído de días pasados?

(La base de datos específica es SQL Server 2005.)

Author: DineshDB, 2009-08-03

11 answers

No hay diferencia.

Razón:

Libros en línea dice "COUNT ( { [ [ ALL | DISTINCT ] expression ] | * } )"

"1" es una expresión no nula: así que es lo mismo que COUNT(*). El optimizador lo reconoce por lo que es: trivial.

Lo mismo que EXISTS (SELECT * ... o EXISTS (SELECT 1 ...

Ejemplo:

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

Mismo IO, mismo plan, las obras

Editar, Ago 2011

Pregunta similar en DBA.SE .

Editar, Dic 2011

COUNT(*) se menciona específicamente en ANSI-92 (busque "Scalar expressions 125")

Caso:

A) Si se especifica COUNT (*), entonces el resultado es la cardinalidad de T.

Es decir, el estándar ANSI lo reconoce como sangrado obvio lo que quiere decir. COUNT(1) ha sido optimizado por los vendedores de RDBMS porque de esta superstición. De lo contrario, se evaluaría según ANSI

B) De lo contrario, sea TX la tabla de una sola columna que es la resultado de la aplicación de la a cada fila de T y eliminando valores nulos. Si uno o más valores null eliminado, entonces se plantea una condición de finalización: advertencia -

 531
Author: gbn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-13 12:42:40

En SQL Server, estas sentencias producen los mismos planes.

Contrariamente a la opinión popular, en Oracle también lo hacen.

SYS_GUID() en Oracle es bastante computación función intensiva.

En mi base de datos de pruebas, t_even es una tabla con 1,000,000 filas

Esta consulta:

SELECT  COUNT(SYS_GUID())
FROM    t_even

Se ejecuta durante 48 segundos, ya que la función necesita evaluar cada SYS_GUID() devuelto para asegurarse de que no es un NULL.

Sin embargo, esta consulta:

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

Se ejecuta para pero 2 segundos, ya que ni siquiera intenta evaluar SYS_GUID() (a pesar de que * es un argumento para COUNT(*))

 68
Author: Quassnoi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-03 05:20:08

Claramente, COUNT(*) y COUNT(1) siempre devolverán el mismo resultado. Por lo tanto, si uno fuera más lento que el otro, efectivamente sería debido a un error del optimizador. Dado que ambas formas se utilizan con mucha frecuencia en las consultas, no tendría sentido que un DBMS permita que dicho error permanezca sin corregir. Por lo tanto, encontrará que el rendimiento de ambas formas es (probablemente) idéntico en todos los DBMSs SQL principales.

 52
Author: Tony Andrews,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-31 08:54:03

En el estándar SQL-92, COUNT(*) significa específicamente "la cardinalidad de la expresión de la tabla" (podría ser una tabla base, `VIEW, tabla derivada, CTE, etc.).

Supongo que la idea era que COUNT(*) es fácil de analizar. El uso de cualquier otra expresión requiere que el analizador se asegure de que no hace referencia a ninguna columna (COUNT('a') donde a es un literal y COUNT(a) donde a es una columna puede producir resultados diferentes).

En la misma línea, COUNT(*) puede ser fácilmente elegido por un codificador humano familiarizado con los estándares SQL, una habilidad útil cuando se trabaja con la oferta SQL de más de un proveedor.

También, en el caso especial SELECT COUNT(*) FROM MyPersistedTable;, el pensamiento es que el DBMS es probable que mantenga estadísticas para la cardinalidad de la tabla.

Por lo tanto, debido a que COUNT(1) y COUNT(*) son semánticamente equivalentes, utilizo COUNT(*).

 20
Author: onedaywhen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-16 08:36:45

COUNT(*) y COUNT(1) son iguales en caso de resultado y rendimiento.

 15
Author: Nakul Chaudhary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-05 09:47:21

Esperaría que el optimizador se asegurara de que no hay una diferencia real fuera de los casos extremos extraños.

Como con cualquier cosa, la única manera real de saber es medir sus casos específicos.

Dicho esto, siempre he usado COUNT(*).

 12
Author: Richard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-03 10:17:05

A medida que esta pregunta surge una y otra vez, aquí hay una respuesta más. Espero agregar algo para los principiantes que se preguntan sobre" mejores prácticas " aquí.

SELECT COUNT(*) FROM something cuenta registros que es una tarea fácil.

SELECT COUNT(1) FROM something recupera un 1 por registro y que cuenta los 1s que no son null, que es esencialmente contando registros, solo que más complicado.

Dicho esto: Los buenos dbms notan que la segunda declaración resultará en el mismo conteo que la primera declaración y la reinterpretarán en consecuencia, como para no hacer un trabajo innecesario. Por lo general, ambas declaraciones resultarán en el mismo plan de ejecución y tomarán la misma cantidad de tiempo.

Sin embargo, desde el punto de vista de la legibilidad, debe usar la primera instrucción. Quieres contar registros, así que cuenta registros, no expresiones. Use COUNT (expresión) solo cuando desee contar ocurrencias no nulas de algo.

 7
Author: Thorsten Kettner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-05 10:43:08

Ejecuté una prueba rápida en SQL Server 2012 en una caja hyper-v de 8 GB de RAM. Puedes ver los resultados por ti mismo. No estaba ejecutando ninguna otra aplicación de ventana aparte de SQL Server Management Studio mientras ejecutaba estas pruebas.

Mi esquema de tabla:

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

Número total de registros en la tabla Employee: 178090131 (~178 millones de filas)

Primera Consulta:

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

Resultado de la Primera Consulta:

 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.

Segundo Consulta:

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

Resultado de la Segunda Consulta:

 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.

Puede notar que hay una diferencia de 83 milisegundos (= 70265 - 70182) que se puede atribuir fácilmente a la condición exacta del sistema en el momento en que se ejecutan las consultas. También hice una sola carrera, por lo que esta diferencia será más precisa si hago varias carreras y hago un promedio. Si para un conjunto de datos tan grande la diferencia es inferior a 100 milisegundos, entonces podemos concluir fácilmente que las dos consultas no tener cualquier diferencia de rendimiento exhibida por el motor de SQL Server.

Nota : La RAM alcanza cerca del 100% de uso en ambas carreras. Reinicié el servicio SQL Server antes de iniciar ambas ejecuciones.

 7
Author: RBT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-20 03:54:41
SET STATISTICS TIME ON

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

Tiempos de ejecución de SQL Server:
Tiempo de CPU = 31 ms, tiempo transcurrido = 36 ms.

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

Tiempos de ejecución de SQL Server:
Tiempo de CPU = 46 ms, tiempo transcurrido = 37 ms.

He ejecutado esto cientos de veces, borrando la caché cada vez.. Los resultados varían de vez en cuando a medida que varía la carga del servidor, pero casi siempre count(*) tiene un tiempo de cpu más alto.

 7
Author: Eyal Z.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-22 10:43:41

Hay un artículo que muestra que el COUNT(1) en Oracle es solo un alias para COUNT(*), con una prueba sobre eso.

Citaré algunas partes: {[17]]}

Hay una parte del software de la base de datos que se llama " El Optimizador", que se define en la documentación oficial como "Software de base de datos incorporado que determina la forma más eficiente de ejecutar una sentencia SQL".

Uno de los componentes del optimizador es llamado "el transformador", cuyo papel es determinar si es ventajoso reescribir el sentencia SQL original en una sentencia SQL semánticamente equivalente eso podría ser más eficiente.

¿Le gustaría ver lo que hace el optimizador cuando escribe una consulta ¿usando COUNT(1)?

Con un usuario con privilegios ALTER SESSION, puede poner un tracefile_identifier, habilitar el seguimiento del optimizador y ejecutar la selección COUNT(1), como: SELECT /* test-1 */ COUNT(1) FROM employees;.

Después de eso, debe localizar el archivos de seguimiento, lo que se puede hacer con SELECT VALUE FROM V$DIAG_INFO WHERE NAME = 'Diag Trace';. Más adelante en el archivo, encontrará:

SELECT COUNT(*) “COUNT(1)” FROM “COURSE”.”EMPLOYEES” “EMPLOYEES”

Como puedes ver, es solo un alias para COUNT(*).

Otro comentario importante: el COUNT(*) era realmente más rápido hace dos décadas en Oracle, antes de Oracle 7.3:

Count (1) se ha reescrito en count(*) desde 7.3 porque Oracle like para ajustar automáticamente las declaraciones míticas. En Oracle7 anterior, oracle tuvo que evaluar (1) para cada fila, como una función, antes de DETERMINISTIC y Existen no DETERMINISTAS.

Así que hace dos décadas, el conteo(*) era más rápido

Para otras bases de datos como Sql Server, se debe investigar individualmente para cada una.

Sé que esta pregunta es específica para Sql Server, pero las otras preguntas sobre SO sobre el mismo tema, sin mencionar la base de datos, se cerraron y marcaron como duplicadas de esta respuesta.

 2
Author: Dherik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-26 11:50:14

CUENTA fácil de demo ( * ) vs CUENTA () {

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
 -1
Author: Graeme,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-22 17:00:08