UUIDv7 生成
生成的 UUID 包含一个以毫秒为单位的 Unix 48 位时间戳,随后是版本号 "7"(4 位)、用于区分同一毫秒内 UUID 的计数器(42 位,其中包括变体字段值为 "2" 的 2 位),以及一个随机字段(32 位)。
对于任意给定的时间戳(unix_ts_ms),计数器从一个随机值开始,对每个新的 UUID 加 1,直到时间戳发生变化为止。如果计数器溢出,则将时间戳字段加 1,并将计数器重置为新的随机起始值。
UUID 生成函数保证,在并发运行的线程和查询中,对于同一时间戳的所有函数调用,计数器字段都是单调递增的。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
| unix_ts_ms |
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
| unix_ts_ms | ver | counter_high_bits |
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
|var| counter_low_bits |
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
| rand_b |
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
Snowflake ID 生成
生成的 Snowflake ID 包含当前以毫秒为单位的 Unix 时间戳(41 位时间戳位 + 1 位最高为 0 的比特),随后是机器 ID(10 位)以及用于在同一毫秒内区分 ID 的计数器(12 位)。对于任意给定的时间戳(unix_ts_ms),计数器从 0 开始,每生成一个新的 Snowflake ID 就加 1,直到时间戳发生变化。如果计数器溢出,则将时间戳字段加 1,并将计数器重置为 0。
注意
生成的 Snowflake ID 是基于 UNIX 纪元 1970-01-01 的。由于 Snowflake ID 的纪元没有统一的标准或推荐方案,不同系统中的实现可能会使用不同的纪元,例如 Twitter/X(2010-11-04)或 Mastodon(2015-01-01)。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
|0| timestamp |
├─┼ ┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
| | machine_id | machine_seq_num |
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
UUIDNumToString
引入于:v1.1
接受 UUID 的二进制表示形式,其格式可通过可选参数 variant 指定(默认为 Big-endian),并返回一个包含 36 个字符的文本格式字符串。
语法
UUIDNumToString(binary[, variant])
参数
返回值
返回 UUID 的字符串表示。String
示例
用法示例
SELECT
'a/<@];!~p{jTj={)' AS bytes,
UUIDNumToString(toFixedString(bytes, 16)) AS uuid
┌─bytes────────────┬─uuid─────────────────────────────────┐
│ a/<@];!~p{jTj={) │ 612f3c40-5d3b-217e-707b-6a546a3d7b29 │
└──────────────────┴──────────────────────────────────────┘
Microsoft 版本
SELECT
'@</a;]~!p{jTj={)' AS bytes,
UUIDNumToString(toFixedString(bytes, 16), 2) AS uuid
┌─bytes────────────┬─uuid─────────────────────────────────┐
│ @</a;]~!p{jTj={) │ 612f3c40-5d3b-217e-707b-6a546a3d7b29 │
└──────────────────┴──────────────────────────────────────┘
UUIDStringToNum
自 v1.1 起提供
接受一个包含 36 个字符且格式为 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 的字符串,并返回其二进制表示形式的 FixedString(16),其格式可以通过 variant 参数进行可选指定(默认使用 Big-endian)。
语法
UUIDStringToNum(string[, variant = 1])
参数
返回值
返回 string 的二进制表示形式。FixedString(16)
示例
使用示例
SELECT
'612f3c40-5d3b-217e-707b-6a546a3d7b29' AS uuid,
UUIDStringToNum(uuid) AS bytes
┌─uuid─────────────────────────────────┬─bytes────────────┐
│ 612f3c40-5d3b-217e-707b-6a546a3d7b29 │ a/<@];!~p{jTj={) │
└──────────────────────────────────────┴──────────────────┘
Microsoft 变体
SELECT
'612f3c40-5d3b-217e-707b-6a546a3d7b29' AS uuid,
UUIDStringToNum(uuid, 2) AS bytes
┌─uuid─────────────────────────────────┬─bytes────────────┐
│ 612f3c40-5d3b-217e-707b-6a546a3d7b29 │ @</a;]~!p{jTj={) │
└──────────────────────────────────────┴──────────────────┘
UUIDToNum
引入版本:v24.5
接受一个 UUID,并返回其二进制表示形式,类型为 FixedString(16),其格式可以通过可选参数 variant 指定(默认是 Big-endian)。
此函数取代了对两个独立函数 UUIDStringToNum(toString(uuid)) 的组合调用,因此在从 UUID 中提取字节时,无需先将 UUID 中间转换为字符串。
语法
UUIDToNum(uuid[, variant = 1])
参数
返回值
返回 UUID 的二进制表示形式。FixedString(16)
示例
用法示例
SELECT
toUUID('612f3c40-5d3b-217e-707b-6a546a3d7b29') AS uuid,
UUIDToNum(uuid) AS bytes
┌─uuid─────────────────────────────────┬─bytes────────────┐
│ 612f3c40-5d3b-217e-707b-6a546a3d7b29 │ a/<@];!~p{jTj={) │
└──────────────────────────────────────┴──────────────────┘
Microsoft 版本
SELECT
toUUID('612f3c40-5d3b-217e-707b-6a546a3d7b29') AS uuid,
UUIDToNum(uuid, 2) AS bytes
┌─uuid─────────────────────────────────┬─bytes────────────┐
│ 612f3c40-5d3b-217e-707b-6a546a3d7b29 │ @</a;]~!p{jTj={) │
└──────────────────────────────────────┴──────────────────┘
UUIDv7ToDateTime
引入于:v24.5
返回 UUID 第 7 版的时间戳部分。
语法
UUIDv7ToDateTime(uuid[, timezone])
参数
返回值
返回一个具有毫秒级精度的时间戳。如果 UUID 不是有效的版本 7 UUID,则返回 1970-01-01 00:00:00.000。DateTime64(3)
示例
用法示例
SELECT UUIDv7ToDateTime(toUUID('018f05c9-4ab8-7b86-b64e-c9f03fbd45d1'))
┌─UUIDv7ToDateTime(toUUID('018f05c9-4ab8-7b86-b64e-c9f03fbd45d1'))─┐
│ 2024-04-22 15:30:29.048 │
└──────────────────────────────────────────────────────────────────┘
含时区
SELECT UUIDv7ToDateTime(toUUID('018f05c9-4ab8-7b86-b64e-c9f03fbd45d1'), 'America/New_York')
┌─UUIDv7ToDateTime(toUUID('018f05c9-4ab8-7b86-b64e-c9f03fbd45d1'), 'America/New_York')─┐
│ 2024-04-22 11:30:29.048 │
└─────────────────────────────────────────────────────────────────────────────────────┘
dateTime64ToSnowflake
引入版本:v21.10
将 DateTime64 在给定时间点转换为第一个 Snowflake ID。
语法
dateTime64ToSnowflake(value)
参数
返回值
返回将输入值转换为该时间点对应的第一个 Snowflake ID。Int64
示例
用法示例
WITH toDateTime64('2021-08-15 18:57:56.492', 3, 'Asia/Shanghai') AS dt64 SELECT dateTime64ToSnowflake(dt64);
┌─dateTime64ToSnowflake(dt64)─┐
│ 1426860704886947840 │
└─────────────────────────────┘
dateTime64ToSnowflakeID
自 v24.6 版本引入
将 DateTime64 转换为给定时间点的第一个 Snowflake ID。
语法
dateTime64ToSnowflakeID(value[, epoch])
参数
value — 带时间的日期。DateTime64
epoch — Snowflake ID 的纪元时间,从 1970-01-01 起按毫秒计。默认值为 0(1970-01-01)。对于 Twitter/X 的纪元时间(2015-01-01),请提供 1288834974657。UInt*
返回值
将输入值转换为 UInt64
示例
简单示例
SELECT dateTime64ToSnowflakeID(toDateTime64('2021-08-15 18:57:56', 3, 'Asia/Shanghai'))
dateTimeToSnowflake
引入版本:v21.10
将一个 DateTime 值转换为指定时间点对应的第一个 Snowflake ID。
语法
dateTimeToSnowflake(value)
参数
返回值
返回输入值在该时间点对应的第一个 Snowflake ID。Int64
示例
使用示例
WITH toDateTime('2021-08-15 18:57:56', 'Asia/Shanghai') AS dt SELECT dateTimeToSnowflake(dt);
┌─dateTimeToSnowflake(dt)─┐
│ 1426860702823350272 │
└─────────────────────────┘
dateTimeToSnowflakeID
自 v24.6 引入
将一个 DateTime 值转换为该时间点对应的第一个 Snowflake ID。
语法
dateTimeToSnowflakeID(value[, epoch])
参数
value — 带时间的日期。DateTime
epoch — Snowflake ID 的纪元时间(毫秒),自 1970-01-01 起算。默认值为 0(1970-01-01)。对于 Twitter/X 的纪元时间(2015-01-01),请使用 1288834974657。UInt*
返回值
将输入值转换为 UInt64
示例
简单示例
SELECT dateTimeToSnowflakeID(toDateTime('2021-08-15 18:57:56', 'Asia/Shanghai'))
dateTimeToUUIDv7
引入版本:v25.9
将给定时间点的 DateTime 值转换为 UUIDv7。
有关 UUID 结构、计数器管理以及并发保证的详细信息,请参阅 "UUIDv7 generation" 一节。
注意
截至 2025 年 9 月,UUID 版本 7 仍处于草案阶段,其格式在未来可能会发生变化。
语法
参数
返回值
返回一个 UUIDv7。UUID
示例
用法示例
SELECT dateTimeToUUIDv7(toDateTime('2021-08-15 18:57:56', 'Asia/Shanghai'));
┌─dateTimeToUUIDv7(toDateTime('2021-08-15 18:57:56', 'Asia/Shanghai'))─┐
│ 018f05af-f4a8-778f-beee-1bedbc95c93b │
└─────────────────────────────────────────────────────────────────────────┘
同一时间戳对应多个 UUID
SELECT dateTimeToUUIDv7(toDateTime('2021-08-15 18:57:56'));
SELECT dateTimeToUUIDv7(toDateTime('2021-08-15 18:57:56'));
┌─dateTimeToUUIDv7(t⋯08-15 18:57:56'))─┐
│ 017b4b2d-7720-76ed-ae44-bbcc23a8c550 │
└──────────────────────────────────────┘
┌─dateTimeToUUIDv7(t⋯08-15 18:57:56'))─┐
│ 017b4b2d-7720-76ed-ae44-bbcf71ed0fd3 │
└──────────────────────────────────────┘
generateSnowflakeID
引入版本:v24.6
生成一个 Snowflake ID。
函数 generateSnowflakeID 保证在并发运行的线程和查询中,同一时间戳内的计数字段在所有函数调用之间单调递增。
有关实现细节,请参阅 "Snowflake ID generation" 一节。
语法
generateSnowflakeID([expr, [machine_id]])
参数
返回值
返回 Snowflake ID。UInt64
示例
用法示例
CREATE TABLE tab (id UInt64)
ENGINE = MergeTree()
ORDER BY tuple();
INSERT INTO tab SELECT generateSnowflakeID();
SELECT * FROM tab;
┌──────────────────id─┐
│ 7199081390080409600 │
└─────────────────────┘
为每行生成多个 Snowflake ID
SELECT generateSnowflakeID(1), generateSnowflakeID(2);
┌─generateSnowflakeID(1)─┬─generateSnowflakeID(2)─┐
│ 7199081609652224000 │ 7199081609652224001 │
└────────────────────────┴────────────────────────┘
结合表达式和机器 ID
SELECT generateSnowflakeID('expr', 1);
┌─generateSnowflakeID('expr', 1)─┐
│ 7201148511606784002 │
└────────────────────────────────┘
generateUUIDv4
自 v1.1 起引入
生成一个 版本 4 的 UUID。
语法
参数
expr — 可选。任意表达式,用于在函数在同一查询中被多次调用时绕过公共子表达式消除。该表达式的值不会影响返回的 UUID。
返回值
返回 UUIDv4。UUID
示例
用法示例
SELECT generateUUIDv4(number) FROM numbers(3);
┌─generateUUIDv4(number)───────────────┐
│ fcf19b77-a610-42c5-b3f5-a13c122f65b6 │
│ 07700d36-cb6b-4189-af1d-0972f23dc3bc │
│ 68838947-1583-48b0-b9b7-cf8268dd343d │
└──────────────────────────────────────┘
公共子表达式消除
SELECT generateUUIDv4(1), generateUUIDv4(1);
┌─generateUUIDv4(1)────────────────────┬─generateUUIDv4(2)────────────────────┐
│ 2d49dc6e-ddce-4cd0-afb8-790956df54c1 │ 2d49dc6e-ddce-4cd0-afb8-790956df54c1 │
└──────────────────────────────────────┴──────────────────────────────────────┘
generateUUIDv7
引入于:v24.5
生成一个 版本 7 的 UUID。
关于 UUID 结构、计数器管理以及并发保证的详细信息,参见 "UUIDv7 generation" 一节。
注意
截至 2025 年 9 月,版本 7 UUID 仍处于草案状态,其格式和布局在未来可能会发生变化。
语法
参数
expr — 可选。任意表达式,用于在函数在单个查询中被多次调用时绕过公共子表达式消除。该表达式的值不会影响返回的 UUID。Any
返回值
返回一个 UUIDv7。UUID
示例
用法示例
SELECT generateUUIDv7(number) FROM numbers(3);
┌─generateUUIDv7(number)───────────────┐
│ 019947fb-5766-7ed0-b021-d906f8f7cebb │
│ 019947fb-5766-7ed0-b021-d9072d0d1e07 │
│ 019947fb-5766-7ed0-b021-d908dca2cf63 │
└──────────────────────────────────────┘
公共子表达式消除
SELECT generateUUIDv7(1), generateUUIDv7(1);
┌─generateUUIDv7(1)────────────────────┬─generateUUIDv7(1)────────────────────┐
│ 019947ff-0f87-7d88-ace0-8b5b3a66e0c1 │ 019947ff-0f87-7d88-ace0-8b5b3a66e0c1 │
└──────────────────────────────────────┴──────────────────────────────────────┘
readWKTLineString
自 v 版本引入
解析 LineString 几何体的 Well-Known Text(WKT)表示,并以 ClickHouse 的内部格式返回。
语法
readWKTLineString(wkt_string)
参数
wkt_string — 表示 LineString 几何对象的输入 WKT 字符串。String
返回值
该函数返回 ClickHouse 对 LineString 几何对象的内部表示形式。
示例
第一次调用
SELECT readWKTLineString('LINESTRING (1 1, 2 2, 3 3, 1 1)');
┌─readWKTLineString('LINESTRING (1 1, 2 2, 3 3, 1 1)')─┐
│ [(1,1),(2,2),(3,3),(1,1)] │
└──────────────────────────────────────────────────────┘
第二次调用
SELECT toTypeName(readWKTLineString('LINESTRING (1 1, 2 2, 3 3, 1 1)'));
┌─toTypeName(readWKTLineString('LINESTRING (1 1, 2 2, 3 3, 1 1)'))─┐
│ LineString │
└──────────────────────────────────────────────────────────────────┘
snowflakeIDToDateTime
自 v24.6 引入
返回 Snowflake ID 中的时间戳部分,类型为 DateTime。
语法
snowflakeIDToDateTime(value[, epoch[, time_zone]])
参数
value — Snowflake ID。UInt64
epoch — 可选。Snowflake ID 的纪元(自 1970-01-01 起的毫秒数)。默认值为 0(1970-01-01)。对于 Twitter/X 的纪元(2015-01-01),请使用 1288834974657。UInt*
time_zone — 可选。时区。函数会根据该时区解析 time_string。String
返回值
返回 value 的时间戳部分。DateTime
示例
使用示例
SELECT snowflakeIDToDateTime(7204436857747984384) AS res
┌─────────────────res─┐
│ 2024-06-06 10:59:58 │
└─────────────────────┘
snowflakeIDToDateTime64
自 v24.6 版本引入
返回 Snowflake ID 的时间戳部分,类型为 DateTime64。
语法
snowflakeIDToDateTime64(value[, epoch[, time_zone]])
参数
value — Snowflake ID。UInt64
epoch — 可选。Snowflake ID 的纪元(自 1970-01-01 起的毫秒数)。默认值为 0(1970-01-01)。对于 Twitter/X 的纪元(2015-01-01),请使用 1288834974657。UInt*
time_zone — 可选。Timezone。函数会根据该时区解析 time_string。String
返回值
返回 value 的时间戳部分,类型为 DateTime64,scale = 3,即毫秒级精度。DateTime64
示例
用法示例
SELECT snowflakeIDToDateTime64(7204436857747984384) AS res
┌─────────────────res─┐
│ 2024-06-06 10:59:58 │
└─────────────────────┘
snowflakeToDateTime
引入版本:v21.10
提取 Snowflake ID 中的时间戳部分,并以 DateTime 格式返回。
语法
snowflakeToDateTime(value[, time_zone])
参数
返回值
返回 value 的时间戳部分。DateTime
示例
使用示例
SELECT snowflakeToDateTime(CAST('1426860702823350272', 'Int64'), 'UTC');
┌─snowflakeToDateTime(CAST('1426860702823350272', 'Int64'), 'UTC')─┐
│ 2021-08-15 10:57:56 │
└──────────────────────────────────────────────────────────────────┘
snowflakeToDateTime64
引入版本:v21.10
提取 Snowflake ID 中的时间戳部分,并以 DateTime64 格式返回。
语法
snowflakeToDateTime64(value[, time_zone])
参数
返回值
返回 value 的时间戳部分。DateTime64(3)
示例
用法示例
SELECT snowflakeToDateTime64(CAST('1426860802823350272', 'Int64'), 'UTC');
┌─snowflakeToDateTime64(CAST('1426860802823350272', 'Int64'), 'UTC')─┐
│ 2021-08-15 10:58:19.841 │
└────────────────────────────────────────────────────────────────────┘
toUUIDOrDefault
引入自:v21.1
将 String 值转换为 UUID 类型。如果转换失败,则返回默认 UUID 值,而不会抛出错误。
该函数会尝试将长度为 36 的字符串解析为标准 UUID 格式(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)。
如果该字符串无法转换为有效 UUID,函数将返回提供的默认 UUID 值。
语法
toUUIDOrDefault(string, default)
参数
string — 将要转换为 UUID 的 36 个字符的字符串或 FixedString(36)。
default — 当第一个参数无法转换为 UUID 类型时返回的 UUID 值。
返回值
转换成功时返回转换后的 UUID,转换失败时返回默认 UUID。UUID
示例
转换成功时返回解析得到的 UUID
SELECT toUUIDOrDefault('61f0c404-5cb3-11e7-907b-a6006ad3dba0', toUUID('59f0c404-5cb3-11e7-907b-a6006ad3dba0'));
┌─toUUIDOrDefault('61f0c404-5cb3-11e7-907b-a6006ad3dba0', toUUID('59f0c404-5cb3-11e7-907b-a6006ad3dba0'))─┐
│ 61f0c404-5cb3-11e7-907b-a6006ad3dba0 │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────┘
转换失败时会返回默认 UUID
SELECT toUUIDOrDefault('-----61f0c404-5cb3-11e7-907b-a6006ad3dba0', toUUID('59f0c404-5cb3-11e7-907b-a6006ad3dba0'));
┌─toUUIDOrDefault('-----61f0c404-5cb3-11e7-907b-a6006ad3dba0', toUUID('59f0c404-5cb3-11e7-907b-a6006ad3dba0'))─┐
│ 59f0c404-5cb3-11e7-907b-a6006ad3dba0 │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
toUUIDOrNull
自 v20.12 引入
将输入值转换为 UUID 类型的值,但在发生错误时返回 NULL。
类似于 toUUID,但在转换出错时返回 NULL,而不是抛出异常。
支持的参数:
- 标准格式的 UUID 字符串表示(8-4-4-4-12 个十六进制数字)。
- 去掉连字符的 UUID 字符串表示(32 个十六进制数字)。
不支持的参数(返回 NULL):
- 无效的字符串格式。
- 非字符串类型。
- 格式错误的 UUID。
语法
参数
返回值
成功时返回 UUID 值,否则返回 NULL。UUID 或 NULL
示例
用法示例
SELECT
toUUIDOrNull('550e8400-e29b-41d4-a716-446655440000') AS valid_uuid,
toUUIDOrNull('invalid-uuid') AS invalid_uuid
┌─valid_uuid───────────────────────────┬─invalid_uuid─┐
│ 550e8400-e29b-41d4-a716-446655440000 │ ᴺᵁᴸᴸ │
└──────────────────────────────────────┴──────────────┘