长度固定为 N 字节的字符串 (不是字符数,也不是码点数) 。
要声明 FixedString 类型的列,请使用以下语法:
<column_name> FixedString(N)其中 N 为自然数。
当数据长度恰好为 N 字节时,FixedString 类型效率较高。其他情况下,它很可能会降低效率。
适合高效存储在 FixedString 类型列中的值示例:
- IP 地址的二进制表示 (
FixedString(16)用于 IPv6)。 - 语言代码 (ru_RU、en_US、…)。
- 货币代码 (USD、RUB、…)。
- 哈希的二进制表示 (
FixedString(16)用于 MD5,FixedString(32)用于 SHA256)。
要存储 UUID 值,请使用 UUID 数据类型。
插入数据时,ClickHouse 会:
- 如果字符串包含的字节数少于
N,则用 null byte 补齐字符串。 - 如果字符串包含的字节数超过
N,则抛出Too large value for FixedString(N)异常。
来看下面这张仅包含一个 FixedString(2) 列的表:
INSERT INTO FixedStringTable VALUES ('a'), ('ab'), ('');SELECT
name,
toTypeName(name),
length(name),
empty(name)
FROM FixedStringTable;┌─name─┬─toTypeName(name)─┬─length(name)─┬─empty(name)─┐
│ a │ FixedString(2) │ 2 │ 0 │
│ ab │ FixedString(2) │ 2 │ 0 │
│ │ FixedString(2) │ 2 │ 1 │
└──────┴──────────────────┴──────────────┴─────────────┘请注意,FixedString(N) 值的长度是固定的。即使 FixedString(N) 值仅由 null byte 填充,length 函数也会返回 N;但在这种情况下,empty 函数会返回 1。
使用 WHERE 子句查询数据时,返回结果会因条件的指定方式不同而有所差异:
- 如果使用等于运算符
=或==,或使用equals函数,ClickHouse 不会 将\0字符考虑在内。也就是说,查询SELECT * FROM FixedStringTable WHERE name = 'a';和SELECT * FROM FixedStringTable WHERE name = 'a\0';会返回相同的结果。 - 如果使用
LIKE子句,ClickHouse 会 将\0字符考虑在内,因此可能需要在过滤条件中显式指定\0字符。
SELECT name
FROM FixedStringTable
WHERE name = 'a'
FORMAT JSONStringsEachRow
{"name":"a\u0000"}
SELECT name
FROM FixedStringTable
WHERE name = 'a\0'
FORMAT JSONStringsEachRow
{"name":"a\u0000"}
SELECT name
FROM FixedStringTable
WHERE name = 'a'
FORMAT JSONStringsEachRow
Query id: c32cec28-bb9e-4650-86ce-d74a1694d79e
{"name":"a\u0000"}
SELECT name
FROM FixedStringTable
WHERE name LIKE 'a'
FORMAT JSONStringsEachRow
0 rows in set.
SELECT name
FROM FixedStringTable
WHERE name LIKE 'a\0'
FORMAT JSONStringsEachRow
{"name":"a\u0000"}