Muchas veces nos topamos con la tarea de saber cuales valores de cierta columna(s) son distintos de un conjunto de registros.

Normalmente lo hacemos con la clausula distinct, pues nos ahorra un par de palabras a la hora de escribir el query. Algo como:

select distinct(firstname) from test

Pero el mismo resultado obtenemos si lo hacemos de la siguiente forma:

select firstname from test group by firstname

Entonces, ¿cuál es la diferencia? La diferencia es que con una cantidad considerable de registros, podríamos reducir hasta 1 segundo en el query. Veámoslo con un ejemplo:

Tenemos la tabla test con los siguientes datos (Mostraré solo una parte de la tabla, para ver todos los datos vean el script):



Nombre
codigo1
codigo2
codigo3
Juan 2565368308 35763
Juan 87728636342562659891 2565188276 35801
Mohamad 25653346402565334648 2565334647 35801
Joel 2059330320 2059336400 35205
William 2058700123 2058700227 35209
William 2059789339 2058700227 35594
William 2058700123 2058700227 35202
Elia 2516079797 2058700227 36608
Elia 2516079797 2516390940 36532
Elia 2516079797 2516390940 36608
Elia 2516079797 2516390940 36545

Esta tabla tiene 100 registros y cuando hacemos un DISTINCT sobre la columna firstname el query tarda 110ms en promedio
mientras si lo hacemos con GROUP BY 93 ms. ¿17 ms se preguntarán? Pero si eso sucede con 100 registros y sin nadie más usando la BD, imagínense lo significativo que es el cambio con 2 millones de registros y varias personas haciendo el mismo query al mismo tiempo.

¿A que se debe la diferencia?

Si vemos el plan de ejecución podríamos observar lo siguientes:


-- query con DISTINCT
‘Unique (cost=37.41..39.91 rows=200 width=32) (actual time=0.380..0.462 rows=49 loops=1)’
‘ -> Sort (cost=37.41..38.66 rows=500 width=32) (actual time=0.379..0.409 rows=100 loops=1)’
‘ Sort Key: firstname’
‘ -> Seq Scan on test (cost=0.00..15.00 rows=500 width=32) (actual time=0.015..0.093 rows=100 loops=1)’
‘Total runtime: 0.495 ms’

Aquí el costo de hacer un recorrido secuencial y luego sort, unique es el que aumenta en total el tiempo de ejecución, mientras


-- Haciendo un query con GROUP BY
'HashAggregate (cost=16.25..18.25 rows=200 width=32) (actual time=0.145..0.165 rows=49 loops=1)'
' -> Seq Scan on test (cost=0.00..15.00 rows=500 width=32) (actual time=0.013..0.052 rows=100 loops=1)'
'Total runtime: 0.201 ms'

Se realiza un recorrido secuencial pero se utiliza una función Hash que es más rápida que el sort y el unique.

Así que aunque nos lleve un poco más de tiempo escribir un query con GROUP BY, vamos a recuperarlo cada vez que se ejecute dicho query.

Bueno, pues, una vez más, espero que les sirva y hasta la próxima.

Por cierto, esperen una oleada de artículos entre hoy y mañana pues vamos tratar de subir el nivel del Blog.

Deja un comentario

Cerrar
Enviar por Correo