Zastanawiałem się nad tym samym. Znalazłem dwa alternatywne sposoby na zrobienie tego, ale ten, który zasugerowałeś, był szybszy.
Nieformalnie porównałem jeden z naszych większych stołów. Ograniczyłem zapytanie do pierwszych 4 milionów wierszy. Zmieniałem te dwa zapytania, aby uniknąć nieuczciwej przewagi ze względu na buforowanie bazy danych.
Przechodzenie przez epokę/czas uniksowy
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
(Zauważ, że to daje timestamptz
nawet jeśli użyłeś typu danych nie rozpoznającego strefy czasowej)
Wyniki
- Uruchom 1 :39,368 sekund
- Uruchom 3 :39,526 sekund
- Uruchom 5 :39,883 sekundy
Korzystanie z date_trunc i 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
Wyniki
- Uruchom 2 :34,189 sekund
- Uruchom 4 :37.028 sekund
- Uruchom 6 :32,397 sekund
System
- Wersja DB:PostgreSQL 9.6.2 na x86_64-pc-linux-gnu, skompilowany przez gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2, 64-bitowy
- Rdzenie:Intel® Xeon®, E5-1650v2, sześciordzeniowy
- RAM:64 GB, DDR3 ECC RAM
Wniosek
Twoja wersja wydaje się szybsza. Ale nie wystarczająco szybko dla mojego konkretnego przypadku użycia. Zaleta braku konieczności określania godziny sprawia, że wersja epoki jest bardziej wszechstronna i zapewnia prostszą parametryzację w kodzie po stronie klienta. Obsługuje 2 hour
interwały tak samo jak 5 minute
interwały bez konieczności wbijania date_trunc
argument jednostki czasu w górę. Na koniec chciałbym, aby ten argument jednostki czasu został zmieniony na argument przedziału czasu.