在阅读 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 中这些类型的内部存储是如何工作的?
最佳答案
timestamp with time zone
和 timestamp 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
:
The type
time with time zone
is defined by the SQL standard, but the definition exhibits properties which lead to questionable usefulness.
关于postgresql - PostgreSQL 如何在内部存储日期时间类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65143816/