Napadlo mě to samé. Našel jsem dva alternativní způsoby, jak to udělat, ale ten, který jste navrhl, byl rychlejší.
Neformálně jsem porovnal s jedním z našich větších stolů. Dotaz jsem omezil na první 4 miliony řádků. Střídal jsem tyto dva dotazy, abych se vyhnul neoprávněné výhodě jednoho z důvodu ukládání do mezipaměti databáze.
Procházení epochou/unixovým časem
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
(Všimněte si, že to vytváří timestamptz
i když jste použili datový typ bez vědomí časového pásma)
Výsledky
- Spustit 1 :39,368 sekund
- Spustit 3 :39,526 sekund
- Spustit 5 :39,883 sekund
Použití date_trunc a 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
Výsledky
- Spustit 2 :34,189 sekund
- Spustit 4 :37,028 sekund
- Spustit 6 :32,397 sekund
Systém
- Verze DB:PostgreSQL 9.6.2 na x86_64-pc-linux-gnu, zkompilovaný gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2, 64-bit
- Jádra:Intel® Xeon®, E5-1650v2, Hexa-Core
- RAM:64 GB, DDR3 ECC RAM
Závěr
Vaše verze se zdá být rychlejší. Ale ne dost rychle pro můj konkrétní případ použití. Díky tomu, že není nutné specifikovat hodinu, je epochová verze všestrannější a umožňuje jednodušší parametrizaci v kódu na straně klienta. Zpracovává 2 hour
intervalech stejně dobře jako 5 minute
intervalech, aniž by bylo nutné změnit parametr date_trunc
časová jednotka argument nahoru. Na závěr bych si přál, aby se tento argument časové jednotky místo toho změnil na argument časového intervalu.