速度
在 大多数 情况下,Date 数据类型比 DateTime 更快。
Date 类型占用 2 字节存储空间,而 DateTime 占用 4 字节。不过,在压缩时,Date 和 DateTime 之间的大小差异会更加明显。这是因为 DateTime 中的分钟和秒字段更难被压缩。相比过滤和聚合 DateTime,过滤和聚合 Date 也更快。
使用说明
时间点会保存为 Unix 时间戳,与时区或夏令时无关。时区会影响DateTime 类型的值以文本格式显示的方式,以及以字符串形式指定的值 ('2020-01-01 05:00:01') 的解析方式。
表中存储的是与时区无关的 Unix 时间戳,而时区用于在数据导入/导出期间将其转换为文本格式或从文本格式转换回来,或者用于对这些值执行日历计算 (例如 toDate、toHour 等函数) 。时区不会存储在表的行中 (或结果集中) ,而是存储在列元数据中。
支持的时区名称与 SELECT * FROM system.time_zones 列出的名称完全一致,即随服务器一同提供的 IANA Time Zone Database 中的时区,因此结果不依赖于主机自身的时区数据库。该列表 在 Wikipedia 上也可以查看。此外,也支持相对于 UTC 的固定偏移量,写法为 Fixed/UTC±HH:MM:SS,例如 Fixed/UTC+05:30:00;读取使用固定偏移时区的 Arrow 或 ORC 时间戳列时,得到的正是此类名称。其他名称一律会被拒绝。
创建表时,您可以为 DateTime 类型的列显式设置时区。例如:DateTime('UTC')。如果未设置时区,ClickHouse 会使用 ClickHouse server 启动时服务器设置中的 timezone 参数值,或者使用操作系统设置中的值。
如果在初始化数据类型时未显式设置时区,clickhouse-client 默认会使用服务器时区。要使用客户端时区,请在运行 clickhouse-client 时添加 --use_client_time_zone 参数。
ClickHouse 会根据 date_time_output_format 设置的值输出结果。默认的文本格式为 YYYY-MM-DD hh:mm:ss。此外,您还可以使用 formatDateTime 函数更改输出格式。
向 ClickHouse 插入数据时,您可以根据 date_time_input_format 设置的值,使用不同格式的日期时间字符串。
示例
1. 创建一个带有DateTime 类型列的表,并向其中插入数据:
- 当以数值形式插入 datetime 时,它会被视为以秒为单位的 Unix 时间戳 (UTC)。
1546300800表示 UTC 时间'2019-01-01 00:00:00'。不过,由于timestamp列指定了Asia/Istanbul(UTC+3) 时区,因此在以字符串形式输出时,该值会显示为'2019-01-01 03:00:00'。也接受带小数部分或指数部分的数值,并将其截断为整秒,这与CAST、toDateTime和Values格式的行为一致。 (在 26.8 版本之前,JSON和Values/Quoted输入路径中的此类小数或指数数值 (后者涵盖所有使用Quoted转义规则解析字段的格式:Values、MySQLDump,以及配置了Quoted字段转义的Template/CustomSeparated/Regexp) 不被流式解析器接受;请设置input_format_read_datetime_number_as_raw_value = 1以恢复该行为。在Values格式本身中,此类字面量仍可通过 SQL 表达式回退机制生效——并且在兼容模式下仍然有效——该机制会将其读取为秒数。在JSONExtract和JSON数据类型中,小数值会通过Float64解析,因此接近整秒边界的值可能会舍入到相邻的秒,这与会精确截断原始文本的行输入格式不同。制表符分隔、CSV 和其他转义文本格式不受此设置控制。) - 当以字符串形式插入 datetime 值时,它会被视为采用列时区。
'2019-01-01 00:00:00'会被视为Asia/Istanbul时区的时间,并保存为1546290000。
DateTime 值过滤
DateTime 列的值可以在 WHERE 条件中使用字符串值进行过滤。它会自动转换为 DateTime:
DateTime 类型列的时区:
时区支持的限制
某些时区可能无法得到完全支持,主要有以下几种情况: 如果相对 UTC 的偏移量不是 15 分钟的整数倍,那么小时和分钟的计算可能会不准确。例如,利比里亚蒙罗维亚时区在 1972 年 1 月 7 日之前的偏移量为 UTC -0:44:30。如果你对 Monrovia 时区中的历史时间进行计算,时间处理函数可能会给出不正确的结果。不过,1972 年 1 月 7 日之后的结果仍然是正确的。 如果时间切换 (由于夏令时或其他原因) 发生在一个不是 15 分钟整数倍的时间点,那么在这一天的这个特定时刻,也可能得到不正确的结果。 非单调的日历日期。例如,在 Happy Valley - Goose Bay,时间于 2010 年 11 月 7 日 00:01:00 向后调整了一小时 (即午夜过后 1 分钟) 。因此,在 11 月 6 日结束后,人们先经历了 11 月 7 日的整整 1 分钟,然后时间又被拨回到 11 月 6 日 23:01,接着再过 59 分钟,11 月 7 日才再次开始。ClickHouse (暂时) 还不支持这种特殊情况。在这些日期里,时间处理函数的结果可能会有轻微误差。 2010 年的南极 Casey 测站也存在类似问题。当地在 3 月 5 日 02:00 将时间向后调整了 3 小时。如果你在南极测站工作,也不必因此担心无法使用 ClickHouse。只要确保将时区设置为 UTC,或者了解可能存在的误差即可。 跨越多天的时间移位。一些太平洋岛屿将其相对 UTC 的时区偏移从 UTC+14 改为 UTC-12。这本身没有问题,但如果你使用这些时区对转换当日的历史时间点进行计算,仍可能出现一些不准确。处理夏令时 (DST)
ClickHouse 的带时区 DateTime 类型在夏令时 (DST) 切换期间可能会出现异常行为,尤其是在以下情况下:date_time_output_format设置为simple。- 时钟向后拨 (“秋季回拨”) ,导致一小时重叠。
- 时钟向前拨 (“春季前拨”) ,导致一小时空缺。
- 2023 年 10 月 29 日 02:00:00,时钟从 02:00:00 向后拨至 01:00:00 (BST → GMT) 。
- 01:00:00 – 01:59:59 这一小时会出现两次 (一次是 BST,一次是 GMT) 。
- ClickHouse 总是选择第一次出现的时间 (BST) ,因此在增加时间间隔时可能会产生意外结果。
- 在 2023 年 3 月 26 日
00:59:59时,时钟会直接跳到 02:00:00 (GMT → BST) 。 01:00:00–01:59:59这一小时并不存在。
2023-03-26 01:30:00 移回到 2023-03-26 00:30:00。