Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the most elegant way to store timestamp with nanosec in postgresql?

Unfortunately the postgresql timestamp type only can store timestamps with microsec precision but i need the nanosec also.

PostgreSQL - 8.5. Date/Time Types:

Timestamp, and interval accept an optional precision value p which specifies the number of fractional digits retained in the seconds field. By default, there is no explicit bound on precision. The allowed range of p is from 0 to 6 for the timestamp and interval types.

And i need 7:

0,000 000 001 [ billionth ] nanosecond [ ns ]

0,000 001 [ millionth ] microsecond [ µs ]

0,001 [ thousandth ] millisecond [ ms ]

0.01 [ hundredth ] centisecond [ cs ]

1.0 second [ s ]

Is there any elegant and efficient way to handle this problem?

EDIT: Maybe store the timestamp in bigint?

like image 651
Csuszmusz Avatar asked Oct 17 '17 12:10

Csuszmusz


2 Answers

Use numeric as a base type of nano timestamps. The function converts a numeric value to its textual timestamp representation:

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'))
$$;

You can also easily convert numeric values to regular timestamps in cases where the super precision is not necessary, example:

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)
like image 71
klin Avatar answered Nov 15 '22 07:11

klin


As others have pointed out, Postgres doesn't provide such type out of the box. However, it's relatively simple to create an extension that supports nanosecond resolution due to the open-source nature of Postgres. I faced similar issues a while ago and created this timestamp9 extension for Postgres.

It internally stores the timestamp as a bigint and defines it as the number of nanoseconds since the UNIX epoch. It provides some convenience functions around it that make it easy to view and manipulate the timestamps. If you can live with the limited time range that these timestamps can have, between the year 1970 and the year 2262, then this is a good solution.

Klin's answer is a perfect solution if you don't want to have an extension installed on your system. However, it cooperates less nicely with existing timestamp/interval types and it's also less efficient, because it uses a numeric type as storage. Having an extension gives you greater flexibility.

Disclaimer: I'm the author of the extension

like image 22
fvannee Avatar answered Nov 15 '22 06:11

fvannee