Miles y miles y miles de veces veo que se arman consultas SQL que contiene el COUNT(1). Este es un viejo mito. Muchos piensan que colocar COUNT(1) en vez del COUNT(*) mejora la performance de la consulta.... pero en realidad mejora la performance?
Veamos...
Bien, ahora ejecutemos las 2 consultas:
Veamos lo que nos muestra el TKPROF:
Observamos que en las 2 consultas tenemos la misma cantidad de lecturas de bloques (disk, query, current) y el mismo tiempo de elapsed y cpu.
Las 2 consultas son idénticas y no hay un incremento en la performance por utilizar el COUNT(1) en vez del COUNT(*).
Incluso podría poner cualquier cosa en el COUNT... obtendríamos los mismos resultados:
Bien, por último veamos los siguiente. Qué sucede si realizo un COUNT de alguna de las columnas de la tabla? Veamos...
La consulta nos devolvió la cantidad de registros totales de la tabla. Ahora veamos qué me devuelve la consulta si la columna TEXTO tiene valores nulos.
Como podemos observar, el COUNT sobre una columna sólo cuenta la cantidad de valores que no son nulos. Por lo tanto, tenemos que tener cuidado a la hora de realizar un COUNT y tener en cuenta estos pequeños detalles.
Veamos...
SQL_9iR2> CREATE TABLE test AS
2 SELECT level id, 'texto_'||level texto
3 FROM dual
4 CONNECT BY level <= 100000 ; Table created. SQL_9iR2> EXEC dbms_stats.GATHER_TABLE_STATS(USER,'TEST') ;
PL/SQL procedure successfully completed.
Bien, ahora ejecutemos las 2 consultas:
SQL_9iR2> ALTER SESSION SET SQL_TRACE = TRUE ;
Session altered.
SQL_9iR2> SELECT COUNT(1)
2 FROM test ;
COUNT(1)
----------
100000
1 row selected.
SQL_9iR2> SELECT COUNT(*)
2 FROM test ;
COUNT(*)
----------
100000
1 row selected.
SQL_9iR2> ALTER SESSION SET SQL_TRACE = FALSE ;
Session altered.
Veamos lo que nos muestra el TKPROF:
select count(1)
from
test
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.01 0.01 0 306 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.01 0.01 0 306 0 1
select count(*)
from
test
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.01 0.01 0 306 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.01 0.01 0 306 0 1
Observamos que en las 2 consultas tenemos la misma cantidad de lecturas de bloques (disk, query, current) y el mismo tiempo de elapsed y cpu.
Las 2 consultas son idénticas y no hay un incremento en la performance por utilizar el COUNT(1) en vez del COUNT(*).
Incluso podría poner cualquier cosa en el COUNT... obtendríamos los mismos resultados:
SELECT COUNT(2222222)
FROM
TEST
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.01 0.01 0 306 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.01 0.01 0 306 0 1
SELECT COUNT('EJEMPLO')
FROM
TEST
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.01 0.01 0 306 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.01 0.01 0 306 0 1
SELECT COUNT(12345)
FROM
TEST
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.01 0.01 0 306 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.01 0.01 0 306 0 1
Bien, por último veamos los siguiente. Qué sucede si realizo un COUNT de alguna de las columnas de la tabla? Veamos...
SQL_9iR2> SELECT COUNT(texto)
2 FROM test ;
COUNT(TEXTO)
------------
100000
1 row selected.
La consulta nos devolvió la cantidad de registros totales de la tabla. Ahora veamos qué me devuelve la consulta si la columna TEXTO tiene valores nulos.
SQL_9iR2> UPDATE test
2 SET texto = NULL
3 WHERE id > 50000 ;
50000 rows updated.
SQL_9iR2> EXEC dbms_stats.GATHER_TABLE_STATS(USER,'TEST') ;
PL/SQL procedure successfully completed.
SQL_9iR2> SELECT COUNT(texto)
2 FROM test ;
COUNT(TEXTO)
------------
50000
1 row selected.
Como podemos observar, el COUNT sobre una columna sólo cuenta la cantidad de valores que no son nulos. Por lo tanto, tenemos que tener cuidado a la hora de realizar un COUNT y tener en cuenta estos pequeños detalles.