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

7kqas0il  于 2023-01-25  发布在  PostgreSQL
关注(0)|答案(4)|浏览(292)

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+兼容)。

qcuzuvrc

qcuzuvrc1#

我也在想同样的事情。我找到了两种替代方法来做这件事,但你建议的那个更快。
我非正式地对我们的一个较大的表进行了基准测试。我将查询限制在前400万行。我在两个查询之间交替进行,以避免由于数据库缓存而给一个不公平的优势。

经历纪元/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

(Note即使您使用的是时区未知数据类型,也会生成timestamptz

    • 结果**
      • 运行1**:39.368秒
      • 运行3**:39.526秒
      • 运行5**:39.883秒

使用日期截断和日期部分

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秒
    • 系统**
  • 数据库版本:x86_64-pc-linux-gnu上的PostgreSQL 9.6.2,由gcc(Ubuntu 4.8.2 - 19ubuntu1)4.8.2编译,64位
  • 核心:英特尔®至强®,E5 - 1650v2,六核
  • 内存:64 GB,DDR3 ECC内存

结论

您的版本似乎更快。但对于我的特定用例来说还不够快。不必指定小时的优点使epoch版本更通用,并在客户端代码中产生更简单的参数化。它处理2 hour间隔和5 minute间隔一样好,而不必增加date_trunc时间单位参数。最后,我希望这个时间单位参数改为时间间隔参数。

jchrr9hc

jchrr9hc2#

我认为没有更快的方法了。
我觉得你不必担心这个表情的表现。
执行(SELECT,UPDATE,...)语句所涉及的其他所有操作(例如,检索行的I/O)很可能比日期/时间计算的开销大得多。

shyt4zoc

shyt4zoc3#

完整查询(基于@DNS问题):
假设您有订单,并且希望按5 min和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
ftf50wuq

ftf50wuq4#

Postgres 14以来,date_bin()最简单和最快的

date_bin('5 min', val, '2000-1-1')

本手册:
函数date_bin将输入时间戳"装入"与指定原点对齐的指定间隔(步幅)。
x1米2米1 x(x1米3米1 x,x1米4米1 x,x1米5米1 x)

***source***是timestamptimestamp with time zone类型的值表达式。(date类型的值自动转换为timestamp。)***stride是interval类型的值表达式。返回值同样为timestamptimestamp with time zone类型。并且它标记了source***被放置到其中的仓的开始。

提供匹配数据类型的"原点",以避免由于忽略时区或假定错误时区的强制转换而产生意外结果。
我的例子 * 看起来 * 像date文本,但也可以作为有效的timestamp文本。如果缺少时间部分,则假定为'00:00'。
相关:

  • 在PostgreSQL中生成两个日期之间的时间序列

相关问题