Sólo me preguntaba si alguno de ustedes usan Count(1)
más Count(*)
y si hay una diferencia notable en el rendimiento o si esto es sólo un hábito legado que se ha adelantado a partir de días pasado se ha ido?
La base de datos específica es SQL Server 2005
.
sql
sql-server
performance
super9
fuente
fuente
COUNT(*)
vsCOUNT(1)
vsCOUNT(pk)
- ¿cuál es mejor? . También hayCOUNT(*)
vsCOUNT(column-name)
, ¿cuál es más correcto? . Bien puede haber otros duplicados.Respuestas:
No hay diferencia.
Razón:
"1" es una expresión no nula: es lo mismo que
COUNT(*)
. El optimizador lo reconoce por lo que es: trivial.Lo mismo que
EXISTS (SELECT * ...
oEXISTS (SELECT 1 ...
Ejemplo:
Mismo IO, mismo plan, las obras
Editar, agosto de 2011
Pregunta similar en DBA.SE .
Edit, dic 2011
COUNT(*)
se menciona específicamente en ANSI-92 (busque "Scalar expressions 125
")Es decir, el estándar ANSI lo reconoce como un sangrado obvio a lo que se refiere.
COUNT(1)
ha sido optimizado por los proveedores de RDBMS debido a esta superstición. De lo contrario, se evaluaría según ANSIfuente
En SQL Server, estas declaraciones producen los mismos planes.
Contrariamente a la opinión popular, en Oracle también lo hacen.
SYS_GUID()
en Oracle es bastante computacional la función intensiva.En mi base de datos de prueba,
t_even
hay una tabla con1,000,000
filasEsta consulta:
se ejecuta durante
48
segundos, ya que la función necesita evaluar cada unoSYS_GUID()
devuelto para asegurarse de que no sea unNULL
.Sin embargo, esta consulta:
se ejecuta durante unos
2
segundos, ya que ni siquiera intenta evaluarSYS_GUID()
(a pesar de*
ser un argumento paraCOUNT(*)
)fuente
SYS_GUID()
al menos (quiero decir, exactamente) una vez para que la subconsulta devuelva el resultado, ¿verdad?COUNT(*)
depende de los valores deSYS_GUID
?COUNT(*)
ejecutarse, necesita una tabla, por lo que la subconsulta debe actuar como tal. De lo contrario, no veo una manera deCOUNT(*)
devolver un valor significativomap
método, ¿ves cómo estas dos expresiones:t_even.map(() => sys_guid()).length
yt_even.length
siempre devolverían el mismo valor? El optimizador de Oracle es lo suficientemente inteligente como para verlo y optimizar lamap
parte.length
no depende del contenido de la colección, solo del número de sus elementos. Si este número se almacena en los metadatos de la colección (este no es el caso de Oracle ni de la mayoría de los RDBMS modernos, pero es el caso del antiguo motor de almacenamiento de MySQL, MyISAM), entoncesCOUNT(*)
solo necesitaría tomar el valor de los metadatos.Claramente,
COUNT(*)
yCOUNT(1)
será siempre devolverá el mismo resultado. Por lo tanto, si uno fuera más lento que el otro, se debería a un error optimizador. Dado que ambos formularios se usan con mucha frecuencia en las consultas, no tendría sentido que un DBMS permita que dicho error permanezca sin reparar. Por lo tanto, encontrará que el rendimiento de ambos formularios es (probablemente) idéntico en todos los DBMS SQL principales.fuente
Trabajo en el equipo de SQL Server y espero aclarar algunos puntos en este hilo (no lo había visto anteriormente, así que lamento que el equipo de ingeniería no lo haya hecho antes).
En primer lugar, no existe una diferencia semántica entre
select count(1) from table
vsselect count(*) from table
. Devuelven los mismos resultados en todos los casos (y es un error si no). Como se señaló en las otras respuestas,select count(column) from table
es semánticamente diferente y no siempre devuelve los mismos resultados quecount(*)
.En segundo lugar, con respecto al rendimiento, hay dos aspectos que serían importantes en SQL Server (y SQL Azure): trabajo en tiempo de compilación y trabajo en tiempo de ejecución. El trabajo del tiempo de compilación es una cantidad trivialmente pequeña de trabajo adicional en la implementación actual. Hay una expansión de * a todas las columnas en algunos casos, seguida de una reducción a 1 columna que se genera debido a cómo algunas de las operaciones internas funcionan en el enlace y la optimización. Dudo que aparezca en cualquier prueba medible, y es probable que se pierda en el ruido de todas las otras cosas que suceden debajo de las cubiertas (como estadísticas automáticas, sesiones xevent, gastos generales de almacenamiento de consultas, disparadores, etc.). Es tal vez unos pocos miles de instrucciones de CPU adicionales. Entonces, count (1) hace un poco menos de trabajo durante la compilación (lo que generalmente sucederá una vez y el plan se almacena en caché en varias ejecuciones posteriores). Para el tiempo de ejecución, suponiendo que los planes sean los mismos, no debería haber una diferencia medible. (Uno de los ejemplos anteriores muestra una diferencia: lo más probable es que se deba a otros factores en la máquina si el plan es el mismo).
En cuanto a cómo el plan puede ser potencialmente diferente. Es muy poco probable que sucedan, pero es potencialmente posible en la arquitectura del optimizador actual. El optimizador de SQL Server funciona como un programa de búsqueda (piense: un programa de computadora que juega al ajedrez buscando a través de varias alternativas para diferentes partes de la consulta y calcula las alternativas para encontrar el plan más barato en un tiempo razonable). Esta búsqueda tiene algunos límites sobre cómo funciona para mantener la compilación de consultas terminando en un tiempo razonable. Para consultas más allá de lo más trivial, hay fases de la búsqueda y se ocupan de tramos de consultas en función de lo costoso que el optimizador cree que la consulta es potencialmente ejecutable. Hay 3 fases de búsqueda principales, y cada fase puede ejecutar heurísticas más agresivas (costosas) 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 si debe seguir buscando. Este proceso utiliza el tiempo total empleado hasta ahora 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 raro) 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 costosas que consumen toda la memoria en la máquina (no suele ser un problema en 64 bits, pero fue una preocupación mayor) de nuevo en servidores de 32 bits). En última instancia, si obtiene un plan diferente, el rendimiento en tiempo de ejecución sería diferente. Yo no'
Net-net: utilice cualquiera de los dos que desee, ya que nada de esto importa de forma práctica. (Hay factores mucho, mucho más grandes que afectan el rendimiento en SQL más allá de este tema, sinceramente).
Espero que esto ayude. Escribí un capítulo del libro sobre cómo funciona el optimizador, pero no sé si es apropiado publicarlo aquí (ya que creo que recibo 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 un alto nivel para que pueda ver las diferentes fases principales de la búsqueda con un poco más de detalle si lo desea para aprender sobre eso. Aquí está el enlace del video: https://sqlbits.com/Sessions/Event6/inside_the_sql_server_query_optimizer
fuente
1
también sufre la misma expansión. Baso esto en las pruebas de rendimiento aquí stackoverflow.com/questions/1597442/… también veo el ejemplo en esa respuesta de una consulta usando1
fallar inesperadamente cuando los permisos de nivel de columna están en juegoEn 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 es 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')
dondea
es literal yCOUNT(a)
dóndea
es una columna puede producir resultados diferentes).En la misma línea,
COUNT(*)
un codificador humano familiarizado con los Estándares SQL puede elegirlo fácilmente, una habilidad útil cuando se trabaja con más de la oferta SQL de un proveedor.Además, en el caso especial
SELECT COUNT(*) FROM MyPersistedTable;
, el pensamiento es que es probable que el DBMS contenga estadísticas para la cardinalidad de la tabla.Por lo tanto, porque
COUNT(1)
yCOUNT(*)
son semánticamente equivalentes, yo usoCOUNT(*)
.fuente
COUNT(*)
yCOUNT(1)
son iguales en caso de resultado y rendimiento.fuente
Esperaría que el optimizador se asegure de que no haya una diferencia real fuera de los casos extraños.
Como con cualquier cosa, la única forma real de saberlo es midiendo sus casos específicos.
Dicho eso, siempre lo he usado
COUNT(*)
.fuente
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 las "mejores prácticas" aquí.
SELECT COUNT(*) FROM something
cuenta registros, lo cual es una tarea fácil.SELECT COUNT(1) FROM something
recupera un 1 por registro y luego cuenta los 1 que no son nulos, lo que esencialmente es contar registros, solo que es más complicado.Dicho esto: Good dbms nota que la segunda declaración dará como resultado la misma cuenta que la primera declaración y la reinterpretará en consecuencia, para no hacer un trabajo innecesario. Por lo tanto, ambas declaraciones darán como resultado 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 declaración. Desea contar registros, así que cuente registros, no expresiones. Use COUNT (expresión) solo cuando desee contar las ocurrencias no nulas de algo.
fuente
Ejecuté una prueba rápida en SQL Server 2012 en un cuadro Hyper-V de 8 GB de RAM. Puedes ver los resultados por ti mismo. No estaba ejecutando ninguna otra aplicación con ventana aparte de SQL Server Management Studio mientras ejecutaba estas pruebas.
Mi esquema de mesa:
Número total de registros en la
Employee
tabla: 178090131 (~ 178 millones de filas)Primera consulta
Resultado de la primera consulta:
Segunda consulta
Resultado de la segunda consulta:
Puede notar que hay una diferencia de 83 (= 70265 - 70182) milisegundos que se pueden 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 tienen ninguna diferencia de rendimiento exhibida por el motor de SQL Server.
Nota : RAM alcanza casi el 100% de uso en ambas ejecuciones. Reinicié el servicio de SQL Server antes de iniciar ambas ejecuciones.
fuente
Lo he ejecutado cientos de veces, borrando la memoria 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 mayor tiempo de CPU.fuente
count(*)
ycount(1)
devolver resultados con unos pocos ms de diferencia, incluso cuando cuento una tabla con 4,5 millones de filas, en mi instancia de SQL 2008.Hay un artículo que muestra que
COUNT(1)
en Oracle es solo un aliasCOUNT(*)
, con una prueba al respecto.Citaré algunas partes:
Con un usuario con
ALTER SESSION
privilegios, se puede poner unatracefile_identifier
, que el trazado optimizador y ejecutar laCOUNT(1)
selección, como:SELECT /* test-1 */ COUNT(1) FROM employees;
.Después de eso, necesita localizar los archivos de rastreo, con qué se puede hacer
SELECT VALUE FROM V$DIAG_INFO WHERE NAME = 'Diag Trace';
. Más adelante en el archivo, encontrará:Como puede 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:Para otras bases de datos como Sql Server, debe investigarse 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 se marcaron como duplicadas de esta respuesta.
fuente
En todos los RDBMS, las dos formas de contar son equivalentes en términos del resultado que producen. Con respecto al rendimiento, no he observado ninguna diferencia de rendimiento en SQL Server, pero vale la pena señalar que algunos RDBMS, por ejemplo , PostgreSQL 11, tienen implementaciones menos óptimas
COUNT(1)
ya que verifican la nulabilidad de la expresión de argumento como se puede ver en esta publicación .He encontrado una diferencia de rendimiento del 10% para las filas de 1 millón cuando se ejecuta:
fuente
COUNT (1) no es sustancialmente diferente de COUNT (*), si es que lo hace. En cuanto a la cuestión de COUNTing NULLable COLUMNs, esto puede ser sencillo para demostrar las diferencias entre COUNT (*) y COUNT (<some col>) -
fuente