DNS*_*DNS 42 sql postgresql performance datetime
Postgres可以使用date_trunc函数对时间戳进行舍入(截断),如下所示:
date_trunc('hour', val)
date_trunc('minute', val)
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种方法将时间戳截断到最近的5分钟边界,例如,14:26:57变为14:25:00.直截了当的方式是这样的:
date_trunc('hour', val) + date_part('minute', val)::int / 5 * interval '5 min'
Run Code Online (Sandbox Code Playgroud)
由于这是查询的性能关键部分,我想知道这是否是最快的解决方案,或者是否有一些我忽略的快捷方式(与Postgres 8.1+兼容).
a_h*_*ame 15
我认为没有更快的方法.
而且我认为你不应该担心表达的表现.
执行(SELECT,UPDATE,...)语句所涉及的其他所有内容都可能比日期/时间计算更昂贵(例如,检索行的I/O).
And*_*sen 13
我想知道同样的事情.我找到了两种替代方法,但你提出的方法更快.
我非正式地对照我们的一个较大的表格.我将查询限制在前400万行.我在两个查询之间进行了交替,以避免由于db缓存而给予一个不公平的优势.
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
Run Code Online (Sandbox Code Playgroud)
(注意,timestamptz即使你使用了时区unaware数据类型,也会产生这种情况)
结果
SELECT
date_trunc('hour', ht.time)
+ date_part('minute', ht.time)::int / 5 * interval '5 min'
FROM huge_table AS ht LIMIT 4000000
Run Code Online (Sandbox Code Playgroud)
结果
系统
你的版本似乎更快.但对于我的具体用例来说还不够快.不必指定小时的优点使得epoch版本更加通用并且在客户端代码中产生更简单的参数化.它可以处理2 hour间隔以及5 minute间隔,而不必将date_trunc时间单元参数提升.最后,我希望将时间单位参数更改为时间间隔参数.
从Postgres 14开始,date_bin()是最简单、最快的:
date_bin(\'5 min\', val, \'2000-1-1\')\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n函数
\ndate_bin\xe2\x80\x9cbins\xe2\x80\x9d 将输入时间戳放入与指定原点对齐的指定\n间隔(步幅)中。\n
date_bin(stride,source,origin)\n
sourcetimestamp是or类型的值表达式timestamp with time zone。(类型的值date自动转换为\ntimestamp。)stride是interval 类型的值表达式。\n返回值同样是timestampor类型timestamp with time zone,它标记\n 所在的bin 的开始位置source。
提供匹配数据类型的“来源”,以避免由于忽略时区或假定错误的时区而导致意外结果。
\n我的示例看起来像一个date文字,但也可以作为有效的timestamp文字。如果时间部分缺失,则假定为“00:00”。
有关的:
\n\n