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

时间:2011-09-04 12:52:16

标签: sql performance postgresql datetime

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

3 个答案:

答案 0 :(得分:14)

我认为没有更快的方法。

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

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

答案 1 :(得分:8)

我想知道同样的事情。我找到了两种替代方法,但你提出的方法更快。

我非正式地对照了一个较大的表格。我将查询限制在前400万行。我在两个查询之间进行了交替,以避免因db缓存而给予一个不公平的优势。

通过epoch / 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,即使你使用了时区unaware数据类型)

<强>结果

  • 运行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秒

<强>系统

  • 数据库版本:x86_64-pc-linux-gnu上的PostgreSQL 9.6.2,由gcc编译(Ubuntu 4.8.2-19ubuntu1)4.8.2,64位
  • 核心:Intel®Xeon®,E5-1650v2,Hexa-Core
  • RAM:64 GB,DDR3 ECC RAM

结论

您的版本似乎更快。但对于我的具体用例来说还不够快。不必指定小时的优点使得epoch版本更加通用并且在客户端代码中产生更简单的参数化。它处理2 hour间隔以及5 minute间隔,而不必将date_trunc时间单位参数提升。最后,我希望将时间单位参数更改为时间间隔参数。

答案 2 :(得分:0)

完全查询那些想知道的人(基于@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