在postgresql中使用nanosec存储时间戳的最优雅方法是什么?

时间:2017-10-17 12:54:34

标签: sql postgresql date datetime timestamp

不幸的是postgresql时间戳类型只能存储具有microsec精度的时间戳,但我也需要nanosec。

PostgreSQL - 8.5. Date/Time Types:

  

Timestamp和interval接受一个可选的精度值p,它指定秒字段中保留的小数位数。默认情况下,精度没有明确的界限。对于时间戳和间隔类型,允许的p范围是0到6。

我需要7:

  

0,000 000 001 [十亿分]纳秒[ns]

     

0,000 001 [百万分之]微秒[μs]

     

0,001 [千分之一]毫秒[ms]

     

0.01 [百分位] [cs]

     

1.0秒[s]

有没有优雅有效的方法来处理这个问题?

编辑: 也许将时间戳存储在bigint中?

3 个答案:

答案 0 :(得分:3)

使用numeric作为纳米时间戳的基本类型。该函数将数值转换为其文本时间戳表示:

create or replace function nanotimestamp_as_text(numeric)
returns text language sql immutable as $$
    select concat(to_timestamp(trunc($1))::timestamp::text, ltrim(($1- trunc($1))::text, '0'))
$$;

在不需要超精度的情况下,您也可以轻松地将数值转换为常规时间戳,例如:

with my_data(nano_timestamp) as (
    select 1508327235.388551234::numeric
)

select 
    to_timestamp(nano_timestamp)::timestamp,
    nanotimestamp_as_text(nano_timestamp)
from my_data;

        to_timestamp        |     nanotimestamp_as_text     
----------------------------+-------------------------------
 2017-10-18 13:47:15.388551 | 2017-10-18 13:47:15.388551234
(1 row)

答案 1 :(得分:2)

Bigint会奏效。如果要以纳秒精度保存所有时间戳,我建议定义一个新的强制转换:

CREATE CAST (timestamp AS bigint)
WITHOUT FUNCTION;

答案 2 :(得分:0)

正如其他人所指出的那样,Postgres并不提供这种开箱即用的类型。但是,由于Postgres的开源特性,创建支持纳秒分辨率的扩展相对简单。不久前,我遇到了类似的问题,并为Postgres创建了this timestamp9 extension

它在内部将时间戳记存储为bigint,并将其定义为自UNIX时代以来的纳秒数。它提供了一些便利的功能,使查看和操作时间戳变得容易。如果您可以忍受这些时间戳记所具有的有限时间范围(在1970年和2262年之间),那么这是一个很好的解决方案。

如果您不想在系统上安装扩展程序,则Klin的答案是一个完美的解决方案。但是,它与现有的时间戳/时间间隔类型配合不太好,并且效率也较低,因为它使用数字类型作为存储。扩展具有更大的灵活性。

免责声明:我是扩展名的作者