【问题标题】:How does PostgreSQL store datetime types internallyPostgreSQL 如何在内部存储日期时间类型
【发布时间】:2021-03-16 12:31:09
【问题描述】:

在阅读 PostreSQL (13) 文档时,我遇到了this 页面,其中列出了不同日期时间类型的存储大小。

除其他外,它指出:

Name                         Storage Size       Description                                   Low Value      High Value      Resolution
----                         ------------       -----------                                   ---------      ----------      ----------
timestamp without time zone       8 bytes       both date and time (no time zone)               4713 BC       294276 AD   1 microsecond
timestamp with time zone          8 bytes       both date and time, with time zone              4713 BC       294276 AD   1 microsecond
time with time zone              12 bytes       time of day (no date), with time zone     00:00:00+1559   24:00:00-1559   1 microsecond

我可以理解timestamp without time zone:低值和高值之间大约有 (4713 + 294276) * 365 * 24 * 60 * 60 * 1000000 微秒。 (不考虑日历变化等)。这相当于大约 2^63 个值,这些值可以存储在 8 个字节中。

但是,timestamp with timezone 具有相同的范围和分辨率,并且可以额外存储时区信息。如果我们已经使用 63 位作为值,则只剩下一位,不足以存储时区,因此内部存储的工作方式必须有所不同。

更奇怪的是,虽然时间戳只使用 8 个字节,但 time with time zone 需要 12 个字节,尽管它具有相同的分辨率和更小的允许值范围。

因此我的问题是:PostgreSQL 中这些类型的内部存储如何工作?

【问题讨论】:

  • 不相关,但是:time with time zone 应该是not be used
  • 这个问题可以通过阅读源码来回答。 (Postgres 是开源的)

标签: postgresql timestamp storage


【解决方案1】:

并且可以额外存储时区信息

不,它不存储时区信息。

来自您链接到的same page

所有可识别时区的日期和时间都以 UTC 格式在内部存储。在显示给客户端之前,它们会转换为 TimeZone 配置参数指定的区域中的本地时间。

(强调我的)

所以timestamptimestamptz 存储在同一个地方。它们只是在从客户端接受和返回值的方式上有所不同。

【讨论】:

    【解决方案2】:

    timestamp with time zonetimestamp without time zone 都存储为一个 8 字节整数,表示自 2000 年 1 月 1 日午夜以来的微秒。

    不同之处在于timestamp with time zone 被解释为UTC 格式,并根据显示的timezone 参数的当前设置进行转换。

    定义在src/include/datatype/timestamp.h:

    typedef int64 Timestamp;
    typedef int64 TimestampTz;
    

    time without time zone 是一个 8 字节整数,表示自午夜以来的微秒(4 字节整数是不够的)。见src/include/utils/date.h:

    typedef int64 TimeADT;
    

    time with time zone 有一个额外的 4 字节整数,表示时区偏移量(以秒为单位)。

    src/include/utils/date.h:

    typedef struct
    {
        TimeADT     time;           /* all time units other than months and years */
        int32       zone;           /* numeric time zone, in seconds */
    } TimeTzADT;
    

    关注the documentation,避开time with time zone

    time with time zone 类型是由 SQL 标准定义的,但该定义显示的属性会导致有用性值得怀疑。

    【讨论】:

      猜你喜欢
      • 2019-02-20
      • 2012-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-29
      • 2016-10-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多