Каков самый быстрый способ обрезать временные метки до 5 минут в Postgres?

Postgres может округлять (сокращать) временные метки, используя функцию date_trunc, например:

date_trunc('hour', val)
date_trunc('minute', val)

Я ищу способ обрезать временную метку до ближайшей 5-минутной границы, так что, например, 14:26:57 становится 14:25:00. Прямой способ сделать это выглядит следующим образом:

date_trunc('hour', val) + date_part('minute', val)::int / 5 * interval '5 min'

Поскольку это критически важная часть запроса, мне интересно, является ли это самым быстрым решением, или есть ли какой-либо ярлык (совместимый с Postgres 8.1+), который я упустил.

4b9b3361

Я не думаю, что есть более быстрый метод.

И я не думаю, что вы должны беспокоиться о производительности выражения.

Все, что связано с выполнением вашего (SELECT, UPDATE,...) оператора, скорее всего, намного дороже (например, ввод-вывод для извлечения строк), чем этот расчет даты/времени.

9
ответ дан 04 сент. '11 в 15:54
источник

Мне было интересно то же самое. Я нашел два альтернативных способа сделать это, но тот, который вы предложили, был быстрее.

Я неофициально сравнивал один из наших больших таблиц. Я ограничил запрос на первые 4 миллиона строк. Я чередовался между двумя запросами, чтобы избежать предоставления одного несправедливого преимущества из-за кэширования db.


Переход через эпоху/время unix

SELECT to_timestamp(
    (EXTRACT(epoch FROM ht.time) / EXTRACT(epoch FROM interval '5 min'))::int 
    * 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
  • ОЗУ: 64 ГБ, DDR3 ECC RAM

Заключение

Ваша версия выглядит быстрее. Но не достаточно быстро для моего конкретного случая использования. Преимущество в том, что не нужно указывать час, делает версию эпохи более универсальной и упрощает параметризацию в клиентском коде. Он обрабатывает интервалы 2 hour так же, как и интервалы 5 minute, не увеличивая аргумент единицы времени date_trunc. В конце примечание, я бы хотел, чтобы этот аргумент единицы времени был изменен на аргумент временного интервала.

3
ответ дан 26 марта '17 в 15:37
источник

Полный запрос для интересующихся (на основе вопроса @DNS):

Предполагая, что у вас есть заказы, и вы хотите подсчитать их на кусочки 5 минут и shop_id:

SELECT date_trunc('hour', created_at) + date_part('minute', created_at)::int / 5 * interval '5 min' AS minute
      , shop_id, count(id) as orders_count
FROM orders
GROUP BY 1, shop_id
ORDER BY 1 ASC
0
ответ дан 06 апр. '16 в 13:22
источник