写点什么

Apache IoTDB 中的时间精度 | 铁头乔分享

作者:Apache IoTDB
  • 2023-01-12
    北京
  • 本文字数:1720 字

    阅读完需:约 6 分钟

Apache IoTDB 中的时间精度 | 铁头乔分享

从启动说起

有一个 timestamp_precision 的配置项文件名在 IoTDB 的配置文件里,默认是 ms。但是大多数用户在使用 IoTDB 储存数据时,对这个配置项 timestamp_precision 不关注,而通过 System.currentTime Millis 在 Java 客户端拿到一个 long 类型的时间戳,刚好就是毫秒级别的,很合适。

所以大多数用户对这个都无感,但是也有一些场景,数据采集频率大于 1000 了,这时候大家就开始想着改这个参数了,比如改成 ns。


然后就会遇到一个启动问题:


ConfigurationException:

Parameter timestamp_precision can not be ns, please set to: ms。


大家可能就蒙了,为啥不让改?


正好 0.13.1 版本发布了,接下来的介绍和截图也就用这个版本了。


能不能不管时间精度?


传给数据库的 Time 都是数字格式的时间戳,就不用管这个参数。


我们先启动一个 CLI,加一个参数:

./sbin/start-cli.sh -disableISO8601


然后执行下列 SQL:

insert into root.sg.d(time,s1) values(1,520)

insert into root.sg.d(time,s1) values(2,520)

select s1 from root.sg.d where time<10


接下来,我们会看到下面这种结果,从写入的 SQL,到查询出的结果的 Time 列展示,都跟时间精度没关系,时间戳都只是一个整数。



我们把这个 1、2 当做 ms 也可以,当做 us、ns 都可以。


这就是最原始的样子,没有时间精度,时间戳就是一个 long 类型的数据,数据库接收到这个 long,就存储这个 long,并且查询的时候把这个 long 返回给客户端。


所以,如果用 long 类型的时间戳跟数据库交互(凡是给数据库传输的时间戳都是 long),数据库也会返回 long,完全不用管这个参数,只需要在客户端这边把这个 long 表达的意思理清楚就行。


CLI 打印时间


注意一下,我们刚才启动 CLI 的时候加了一个参数 -disableISO8601,这是干啥的?


这个参数的功能是 关闭 ISO 8601 格式打印,ISO 8601 是一种日期和时间的表示方法。


比如北京时间 2021 年 5 月 21 日下午 2 点 22 分 22 秒,ISO 8601 格式就是 :

2021-05-21T14:22:22+08:00


为啥要加这个呢,刚才我们查出来的数据时间是 1 和 2,这是啥玩意,就很不好理解,大家还是喜欢看是哪年哪月哪天的。


所以,为了让 CLI 查出来的数据更直观,我们把这个 long 类型的时间戳,转成 ISO8601 格式的字符串来打印了。因此,不加任何参数启动 CLI 时,就是下面这种效果了。


这个时候,时间精度就开始发挥作用了。



时间戳与 1970


时间戳是指格林威治时间 1970 年 01 月 01 日 00 时 00 分 00 秒到当前经过的时间。因此 1970 年 01 月 01 日 00 时 00 分 00 秒就是时间戳 0。


更具体一点,0 时间戳也是 1970 年 01 月 01 日 00 时 00 分 00 秒 000 毫秒 000 微秒 000 纳秒。


时间戳 0 没什么歧义,那 1 呢?是 1970 年 01 月 01 日 00 时 00 分 01 秒?还是 00 秒 001 毫秒?还是 00 秒 000 毫秒 001 微秒?亦或是 00 秒 000 毫秒 000 微秒 001 纳秒?


时间精度开始发挥作用


也就是这个 1 个时间单位,到底代表多长的时间,这就是时间精度要管的。


如果配置里的 timestamp_precision =ms,那么 1 就表示 1970 年 01 月 01 日 00 时 00 分 00 秒 001 毫秒。


如果我们配置的是纳秒,那么写入的 1 打印出来的就是:

1970-01-01T08:00:00.000000001+08:00


总结一下:凡是涉及到整数的时间戳和字符串格式的日期的相互转换时,就是时间精度发挥作用的时刻。时间戳有负的吗,有的,1970 年之前的时刻,比如 1969 年用时间戳表示就是小于 0 了。1970 年只是坐标轴的原点,这个时间的坐标轴可正可负。只不过现在一般用不到负数了。


如果我们写入一个 now(),在这时候系统内部就会使用 System.currentTime Millis() 获取当前 ms 级别的时间戳,一般就是这么一个 16 开头的 13 位的数字。



时间精度怎么改?


回到刚开始的启动问题,因为我们要对用户写入的时间戳的解释前后一致,比如刚开始配置的是 ms,那么 1 就是 ms,这时候改成 ns,由于我们没有为每一个时间戳存储精度信息,这时候就会出现原本的 1 变成了 ns。修改前后打印出来的日期就不一致了。


为了避免这种情况,我们做了个启动检查,把 timestamp_precision 当做一个启动之后不能修改的配置项。


如果想改,正常情况我们推荐把 data/system 目录都清空,重新来过。


如果就想把老数据的时间格式改了,可以修改 iotdb-engine.properties 配置文件的同时,把 data/system/schema/ system.properties 里的 timestamp_precision 也一起改了,这时候就没人能阻止你了。


好了,关于时间戳的介绍就到这里了。


发布于: 刚刚阅读数: 4
用户头像

Apache IoTDB

关注

还未添加个人签名 2021-12-30 加入

海量时序数据管理的解决方案,一款高吞吐、高压缩、高可用、物联网原生的开源时序数据库。

评论

发布
暂无评论
Apache IoTDB 中的时间精度 | 铁头乔分享_Apache IoTDB_InfoQ写作社区