Verificar si una tablatiene datos ...

29/10/2007 - 20:36 por Peni | Informe spam
Que es más rápido en general, hacer un select count(*)... where o un
select top 1 ... where?


=Saludos. Peni.
=

Preguntas similare

Leer las respuestas

#11 jeastman - Hotmail
30/10/2007 - 02:01 | Informe spam
Señores.

Me tomé la libertad de hacer la prueba que sugiere el compañero José
Mariano, para ello creé una tabla con 2.342.560 de registros y sin ningún
indice primero y luego con un índice clustered, las pruebas las hice en el
mismo orden que las mostró el compañero y los resultados fueron los
siguiente:


SIN ÍNDICES
=count(*) (4080) milisegundos
select 1 (7156) milisegundos
select top 1 * (13) milisegundos
select top 1 1 (0) milisegundos
if exists (select *... (16) milisegundos
if exists (select 1... (0) milisegundos
if (select count(*)...) > 0 (4033) milisegundos


CON ÍNDICE CLUSTERED
==count(*) (10923) milisegundos
select 1 (12310) milisegundos
select top 1 * (46) milisegundos
select top 1 1 (0) milisegundos
if exists (select *... (13) milisegundos
if exists (select 1... (0) milisegundos
if (select count(*)...) > 0 (11690) milisegundos

Los resultados demuestran que existen dos opciones que supera a cualquier
otra con o sin índices

1) select top 1 1 (0) milisegundos
2) if exists(select 1 from aaa ) print 'tiene filas' else print 'NO tiene
filas'

Aqui les anexo el script que utilicé para la prueba

Saludos a todos.


P.D. Si alguien obtiene algún resultado diferente, me gustaría conocer los
resultados.

Este es el script de la tabla
CREATE TABLE aaa (
CorrelMovimiento int NOT NULL ,
CodEstructura int NOT NULL ,
CodPartida int NOT NULL ,
CodUsuario int NOT NULL ,
NroPresupuesto int NOT NULL ,
TipoMovimiento tinyint NOT NULL ,
PresupuestoOrd money NOT NULL ,
FIDES money NOT NULL ,
LAES money NOT NULL ,
Otras money NOT NULL ,
Observacion varchar (255) NOT NULL ,
FechaAgregado datetime NOT NULL ,
FechaCierre datetime NOT NULL
)


y el índice lo hice por los campos correlMovimiento y nroPresupuesto, estaba
seguro que podía hacer un índice único por esos valores


y el íindice lo hice
declare @inicio datetime,
@fin datetime,
@dif int



DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
set @inicio = getdate()
select count(*) from aaa
set @fin = getdate()
set @dif = datediff( ms, @inicio, @fin )
print 'count(*) (' + cast( @dif as varchar ) + ') milisegundos'

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
set @inicio = getdate()
select 1 from aaa
set @fin = getdate()
set @dif = datediff( ms, @inicio, @fin )
print 'select 1 (' + cast( @dif as varchar ) + ') milisegundos'

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
set @inicio = getdate()
select top 1 * from aaa
set @fin = getdate()
set @dif = datediff( ms, @inicio, @fin )
print 'select top 1 * (' + cast( @dif as varchar ) + ') milisegundos'

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
set @inicio = getdate()
select top 1 1 from aaa
set @fin = getdate()
set @dif = datediff( ms, @inicio, @fin )
print 'select top 1 1 (' + cast( @dif as varchar ) + ') milisegundos'

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
set @inicio = getdate()
if exists(select * from aaa ) print 'tiene filas' else
print 'NO tiene filas'
set @fin = getdate()
set @dif = datediff( ms, @inicio, @fin )
print 'if exists (select *... (' + cast( @dif as varchar ) + ')
milisegundos'

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
set @inicio = getdate()
if exists(select 1 from aaa ) print 'tiene filas' else
print 'NO tiene filas'
set @fin = getdate()
set @dif = datediff( ms, @inicio, @fin )
print 'if exists (select 1... (' + cast( @dif as varchar ) + ')
milisegundos'


DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
set @inicio = getdate()
if (select count(*) from aaa ) > 0 print 'tiene filas'
else print 'NO tiene filas'
set @fin = getdate()
set @dif = datediff( ms, @inicio, @fin )
print 'if (select count(*)...) > 0 (' + cast( @dif as varchar ) + ')
milisegundos'


"Jose Mariano Alvarez"
escribió en el
mensaje news:e%
Los dos son igualmente malos.
Es mejor como dice alejandro, usando TOP 1 o usando el cuantificador
existencial.

Prueba esto con la base de datos de ejemplo y mira los pesos relativos.

select count(*) from dbo.FactInternetSales
select 1 from dbo.FactInternetSales
select top 1 * from dbo.FactInternetSales
select top 1 1 from dbo.FactInternetSales
if exists(select * from dbo.FactInternetSales ) print 'tiene filas' else
print 'NO tiene filas'
if exists(select 1 from dbo.FactInternetSales ) print 'tiene filas' else
print 'NO tiene filas'
if (select count(*) from dbo.FactInternetSales ) > 0 print 'tiene filas'
else print 'NO tiene filas'



Saludos
Ing. Jose Mariano Alvarez


(Cambia los ceros por O y saca lo que sobra)


IMPORTANTE

Por favor traten de indicar la versión de SQL y Service Pack.
La inclusión de (CREATE, INSERTS, etc.) para poder reproducir el problema
también ayuda.



"jeastman - Hotmail" wrote in message
news:e%238$
Hola.

Yo hice una prueba con éstas dos versiones:

select count(*) from tabla

y la segunda versión fue:

if exists (select 1 from tabla)
begin
print 'Existe'
end

La tabla es muy pequeña, solo tiene 73.205 registros

En la primera forma me dio un segundo, en la segunda no llegó al segundo.

Yo personalmente utilizo la segunda alternativa, pues le dejo el trabajo
al obtimizador de buscar la mejor manera de averiguar si hay o no
registros, el 1 que está en el select es para evitar colocar un * que en
éste caso no hace falta.

Si obtienen otros resultados y alguna mejor vía me gustaría conocerla y
así evitarle trabajo al motor.

Saludos.

"Leonardo Azpurua" <l e o n a r d o [arroba] m v p s [punto] o r g>
escribió en el mensaje news:

"Penta" escribió en el mensaje
news:
Con el top de toda maneras, si haces un count(*) de una tabla de
muchos registros = se toma su tiempo.



Igual hay quien sabe mas que nosotros de SQL Server y me corrige, pero
creo que el COUNT(*) lo unico que hace es examinar el descriptor de la
tabla, o sea que debe ser mucho más rápido.

Salud!










Respuesta Responder a este mensaje
#12 Peni
30/10/2007 - 07:30 | Informe spam
Aclarado, muchismimas gracias :-)))

Señores.

Me tomé la libertad de hacer la prueba que sugiere el compañero José Mariano,
para ello creé una tabla con 2.342.560 de registros y sin ningún indice
primero y luego con un índice clustered, las pruebas las hice en el mismo
orden que las mostró el compañero y los resultados fueron los siguiente:


SIN ÍNDICES
=> count(*) (4080) milisegundos
select 1 (7156) milisegundos
select top 1 * (13) milisegundos
select top 1 1 (0) milisegundos
if exists (select *... (16) milisegundos
if exists (select 1... (0) milisegundos
if (select count(*)...) > 0 (4033) milisegundos


CON ÍNDICE CLUSTERED
==> count(*) (10923) milisegundos
select 1 (12310) milisegundos
select top 1 * (46) milisegundos
select top 1 1 (0) milisegundos
if exists (select *... (13) milisegundos
if exists (select 1... (0) milisegundos
if (select count(*)...) > 0 (11690) milisegundos

Los resultados demuestran que existen dos opciones que supera a cualquier
otra con o sin índices

1) select top 1 1 (0) milisegundos
2) if exists(select 1 from aaa ) print 'tiene filas' else print 'NO tiene
filas'

Aqui les anexo el script que utilicé para la prueba

Saludos a todos.


P.D. Si alguien obtiene algún resultado diferente, me gustaría conocer los
resultados.

Este es el script de la tabla
CREATE TABLE aaa (
CorrelMovimiento int NOT NULL ,
CodEstructura int NOT NULL ,
CodPartida int NOT NULL ,
CodUsuario int NOT NULL ,
NroPresupuesto int NOT NULL ,
TipoMovimiento tinyint NOT NULL ,
PresupuestoOrd money NOT NULL ,
FIDES money NOT NULL ,
LAES money NOT NULL ,
Otras money NOT NULL ,
Observacion varchar (255) NOT NULL ,
FechaAgregado datetime NOT NULL ,
FechaCierre datetime NOT NULL
)


y el índice lo hice por los campos correlMovimiento y nroPresupuesto, estaba
seguro que podía hacer un índice único por esos valores


y el íindice lo hice
> declare @inicio datetime,
@fin datetime,
@dif int



DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
set @inicio = getdate()
select count(*) from aaa
set @fin = getdate()
set @dif = datediff( ms, @inicio, @fin )
print 'count(*) (' + cast( @dif as varchar ) + ') milisegundos'

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
set @inicio = getdate()
select 1 from aaa
set @fin = getdate()
set @dif = datediff( ms, @inicio, @fin )
print 'select 1 (' + cast( @dif as varchar ) + ') milisegundos'

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
set @inicio = getdate()
select top 1 * from aaa
set @fin = getdate()
set @dif = datediff( ms, @inicio, @fin )
print 'select top 1 * (' + cast( @dif as varchar ) + ') milisegundos'

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
set @inicio = getdate()
select top 1 1 from aaa
set @fin = getdate()
set @dif = datediff( ms, @inicio, @fin )
print 'select top 1 1 (' + cast( @dif as varchar ) + ') milisegundos'

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
set @inicio = getdate()
if exists(select * from aaa ) print 'tiene filas' else
print 'NO tiene filas'
set @fin = getdate()
set @dif = datediff( ms, @inicio, @fin )
print 'if exists (select *... (' + cast( @dif as varchar ) + ') milisegundos'

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
set @inicio = getdate()
if exists(select 1 from aaa ) print 'tiene filas' else
print 'NO tiene filas'
set @fin = getdate()
set @dif = datediff( ms, @inicio, @fin )
print 'if exists (select 1... (' + cast( @dif as varchar ) + ') milisegundos'


DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
set @inicio = getdate()
if (select count(*) from aaa ) > 0 print 'tiene filas'
else print 'NO tiene filas'
set @fin = getdate()
set @dif = datediff( ms, @inicio, @fin )
print 'if (select count(*)...) > 0 (' + cast( @dif as varchar ) + ')
milisegundos'
>

"Jose Mariano Alvarez"
escribió en el
mensaje news:e%
Los dos son igualmente malos.
Es mejor como dice alejandro, usando TOP 1 o usando el cuantificador
existencial.

Prueba esto con la base de datos de ejemplo y mira los pesos relativos.

select count(*) from dbo.FactInternetSales
select 1 from dbo.FactInternetSales
select top 1 * from dbo.FactInternetSales
select top 1 1 from dbo.FactInternetSales
if exists(select * from dbo.FactInternetSales ) print 'tiene filas' else
print 'NO tiene filas'
if exists(select 1 from dbo.FactInternetSales ) print 'tiene filas' else
print 'NO tiene filas'
if (select count(*) from dbo.FactInternetSales ) > 0 print 'tiene filas'
else print 'NO tiene filas'



Saludos
Ing. Jose Mariano Alvarez


(Cambia los ceros por O y saca lo que sobra)


IMPORTANTE

Por favor traten de indicar la versión de SQL y Service Pack.
La inclusión de (CREATE, INSERTS, etc.) para poder reproducir el problema
también ayuda.



"jeastman - Hotmail" wrote in message
news:e%238$
Hola.

Yo hice una prueba con éstas dos versiones:

select count(*) from tabla

y la segunda versión fue:

if exists (select 1 from tabla)
begin
print 'Existe'
end

La tabla es muy pequeña, solo tiene 73.205 registros

En la primera forma me dio un segundo, en la segunda no llegó al segundo.

Yo personalmente utilizo la segunda alternativa, pues le dejo el trabajo
al obtimizador de buscar la mejor manera de averiguar si hay o no
registros, el 1 que está en el select es para evitar colocar un * que en
éste caso no hace falta.

Si obtienen otros resultados y alguna mejor vía me gustaría conocerla y
así evitarle trabajo al motor.

Saludos.

"Leonardo Azpurua" <l e o n a r d o [arroba] m v p s [punto] o r g>
escribió en el mensaje news:

"Penta" escribió en el mensaje
news:
Con el top de toda maneras, si haces un count(*) de una tabla de
muchos registros = se toma su tiempo.



Igual hay quien sabe mas que nosotros de SQL Server y me corrige, pero
creo que el COUNT(*) lo unico que hace es examinar el descriptor de la
tabla, o sea que debe ser mucho más rápido.

Salud!
















=Saludos. Peni.
=
Respuesta Responder a este mensaje
#13 Rubén Vigón
30/10/2007 - 09:09 | Informe spam
¿Y consultando el número de filas del índice agrupado de la tabla?

SELECT i.rowcnt FROM sysindexes i INNER JOIN sysobjects o ON i.id = o.id WHERE o.name = 'NombreTabla' and i.indid = 1

Un saludo!

Rubén Vigón
Microsoft MVP Visual Basic
http://vigon.mvps.org
Respuesta Responder a este mensaje
#14 Rubén Vigón
30/10/2007 - 09:19 | Informe spam
Por cierto, si no quieres hacer el INNER JOIN con sysobjects, puedes usar OBJECT_ID:

SELECT rowcnt FROM sysindexes WHERE id = OBJECT_ID('NombreTabla') AND indid = 1

Un saludo!

Rubén Vigón
Microsoft MVP Visual Basic
http://vigon.mvps.org
Respuesta Responder a este mensaje
#15 jeastman - Hotmail
30/10/2007 - 11:40 | Informe spam
Que tal Rubén...

Hice la pueba con la misma tabla, misma máquina los resultados fueron:


SELECT i.rowcnt FROM sysindexes i INNER JOIN sysobjects o ON i.id = o.id
WHERE o.name = 'aaa' and i.indid = 1 (46) milisegundos
SELECT rowcnt FROM sysindexes WHERE id = OBJECT_ID('aaa') AND indid = 1 (16)
milisegundos


SELECT i.rowcnt FROM sysindexes i INNER JOIN sysobjects o ON i.id = o.id
WHERE o.name = 'aaa' and i.indid = 1 (30) milisegundos
SELECT rowcnt FROM sysindexes WHERE id = OBJECT_ID('aaa') AND indid = 1 (0)
milisegundos


Por algún motivo que desconozco los resultados entre una ejecución y otra
variaban, cosa que no pasó con los otros métodos, dando la impresión que las
opciones no son tan estables.

Saludos.

"Rubén Vigón" escribió en el mensaje
news:%
Por cierto, si no quieres hacer el INNER JOIN con sysobjects, puedes usar
OBJECT_ID:

SELECT rowcnt FROM sysindexes WHERE id = OBJECT_ID('NombreTabla') AND indid
= 1

Un saludo!

Rubén Vigón
Microsoft MVP Visual Basic
http://vigon.mvps.org
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida