Sql 在Postgres中将时间戳缩短为5分钟的最快方法是什么?

Sql 在Postgres中将时间戳缩短为5分钟的最快方法是什么?,sql,performance,postgresql,datetime,Sql,Performance,Postgresql,Datetime,Postgres可以使用date_trunc函数舍入(截断)时间戳,如下所示: date_trunc('hour', val) date_trunc('minute', val) date_trunc('hour', val) + date_part('minute', val)::int / 5 * interval '5 min' 我正在寻找一种方法,将时间戳截断到最近的5分钟边界,例如,14:26:57变为14:25:00。最简单的方法是: date_trunc('hour', val

Postgres可以使用date_trunc函数舍入(截断)时间戳,如下所示:

date_trunc('hour', val)
date_trunc('minute', val)
date_trunc('hour', val) + date_part('minute', val)::int / 5 * interval '5 min'
我正在寻找一种方法,将时间戳截断到最近的5分钟边界,例如,14:26:57变为14:25:00。最简单的方法是:

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

由于这是查询的性能关键部分,我想知道这是否是最快的解决方案,或者是否有一些我忽略的快捷方式(与Postgres 8.1+兼容)。

我认为没有任何更快的方法

我认为你不应该担心这个表达的表现


执行(SELECT,UPDATE,…)语句所涉及的所有其他内容(例如,检索行的I/O)很可能比该日期/时间计算要昂贵得多。

那些想知道的人的完整查询(基于@DNS问题):

假设您有订单,并希望按5分钟的时间段和店铺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

我也在想同样的事情。我找到了两种替代方法,但你建议的方法更快

我非正式地以我们的一张较大的桌子为基准。我将查询限制在前400万行。我在两个查询之间交替进行,以避免由于数据库缓存而给一个查询带来不公平的优势


穿越epoch/unix时代 (注意,即使使用了时区不知道的数据类型,也会产生
timestamptz

结果

  • 运行1:39.368秒
  • 运行3:39.526秒
  • 运行5:39.883秒

使用date\u trunc和date\u part 结果

  • 运行2:34.189秒
  • 运行4:37.028秒
  • 运行6:32.397秒

系统

  • DB版本:x86_64-pc-linux-gnu上的PostgreSQL 9.6.2,由gcc(Ubuntu 4.8.2-19ubuntu1)4.8.2编译,64位
  • 核心:英特尔至强、E5-1650v2、六核
  • RAM:64 GB,DDR3 ECC RAM
结论
你的版本似乎更快。但是对于我的特定用例来说速度不够快。不必指定小时的优点使epoch版本更通用,并在客户端代码中生成更简单的参数化。它可以处理
2小时
间隔和
5分钟
间隔,而不必增加
date\u trunc
时间单位参数。最后,我希望将此时间单位参数改为时间间隔参数。

为什么不将其转换为函数,然后对其进行索引,看看它的速度有多快?或者只是在完全相同的逻辑上建立索引,而不将其包装在索引中。无论哪种方法,你都会知道它的速度有多快。请注意,这种方法似乎不会向上取整到“最近的”边界,而是向下取整到下一个最低的边界。i、 e.“2017-04-01 00:04:00”似乎四舍五入为“2017-04-01 00:00:00”,而不是最近的边界,即“2017-04-01 00:05:00”。使用Django ORM功能后,该操作很快就会简单得多?关于如何在没有自定义SQL查询的情况下执行此操作的任何想法。第一个版本应该使用
floor
而不是强制转换为int-因为强制转换可能会导致错误的结果(
选择0.9::int--=1
)@Pyrocks非常感谢。我在博士后工作了很多年,现在是我第一次了解到用整数“舍入”而不是“截断”小数。我遇到的所有编程语言都会截断,所以我假设它适用于postgres(和其他数据库?)。我已经更新了答案,但没有时间重新运行查询。我希望这不会影响太多。