И аз се чудех същото. Намерих два алтернативни начина да направя това, но този, който предложихте, беше по-бърз.
Неофициално направих сравнение с една от нашите по-големи маси. Ограничих заявката до първите 4 милиона реда. Редувах между двете заявки, за да избегна да давам на една несправедливо предимство поради кеширане на db.
Преминаване през epoch/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
(Обърнете внимание, че това произвежда timestamptz
дори ако сте използвали неизвестен тип данни за часова зона)
Резултати
- Изпълнете 1 :39,368 секунди
- Изпълнете 3 :39,526 секунди
- Изпълнете 5 :39,883 секунди
Използване на date_trunc и 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
Резултати
- Изпълнете 2 :34,189 секунди
- Изпълнете 4 :37,028 секунди
- Изпълнете 6 :32,397 секунди
Система
- DB версия:PostgreSQL 9.6.2 на x86_64-pc-linux-gnu, компилиран от gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2, 64-битов
- Ядра:Intel® Xeon®, E5-1650v2, Hexa-Core
- RAM:64 GB, DDR3 ECC RAM
Заключение
Версията ви изглежда е по-бърза. Но не достатъчно бързо за моя конкретен случай на употреба. Предимството да не се налага да се посочва часът прави епохалната версия по-гъвкава и произвежда по-проста параметризация в кода от страна на клиента. Обработва 2 hour
интервали точно както 5 minute
интервали, без да се налага да блъскате date_trunc
аргумент за единица време нагоре. В крайна сметка бих искал вместо това този аргумент за времева единица да бъде променен на аргумент за интервал от време.