Me preguntaba lo mismo. Encontré dos formas alternativas de hacer esto, pero la que sugeriste fue más rápida.
Me comparé informalmente con una de nuestras mesas más grandes. Limité la consulta a los primeros 4 millones de filas. Alterné entre las dos consultas para evitar darle una ventaja injusta debido al almacenamiento en caché de db.
Pasando por época/tiempo unix
SELECT to_timestamp(
floor(EXTRACT(epoch FROM ht.time) / EXTRACT(epoch FROM interval '5 min'))
* EXTRACT(epoch FROM interval '5 min')
) FROM huge_table AS ht LIMIT 4000000
(Tenga en cuenta que esto produce timestamptz
incluso si utilizó un tipo de datos que desconoce la zona horaria)
Resultados
- Ejecución 1 :39,368 segundos
- Ejecución 3 :39,526 segundos
- Ejecución 5 :39,883 segundos
Usando date_trunc y date_part
SELECT
date_trunc('hour', ht.time)
+ date_part('minute', ht.time)::int / 5 * interval '5 min'
FROM huge_table AS ht LIMIT 4000000
Resultados
- Ejecución 2 :34,189 segundos
- Corrida 4 :37.028 segundos
- Ejecución 6 :32.397 segundos
Sistema
- Versión de base de datos:PostgreSQL 9.6.2 en x86_64-pc-linux-gnu, compilado por gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2, 64 bits
- Núcleos:Intel® Xeon®, E5-1650v2, Hexa-Core
- RAM:64 GB, RAM DDR3 ECC
Conclusión
Su versión parece ser más rápida. Pero no lo suficientemente rápido para mi caso de uso específico. La ventaja de no tener que especificar la hora hace que la versión de época sea más versátil y produce una parametrización más sencilla en el código del lado del cliente. Maneja 2 hour
intervalos tan buenos como 5 minute
intervalos sin tener que cambiar el date_trunc
argumento de unidad de tiempo arriba. En una nota final, desearía que este argumento de unidad de tiempo se cambiara a un argumento de intervalo de tiempo.