Contar(*) frente a Contar(1) - SQL Server

Resuelto super9 asked hace 15 años • 13 respuestas

¿Me pregunto si alguno de ustedes consume Count(1)más Count(*)y si hay una diferencia notable en el rendimiento o si esto es solo un hábito heredado que se ha desarrollado desde tiempos pasados?

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

super9 avatar Aug 03 '09 17:08 super9
Aceptado

No hay diferencia.

Razón:

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

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

Lo mismo que EXISTS (SELECT * ...oEXISTS (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, agosto de 2011

Pregunta similar en DBA.SE.

Editar, diciembre de 2011

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

Caso:

a) If COUNT(*) is specified, then the result is the cardinality of T.

That is, the ANSI standard recognizes it as bleeding obvious what you mean. COUNT(1) has been optimized out by RDBMS vendors because of this superstition. Otherwise it would be evaluated as per ANSI

b) Otherwise, let TX be the single-column table that is the result of applying the <value expression> to each row of T and eliminating null values. If one or more null values are eliminated, then a completion condition is raised: warning-

gbn avatar Aug 03 '2009 10:08 gbn

I work on the SQL Server team and I can hopefully clarify a few points in this thread (I had not seen it previously, so I am sorry the engineering team has not done so previously).

TL;DR:

There is no semantic and no noticeable difference in performance difference between select count(1) from table vs. select count(*) from table.

Explanation

First, there is no semantic difference between select count(1) from table vs. select count(*) from table. They return the same results in all cases (and it is a bug if not). As noted in the other answers, select count(column) from table is semantically different and does not always return the same results as count(*).

Second, with respect to performance, there are two aspects that would matter in SQL Server (and SQL Azure): compilation-time work and execution-time work. The Compilation time work is a trivially small amount of extra work in the current implementation. There is an expansion of the * to all columns in some cases followed by a reduction back to 1 column being output due to how some of the internal operations work in binding and optimization. I doubt it would show up in any measurable test, and it would likely get lost in the noise of all the other things that happen under the covers (such as auto-stats, xevent sessions, query store overhead, triggers, etc.). It is maybe a few thousand extra CPU instructions. So, count(1) does a tiny bit less work during compilation (which will usually happen once and the plan is cached across multiple subsequent executions). For execution time, assuming the plans are the same there should be no measurable difference. (One of the earlier examples shows a difference - it is most likely due to other factors on the machine if the plan is the same).

Disclaimer as to how the plan can potentially be different (very rare)

Es muy poco probable que esto suceda , pero es potencialmente posible en la arquitectura del optimizador actual.

El optimizador de SQL Server funciona como un programa de búsqueda (piense en un programa de computadora que juega al ajedrez, busca entre varias alternativas para diferentes partes de la consulta y calcula los costos de las alternativas para encontrar el plan más barato en un tiempo razonable). Esta búsqueda tiene algunos límites en su funcionamiento para que la compilación de la consulta finalice en un tiempo razonable. Para consultas que van más allá de las más triviales, hay fases de la búsqueda y se ocupan de tramos de consultas en función de lo costosa que el optimizador cree que es potencialmente ejecutar la consulta.

Hay 3 fases de búsqueda principales , y cada fase puede ejecutar heurísticas más agresivas (caras) tratando de encontrar un plan más barato que cualquier solución anterior. En última instancia, hay un proceso de decisión al final de cada fase que intenta determinar si debe devolver el plan que encontró hasta ahora o debe seguir buscando.

Este proceso utiliza el tiempo total empleado hasta el momento frente al costo estimado del mejor plan encontrado hasta el momento. Por lo tanto, en diferentes máquinas con diferentes velocidades de CPU es posible (aunque poco común) obtener diferentes planes debido al tiempo de espera en una fase anterior con un plan en lugar de continuar en la siguiente fase de búsqueda.

También hay algunos escenarios similares relacionados con el tiempo de espera de la última fase y la posibilidad de quedarse sin memoria en consultas muy, muy costosas que consumen toda la memoria de la máquina (no suele ser un problema en 64 bits, pero sí era una preocupación mayor). en servidores de 32 bits).

En última instancia, si obtiene un plan diferente, el rendimiento en tiempo de ejecución será diferente. No creo que sea remotamente probable que la diferencia en el tiempo de compilación NUNCA conduzca a que ocurra alguna de estas condiciones .

Neto-neto:

Utilice cualquiera de los dos que desee, ya que nada de esto importa en la práctica. (Honestamente, hay factores mucho, mucho más importantes que afectan el rendimiento en SQL más allá de este tema).

Informacion adicional

Espero que esto ayude. Escribí un capítulo de libro sobre cómo funciona el optimizador, pero no sé si es apropiado publicarlo aquí (ya que todavía creo que obtengo pequeñas regalías). Entonces, en lugar de publicar eso, publicaré un enlace a una charla que di en SQLBits en el Reino Unido sobre cómo funciona el optimizador a alto nivel para que puedas ver las diferentes fases principales de la búsqueda con un poco más de detalle si quieres. para aprender sobre eso.

Aquí está el enlace del vídeo: Dentro del Optimizador de consultas de SQL Server

Conor Cunningham MSFT avatar Jan 15 '2019 03:01 Conor Cunningham MSFT

En SQL Server, estas declaraciones generan los mismos planes.

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

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

En mi base de datos de prueba, t_evenhay una tabla con 1,000,000filas.

Esta consulta:

SELECT  COUNT(SYS_GUID())
FROM    t_even

se ejecuta durante 48segundos, ya que la función necesita evaluar cada SYS_GUID()retorno para asegurarse de que no sea un archivo NULL.

Sin embargo, esta consulta:

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

se ejecuta durante unos 2segundos, ya que ni siquiera intenta evaluar SYS_GUID()(a pesar de *ser un argumento para COUNT(*))

Quassnoi avatar Aug 03 '2009 10:08 Quassnoi

Claramente, COUNT(*)y siempreCOUNT(1) devolverá el mismo resultado. Por lo tanto, si uno fuera más lento que el otro, efectivamente se debería 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 un error de este tipo permanezca sin corregir. Por lo tanto, encontrará que el rendimiento de ambas formas es (probablemente) idéntico en todos los principales DBMS SQL.

Tony Andrews avatar Aug 03 '2009 10:08 Tony Andrews