Las tablas de calendario implementan una compensación de espacio/tiempo. Al usar más espacio, algunos tipos de consultas se ejecutan en menos tiempo, ya que pueden aprovechar los índices. Son seguros siempre que tenga cuidado con las restricciones de CHECK() y siempre que tenga procesos administrativos para encargarse de cualquier restricción que su dbms no admita.
Si su granularidad es de un minuto, deberá generar aproximadamente medio millón de filas por año. Una tabla de calendario mínima se vería así.
2011-01-01 00:00:00
2011-01-01 00:01:00
2011-01-01 00:02:00
2011-01-01 00:03:00
2011-01-01 00:04:00
Si está haciendo un análisis de "cubo", es posible que esté mejor con algo como esto.
bucket_start bucket_end
--
2011-01-01 00:00:00 2011-01-01 00:01:00
2011-01-01 00:01:00 2011-01-01 00:02:00
2011-01-01 00:02:00 2011-01-01 00:03:00
2011-01-01 00:03:00 2011-01-01 00:04:00
2011-01-01 00:04:00 2011-01-01 00:05:00
Dado que el operador BETWEEN de SQL incluye los extremos, por lo general debe evitar su uso. Esto se debe a que incluye los puntos finales, y es difícil expresar bucket_end como "bucket_start más un minuto, menos el menor tiempo que este servidor pueda reconocer". (El peligro es un valor que es un microsegundo mayor que bucket_end, pero aún menor que el siguiente valor para bucket_start.)
Si fuera a construir esa tabla, probablemente lo haría así. (Aunque yo creo más difícil acerca de si debería llamarlo "calendario".)
create table calendar (
bucket_start timestamp primary key,
bucket_end timestamp unique,
CHECK (bucket_end = bucket_start + interval '1' minute)
-- You also want a "no gaps" constraint, but I don't think you
-- can do that in a CHECK constraint in PostgreSQL. You might
-- be able to use a trigger that counts the rows, and compares
-- that count to the number of minutes between min(bucket_start)
-- and max(bucket_start). Worst case, you can always run a report
-- that counts the rows and sends you an email.
);
La restricción UNIQUE crea un índice implícito en PostgreSQL.
Esta consulta insertará el valor de un día de filas (24 horas * 60 minutos) a la vez.
insert into calendar
select coalesce(
(select max(bucket_start) from calendar),
cast('2011-01-01 00:00:00' as timestamp)
)
+ cast((n || 'minute') as interval) as bucket_start,
coalesce(
(select max(bucket_start) from calendar),
cast('2011-01-01 00:00:00' as timestamp)
)
+ cast((n + 1 || ' minute') as interval) as bucket_end
from generate_series(1, (24*60)) n;
Puede envolver eso en una función para generar un año a la vez. Probablemente intentaré comprometer menos de medio millón de filas a la vez.
No debería tomar demasiado tiempo para generar 20 millones de filas para probar, y otras 20 millones de filas de minutos "calendario". Almuerzo largo. Tal vez una tarde en el sol.
What exactamente "ventaja de los índices" estás hablando? – Quassnoi