【Clickhouse】clickhouse 數據類型


當前版本SELECT version()22.3.3.44
整理日期 2022-04
最新信息請查看官網,新版本可能會添加新的數據類型
https://clickhouse.com/docs/en/sql-reference/data-types/

1 基礎類型

1.1 數值類型

1.1.1 整數

有符號數整形

Int8, Int16, Int32, Int64, Int128, Int256

名稱 大小(字節) 范圍 普遍概念
Int8 1 [-128 : 127] TINYINT, BOOL, BOOLEAN, INT1
Int16 2 [-32768 : 32767] SMALLINT, INT2
Int32 4 [-2147483648 : 2147483647] INT, INT4, INTEGER
Int64 8 [-9223372036854775808 : 9223372036854775807] BIGINT

無符號數整型

UInt8, UInt16, UInt32, UInt64, UInt128, UInt256

名稱 大小(字節) 范圍 普遍概念
UInt8 1 [0 : 255] TINYINT Unsined
UInt16 2 [0 : 65535] SMALLINTUnsined
UInt32 4 [0 : 4294967295] INT Unsined
UInt64 8 [0 : 18446744073709551615] BIGINT Unsined

Boolean

沒有單獨的類型來存儲布爾值。可以使用 UInt8 類型,取值限制為 0 或 1。

1.1.2 浮點數

建議盡可能以整數形式存儲數據。例如,將固定精度的數字轉換為整數值,如時間用毫秒為單位表示.

名稱 大小(字節) 有效精度(位數) 普遍概念
Float32 4 7 Float
Float64 8 16 Double

浮點型進行計算時可能引起四舍五入的誤差。

ac27f97f6a77 :) SELECT 1 - 0.9

SELECT 1 - 0.9

Query id: 7cc88fd3-1e0b-4ec1-aa23-57fd333ec1f7

┌───────minus(1, 0.9)─┐
│ 0.09999999999999998 │
└─────────────────────┘

1 rows in set. Elapsed: 0.035 sec. 

ClickHouse直接使用Float32和Float64代表單精度浮點數以及雙精度浮點數,Float32從小數點后第8位起及Float64從小數點后第17位起,會產生數據溢出

ac27f97f6a77 :) SELECT toFloat32('0.12345678901234567890') as a , toTypeName(a)

SELECT
    toFloat32('0.12345678901234567890') AS a,
    toTypeName(a)

Query id: c5d87476-acfb-4704-bb6f-c92483761808

┌──────────a─┬─toTypeName(toFloat32('0.12345678901234567890'))─┐
│ 0.12345679 │ Float32                                         │
└────────────┴─────────────────────────────────────────────────┘

1 rows in set. Elapsed: 0.032 sec. 

ac27f97f6a77 :) SELECT toFloat64('0.12345678901234567890') as a , toTypeName(a)

SELECT
    toFloat64('0.12345678901234567890') AS a,
    toTypeName(a)

Query id: a3839d5e-7252-4118-b1f2-85de2f910cc2

┌───────────────────a─┬─toTypeName(toFloat64('0.12345678901234567890'))─┐
│ 0.12345678901234568 │ Float64                                         │
└─────────────────────┴─────────────────────────────────────────────────┘

1 rows in set. Elapsed: 0.026 sec.

ClickHouse的浮點數支持正無窮、負無窮以及非數字的表達方式.

-- 正無窮 inf
ac27f97f6a77 :) SELECT 0.1/0

SELECT 0.1 / 0

Query id: aa43028a-8778-49dc-8f73-7b2a7c8d37bd

┌─divide(0.1, 0)─┐
│            inf │
└────────────────┘

1 rows in set. Elapsed: 0.033 sec. 

-- 負無窮 -inf
ac27f97f6a77 :) SELECT -0.1/0

SELECT -0.1 / 0

Query id: 84a1070b-09c7-4153-a743-c69a0dc67c19

┌─divide(-0.1, 0)─┐
│            -inf │
└─────────────────┘

1 rows in set. Elapsed: 0.032 sec. 

-- 非數字 nan
ac27f97f6a77 :) SELECT 0/0

SELECT 0 / 0

Query id: 925823e7-f76c-4a73-af16-9ced6ec5769e

┌─divide(0, 0)─┐
│          nan │
└──────────────┘

1 rows in set. Elapsed: 0.032 sec. 

1.1.3 定點數

定點數表示形式

有符號的浮點數,可在加、減和乘法運算過程中保持精度。對於除法,最低有效數字會被丟棄(不舍入)。
如果要求更高精度的數值運算,則需要使用定點數。ClickHouse提供了Decimal32、Decimal64、Decimal128和Decimal256四種精度的定點數。
可以通過兩種形式聲明定點:

  • 簡寫方式有Decimal32(S)、Decimal64(S)、Decimal128(S)、Decimal256(S)四種
  • 原生方式為Decimal(P,S),其中
    • P代表精度,決定總位數(整數部分+小數部分),取值范圍是[1:76]
    • S代表規模,決定小數位數,取值范圍是[0:P]。

例如:Decimal32(4) 可以表示數字(-99999.9999, 99999.9999) , 步長為0.0001

**名稱 等效聲明 范圍 精度P
Decimal32(S) Decimal(9-s,s) ( -1 * 10^(9 - S), 1 * 10^(9 - S) ) [ 1 : 9 ]
Decimal64(S) Decimal(18-s,s) ( -1 * 10^(18 - S), 1 * 10^(18 - S) ) [ 10 : 18 ]
Decimal128(S) Decimal(38-s,s) ( -1 * 10^(38 - S), 1 * 10^(38 - S) ) [ 19 : 38 ]
Decimal256(S) Decimal(76-s,s) ( -1 * 10^(76 - S), 1 * 10^(76 - S) ) [ 39 : 76 ]

使用場景: 一般金額字段、匯率、利率等字段為了保證小數點精度,都使用 Decimal進行存儲

在使用定點數時還有一點值得注意:由於現代計算器系統只支持32位和64位CPU,所以Decimal128是在軟件層面模擬實現的,它的速度會明顯慢於Decimal32與Decimal64。

定點數運算及結果類型

在使用兩個不同精度的定點數進行四則運算的時:

  • 會得到更寬的結果類型(無關順序)
    • Decimal64(S1) Decimal32(S2) -> Decimal64(S)
    • Decimal128(S1) Decimal32(S2) -> Decimal128(S)
    • Decimal128(S1) Decimal64(S2) -> Decimal128(S)
  • 小數點位數S會發生變化
名稱 精度變化規則
加減法 S = max(S1, S2)
乘法 S = S1 + S2
除法 S = S1

加法示例
Decemal32 op Decemal64 = Decemal64
S=max(S1, S2)=max(4, 2) = 4

-- 加法
840013eee323 :) SELECT toDecimal64(2,4) + toDecimal32(2,2) as a, toTypeName(a)

SELECT
    toDecimal64(2, 4) + toDecimal32(2, 2) AS a,
    toTypeName(a)

Query id: 31c174e5-e50f-4ac4-8642-e263854470c9

┌─a─┬─toTypeName(plus(toDecimal64(2, 4), toDecimal32(2, 2)))─┐
│ 4 │ Decimal(18, 4)                                         │
└───┴────────────────────────────────────────────────────────┘

1 rows in set. Elapsed: 0.012 sec.

減法示例
Decemal32 op Decemal64 = Decemal64
S=max(S1, S2)=max(2, 4) = 4

-- 減法
840013eee323 :) SELECT toDecimal64(4,2) - toDecimal32(2,4) as a, toTypeName(a)

SELECT
    toDecimal64(4, 2) - toDecimal32(2, 4) AS a,
    toTypeName(a)

Query id: 7188e58d-ee0b-4893-a48e-1717f90cd14e

┌─a─┬─toTypeName(minus(toDecimal64(4, 2), toDecimal32(2, 4)))─┐
│ 2 │ Decimal(18, 4)                                          │
└───┴─────────────────────────────────────────────────────────┘

1 rows in set. Elapsed: 0.031 sec.

乘法示例
Decemal32 op Decemal64 = Decemal64
S=S1+S2=4+2 = 6

840013eee323 :)  SELECT toDecimal64(2,4) * toDecimal32(2,2) as a, toTypeName(a)

SELECT
    toDecimal64(2, 4) * toDecimal32(2, 2) AS a,
    toTypeName(a)

Query id: 0c99d332-233c-4d14-964e-c9ba7a012029

┌─a─┬─toTypeName(multiply(toDecimal64(2, 4), toDecimal32(2, 2)))─┐
│ 4 │ Decimal(18, 6)                                             │
└───┴────────────────────────────────────────────────────────────┘

1 rows in set. Elapsed: 0.015 sec.

除法示例
Decemal32 op Decemal64 = Decemal64
S=S1 = 4

840013eee323 :)  SELECT toDecimal64(2,4) / toDecimal32(2,2) as a, toTypeName(a)

SELECT
    toDecimal64(2, 4) / toDecimal32(2, 2) AS a,
    toTypeName(a)

Query id: 48020990-1e82-4682-837b-50b81cb054f5

┌─a─┬─toTypeName(divide(toDecimal64(2, 4), toDecimal32(2, 2)))─┐
│ 1 │ Decimal(18, 4)                                           │
└───┴──────────────────────────────────────────────────────────┘

1 rows in set. Elapsed: 0.013 sec. 

溢出檢查

對 Decimal 類型執行操作時,數值可能會發生溢出。分數中的過多數字被丟棄(不是舍入的)。整數中的過多數字將導致異常

-- 默認溢出檢查是打開的
840013eee323 :) SELECT toDecimal32(2, 4) AS x, x / 3

SELECT
    toDecimal32(2, 4) AS x,
    x / 3

Query id: 44ec8d15-7db1-43bd-88c1-1d50a7afecf3

┌─x─┬─divide(toDecimal32(2, 4), 3)─┐
│ 2 │                       0.6666 │
└───┴──────────────────────────────┘

1 rows in set. Elapsed: 0.029 sec.

-- 檢查溢出會導致計算變慢。如果已知溢出不可能,則可以通過設置decimal_check_overflow來禁用溢出檢查,在這種情況下,溢出將導致結果不正確:
840013eee323 :) SET decimal_check_overflow = 0;

SET decimal_check_overflow = 0

Query id: 74b7b860-250f-42fe-9421-dba591f2a913

Ok.

0 rows in set. Elapsed: 0.019 sec.
840013eee323 :) SELECT toDecimal32(4.2, 8) AS x, 6 * x

SELECT
    toDecimal32(4.2, 8) AS x,
    6 * x

Query id: c195a43d-3ba7-4f19-b161-e965c18c51e1

┌───x─┬─multiply(6, toDecimal32(4.2, 8))─┐
│ 4.2 │                     -17.74967296 │
└─────┴──────────────────────────────────┘

1 rows in set. Elapsed: 0.015 sec. 


--溢出檢查不僅發生在算術運算上,還發生在比較運算上:
SET decimal_check_overflow = 1; --恢復默認溢出檢查
840013eee323 :) SELECT toDecimal32(1, 8) < 100

SELECT toDecimal32(1, 8) < 100

Query id: 0e3b112f-1603-4cc9-b264-c8be6d419e55


0 rows in set. Elapsed: 0.037 sec. 

Received exception from server (version 22.3.3):
Code: 407. DB::Exception: Received from localhost:9000. DB::Exception: Can't compare decimal number due to overflow: While processing toDecimal32(1, 8) < 100. (DECIMAL_OVERFLOW)

1.2 字符串類型

1.2.1 String

String是不限長的,它可以包含任意的字節集,包含空字節。
String — LONGTEXT, MEDIUMTEXT, TINYTEXT, TEXT, LONGBLOB, MEDIUMBLOB, TINYBLOB, BLOB, VARCHAR, CHAR

1.2.2 FixedString

固定長度 N 的字符串,N 必須是嚴格的正自然數。當服務端讀取長度小於 N 的字符串時候,通過在字符串末尾添加空字節來達到 N 字節長度。 當服務端讀取長度大於 N 的 字符串時候,將返回錯誤消息。
與 String 相比,極少會使用 FixedString,因為使用起來不是很方便。
選擇數據時,ClickHouse 不會刪除字符串末尾的空字節。如果使用該WHERE子句,則應手動添加空字節以匹配該FixedString值。以下示例說明了如何將WHERE子句與FixedString.

CREATE TABLE FixedStringTable
(
    `s` FixedString(2)
)
ENGINE = Memory

1.2.3 UUID

UUID是一種數據庫常見的主鍵類型,在ClickHouse中直接把它作為一種數據類型。UUID共有32位,它的格式為8-4-4-4-12。如果一個UUID類型的字段在寫入數據時沒有被賦值,則會依照格式使用0填充

-- 創建一個測試表
CREATE TABLE t_uuid (
    x UUID,
    y String
) ENGINE = Memory;

-- 插入一條數據,使用generateUUIDv4()生成uuid
INSERT INTO t_uuid SELECT generateUUIDv4(), 'Example 1'

-- select查看幫我們生成了UUID
840013eee323 :) SELECT * FROM t_uuid
                
SELECT *
FROM t_uuid

Query id: 5435e8e0-592f-4c8d-b09f-a027dcc9a688

┌─x────────────────────────────────────┬─y─────────┐
│ f349e2b9-5caf-4e16-a192-1573b19b19c3 │ Example 1 │
└──────────────────────────────────────┴───────────┘

1 rows in set. Elapsed: 0.015 sec. 

-- 再插入一條數據,UUID不輸入值
INSERT INTO t_uuid (y) VALUES ('Example 2')

840013eee323 :) SELECT * FROM t_uuid
                
-- 再次查詢發現,不插入UUID,會按UUID格式全部賦值為0
SELECT *
FROM t_uuid

Query id: c8751de4-0646-4707-9923-e219f8709853

┌─x────────────────────────────────────┬─y─────────┐
│ f349e2b9-5caf-4e16-a192-1573b19b19c3 │ Example 1 │
└──────────────────────────────────────┴───────────┘
┌─x────────────────────────────────────┬─y─────────┐
│ 00000000-0000-0000-0000-000000000000 │ Example 2 │
└──────────────────────────────────────┴───────────┘

2 rows in set. Elapsed: 0.012 sec. 

1.3 時間類型

時間類型分為DateTime、DateTime64、Date、Date32四類。ClickHouse目前沒有時間戳類型。時間類型最高的精度是秒,也就是說,如果需要處理毫秒、微秒等大於秒分辨率的時間,則只能借助UInt類型實現。

1.3.1 DateTime

時間戳類型。用四個字節(無符號的)存儲 Unix 時間戳。精確到秒。
值的范圍: [1970-01-01 00:00:00, 2106-02-07 06:28:15]

Tips:

  • 將 datetime 作為整數插入時,它被視為 Unix Timestamp (UTC)。1546300800代表'2019-01-01 00:00:00'UTC。但是,由於timestamp列已Asia/Istanbul指定 (UTC+3) 時區,當輸出為字符串時,值將顯示為'2019-01-01 03:00:00'
  • 將字符串值作為日期時間插入時,它被視為在列時區中。'2019-01-01 00:00:00'將被視為處於Asia/Istanbul時區並保存為1546290000.
-- 支持的時區可通過SELECT * FROM system.time_zones查看,默認使用服務端時區,clickhouse-client可通過--use_client_time_zone使用
-- 這里指定時區Asia/Istanbul
CREATE TABLE dt_time
(
    `timestamp` DateTime('Asia/Istanbul'),
    `event_id` UInt8
)
ENGINE = Memory;

INSERT INTO dt_time Values (1546300800, 1), ('2019-01-01 00:00:00', 2);

-- 查看
840013eee323 :)  SELECT timestamp, event_id, toTypeName(timestamp) FROM dt_time;

SELECT
    timestamp,
    event_id,
    toTypeName(timestamp)
FROM dt_time

Query id: 94617fa9-ab85-4933-ac23-e89584059e3b

┌───────────timestamp─┬─event_id─┬─toTypeName(timestamp)─────┐
│ 2019-01-01 03:00:00 │        1 │ DateTime('Asia/Istanbul') │ 
│ 2019-01-01 00:00:00 │        2 │ DateTime('Asia/Istanbul') │
└─────────────────────┴──────────┴───────────────────────────┘

2 rows in set. Elapsed: 0.033 sec. 

-- 日期過濾查詢
SELECT * FROM dt_time WHERE timestamp = toDateTime('2019-01-01 00:00:00', 'Asia/Istanbul')
SELECT * FROM dt_time WHERE timestamp = '2019-01-01 00:00:00'
-- 獲取時區時間
SELECT toDateTime(now(), 'Asia/Istanbul') AS column, toTypeName(column) AS x
SELECT toDateTime(now()) AS column, toTypeName(column) AS x
-- 時區轉化
SELECT
toDateTime(timestamp, 'Europe/London') as lon_time,
toDateTime(timestamp, 'Asia/Istanbul') as mos_time
FROM dt_time

1.3.2 DateTime64

DateTime64可以記錄亞秒,它在DateTime之上增加了精度的設置。
精度:10-precision,有效范圍:[ 0 : 9 ]
常用precision - 3(毫秒)、6(微秒)、9(納秒)
語法:DateTime64(precision, [timezone])

CREATE TABLE dt_time64
(
    `timestamp` DateTime64(3, 'Asia/Istanbul'),
    `event_id` UInt8
)
ENGINE = Memory;

INSERT INTO dt_time64 Values (1546300800000, 1), ('2019-01-01 00:00:00', 2);
--查看
840013eee323 :) SELECT timestamp, event_id, toTypeName(timestamp) FROM dt_time64;
                

SELECT
    timestamp,
    event_id,
    toTypeName(timestamp)
FROM dt_time64

Query id: 58bb31be-7bb8-465b-bc9f-6afc18c72374

┌───────────────timestamp─┬─event_id─┬─toTypeName(timestamp)──────────┐
│ 2019-01-01 03:00:00.000 │        1 │ DateTime64(3, 'Asia/Istanbul') │
│ 2019-01-01 00:00:00.000 │        2 │ DateTime64(3, 'Asia/Istanbul') │
└─────────────────────────┴──────────┴────────────────────────────────┘

2 rows in set. Elapsed: 0.038 sec. 

1.3.3 Date

日期類型,用兩個字節存儲,表示從 1970-01-01 (無符號) 到當前的日期值。
取值范圍: [1970-01-01, 2149-06-06]。
注意,其實寫入一條超過時間范圍的數值也是能寫進去,並能查出來的,如:INSERT INTO dt VALUES ('2050-01-01', 3);

CREATE TABLE dt
(
    `timestamp` Date,
    `event_id` UInt8
)
ENGINE = Memory;
INSERT INTO dt VALUES (1546300800, 1), ('2019-01-01', 2);

--查看
840013eee323 :) SELECT timestamp, event_id, toTypeName(timestamp) FROM dt;

SELECT
    timestamp,
    event_id,
    toTypeName(timestamp)
FROM dt

Query id: b42b081d-de80-4a85-b735-b6f1d3d91ef1

┌──timestamp─┬─event_id─┬─toTypeName(timestamp)─┐
│ 2019-01-01 │        1 │ Date                  │
│ 2019-01-01 │        2 │ Date                  │
└────────────┴──────────┴───────────────────────┘

2 rows in set. Elapsed: 0.029 sec. 

1.3.4 Date32

日期類型,用四個字節存儲,表示從從 1925-01-01 (無符號) 到當前的日期值。
取值范圍同DateTime64的日期范圍 [1925-01-01, 2283-11-11]

CREATE TABLE dt32
(
    `timestamp` Date32,
    `event_id` UInt8
)
ENGINE = Memory;

INSERT INTO dt32 VALUES (7258118400, 1), ('2200-01-01', 2);

--查看
840013eee323 :) SELECT timestamp, event_id, toTypeName(timestamp) FROM dt32;

SELECT
    timestamp,
    event_id,
    toTypeName(timestamp)
FROM dt32

Query id: 39b2b956-6c28-4036-a5c3-d8cd2fe00006

┌──timestamp─┬─event_id─┬─toTypeName(timestamp)─┐
│ 2106-02-07 │        1 │ Date32                │
│ 2200-01-01 │        2 │ Date32                │
└────────────┴──────────┴───────────────────────┘

2 rows in set. Elapsed: 0.028 sec. 

2 復合類型

2.1 Array(T)

clickhouse起始數組索引為1,類型T可以是任何數據類型。
創建數組的兩種方式:

  • 通過函數創建:array(T)
  • 使用方擴號:[]
-- 在動態創建數組時,ClickHouse 會自動將參數類型定義為可以存儲所有列出的參數的最窄數據類型,即以最小存儲代價為原則
-- array(T)
840013eee323 :) SELECT array(1, 2) AS x, toTypeName(x)
                
SELECT
    [1, 2] AS x,
    toTypeName(x)

Query id: aaaf4542-b5bd-4c54-b7e4-42a95b65baa7

┌─x─────┬─toTypeName([1, 2])─┐
│ [1,2] │ Array(UInt8)       │
└───────┴────────────────────┘

1 rows in set. Elapsed: 0.041 sec. 

-- 方擴號 []
-- 同一數組可以有不同類型,但是類型必須兼容,如果[1, 'a']就會報錯
840013eee323 :) SELECT [1, 2.0] AS x, toTypeName(x)

SELECT
    [1, 2.] AS x,
    toTypeName(x)

Query id: fcb358f3-89de-4907-9a2d-2c581bdf98ab

┌─x─────┬─toTypeName([1, 2.])─┐
│ [1,2] │ Array(Float64)      │
└───────┴─────────────────────┘

1 rows in set. Elapsed: 0.017 sec.

-- 如果有任何Nullable或文字NULL值,則數組元素的類型會統一變為Nullable
-- 如果 ClickHouse 無法確定數據類型,則會拋出異常
840013eee323 :) SELECT array(1, 2, NULL) AS x, toTypeName(x)
                

SELECT
    [1, 2, NULL] AS x,
    toTypeName(x)

Query id: 535c4f47-c756-4903-846f-efd019a90b4d

┌─x──────────┬─toTypeName([1, 2, NULL])─┐
│ [1,2,NULL] │ Array(Nullable(UInt8))   │
└────────────┴──────────────────────────┘

1 rows in set. Elapsed: 0.024 sec. 

-- 對於多維數組,您可以使用sizeN-1指定維度,獲取該維度的大小,而不需要讀取整列
CREATE TABLE t_arr (`arr` Array(Array(Array(UInt32)))) ENGINE = MergeTree ORDER BY tuple();
INSERT INTO t_arr VALUES ([[[12, 13, 0, 1],[12]]]);

840013eee323 :) SELECT arr.size0, arr.size1, arr.size2 FROM t_arr;          

SELECT
    arr.size0,
    arr.size1,
    arr.size2
FROM t_arr

Query id: ecb76832-6005-403a-8b9e-6ffb4ead225b

┌─arr.size0─┬─arr.size1─┬─arr.size2─┐
│         1 │ [2]       │ [[4,1]]   │
└───────────┴───────────┴───────────┘
1 rows in set. Elapsed: 0.051 sec.

2.2 Tuple

元組類型由1~n個元素組成,每個元素之間允許設置不同的數據類型,且彼此之間不要求兼容。元組同樣支持類型推斷,其推斷依據仍然以最小存儲代價為原則。
元組定義方式:

  • 函數方式:tuple(T1, T2, ...)
  • 圓擴號:(T1, T2, ...)
840013eee323 :) SELECT tuple(1,'a') AS x, toTypeName(x)
                
SELECT
    (1, 'a') AS x,
    toTypeName(x)

Query id: 1b470c56-d8d0-47dc-8ac5-c7cd853b41f1

┌─x───────┬─toTypeName((1, 'a'))─┐
│ (1,'a') │ Tuple(UInt8, String) │
└─────────┴──────────────────────┘

1 rows in set. Elapsed: 0.039 sec. 

-- 查詢
CREATE TABLE named_tuples (`a` Tuple(s String, i Int64)) ENGINE = Memory;

INSERT INTO named_tuples VALUES (('y', 10)), (('x',-10));

840013eee323 :) SELECT a.s FROM named_tuples;

SELECT a.s
FROM named_tuples

Query id: b964f84a-b6de-47b2-a587-4ba790623d78

┌─a.s─┐
│ y   │
│ x   │
└─────┘

2 rows in set. Elapsed: 0.018 sec.

840013eee323 :) SELECT a.2 FROM named_tuples;

SELECT a.2
FROM named_tuples

Query id: a2f16f29-ea87-4bb5-9f24-d3e1bf845a5a

┌─tupleElement(a, 2)─┐
│                 10 │
│                -10 │
└────────────────────┘

2 rows in set. Elapsed: 0.035 sec. 

2.3 Enum

ClickHouse支持枚舉類型,這是一種在定義常量時經常會使用的數據類型。
ClickHouse支持兩種枚舉類型,它們除了取值范圍不同之外,別無二致:

  • 8 位Enum. 它最多可以包含在該[-128, 127]范圍內枚舉的 256 個值
  • 16 位Enum。它最多可以包含在該[-32768, 32767]范圍內枚舉的 65536 個值

枚舉固定使用'string' = integer鍵值對的形式定義數據。

可能有人會覺得,完全可以使用String代替枚舉,為什么還需要專門的枚舉類型呢?這是出於性能的考慮。因為雖然枚舉定義中的Key屬於String類型,但是在后續對枚舉的所有操作中(包括排序、分組、去重、過濾等),會使用Int類型的Value值。

CREATE TABLE t_enum
(
    x Enum('hello' = 1, 'world' = 2)
)
ENGINE = Memory

INSERT INTO t_enum VALUES ('hello'), ('world'), ('hello')

840013eee323 :) INSERT INTO t_enum values('a')
                
-- 插入不存在的值會報錯
840013eee323 :) INSERT INTO t_enum values('a')
               
INSERT INTO t_enum FORMAT Values

Query id: c23a0ac1-75c5-4e5b-a9f5-c359ab77f62d

Exception on client:
Code: 36. DB::Exception: Unknown element 'a' for enum: While executing ValuesBlockInputFormat: data for INSERT was parsed from query. (BAD_ARGUMENTS)

-- 查詢元素得到的是字符串name
840013eee323 :) SELECT * FROM t_enum
                

SELECT *
FROM t_enum

Query id: c4dc6929-5b77-4571-9fd1-5e4f0f9c0f26

Connecting to localhost:9000 as user default.
Connected to ClickHouse server version 22.3.3 revision 54455.

┌─x─────┐
│ hello │
│ world │
│ hello │
└───────┘

3 rows in set. Elapsed: 0.042 sec. 

-- 如果您需要查等效數字,則必須將Enum值轉換為整數類型
840013eee323 :) SELECT CAST(x, 'Int8') FROM t_enum               

SELECT CAST(x, 'Int8')
FROM t_enum

Query id: 865f450b-b725-48e2-860d-b4a17c165b9b

┌─CAST(x, 'Int8')─┐
│               1 │
│               2 │
│               1 │
└─────────────────┘

3 rows in set. Elapsed: 0.041 sec. 

-- 在查詢中創建Enum,需要CAST
840013eee323 :) SELECT toTypeName(CAST('a', 'Enum(\'a\' = 1, \'b\' = 2)'))
                

SELECT toTypeName(CAST('a', 'Enum(\'a\' = 1, \'b\' = 2)'))

Query id: 9b91895a-2200-436b-96fb-c314b3af40a1

┌─toTypeName(CAST('a', 'Enum(\'a\' = 1, \'b\' = 2)'))─┐
│ Enum8('a' = 1, 'b' = 2)                             │
└─────────────────────────────────────────────────────┘

1 rows in set. Elapsed: 0.029 sec. 

2.4 Nested

嵌套類型,顧名思義是一種嵌套表結構。一張數據表,可以定義任意多個嵌套類型字段,但每個字段的嵌套層級只支持一級,即嵌套表內不能繼續使用嵌套類型。對於簡單場景的層級關系或關聯關系,使用嵌套類型也是一種不錯的選擇。

CREATE TABLE nested_test
(
    name String,
    age UInt8,
    dept Nested
    (
        id UInt8,
        name String
    )
) ENGINE = Memory

-- 注意:nested_test與dept並不是一對一的包含關系,這樣寫入會報錯的

840013eee323 :) INSERT INTO nested_test VALUES ('nauu',18, 10000, '研發部');

INSERT INTO nested_test FORMAT Values

Query id: 7e766cc1-f146-4542-80c2-4e104e51b9bb

Exception on client:
Code: 53. DB::Exception: Type mismatch in IN or VALUES section. Expected: Array(UInt8). Got: UInt64: While executing ValuesBlockInputFormat: data for INSERT was parsed from query. (TYPE_MISMATCH)

--  嵌套類型本質是一種多維數組的結構,嵌套表中的每個字段都是一個數組,並且行與行之間數組的長度無須對齊,但是行內數組字段的長度沒有對齊
INSERT INTO nested_test VALUES ('bruce' , 30 , [10000,10001,10002], ['研發部','技術支持中心','測試部']);
INSERT INTO nested_test VALUES ('bruce' , 30 , [10000,10001], ['研發部','技術支持中心']);
840013eee323 :) INSERT INTO nested_test VALUES ('bruce' , 30 , [10000,10001], ['研發部','技術支持中心','測試部']); 

INSERT INTO nested_test FORMAT Values

Query id: e9de8279-7b4d-4ff3-8082-f22f7b0bc135


1 rows in set. Elapsed: 0.021 sec. 

Received exception from server (version 22.3.3):
Code: 190. DB::Exception: Received from localhost:9000. DB::Exception: Elements 'dept.id' and 'dept.name' of Nested data structure 'dept' (Array columns) have different array sizes.. (SIZES_OF_ARRAYS_DOESNT_MATCH)

-- 查詢
840013eee323 :) SELECT name, dept.id, dept.name FROM nested_test

SELECT
    name,
    dept.id,
    dept.name
FROM nested_test

Query id: b00fbc7a-bef1-4b8b-b3f6-a33bb3f76a06

┌─name──┬─dept.id────┬─dept.name──────────────────────────┐
│ bruce │ [16,17,18] │ ['研發部','技術支持中心','測試部'] │
└───────┴────────────┴────────────────────────────────────┘
┌─name──┬─dept.id─┬─dept.name─────────────────┐
│ bruce │ [16,17] │ ['研發部','技術支持中心'] │
└───────┴─────────┴───────────────────────────┘

2 rows in set. Elapsed: 0.033 sec. 

默認 flatten_nested = 1

-- flatten_nested = 1
SET flatten_nested = 1;
CREATE TABLE t_nest (`n` Nested(a UInt32, b UInt32)) ENGINE = MergeTree ORDER BY tuple();
840013eee323 :) SHOW CREATE TABLE t_nest;

SHOW CREATE TABLE t_nest

Query id: a9438b0c-65b0-471d-9ad0-67e0b628ae6e

┌─statement───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ CREATE TABLE default.t_nest
(
    `n.a` Array(UInt32),
    `n.b` Array(UInt32)
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS index_granularity = 8192 │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

1 rows in set. Elapsed: 0.013 sec. 

INSERT INTO t_nest VALUES ([1,2],[100,101]);

-- flatten_nested = 0
SET flatten_nested = 0;

CREATE TABLE t_nest2 (`n` Nested(a UInt32, b UInt32)) ENGINE = MergeTree ORDER BY tuple();

840013eee323 :) SHOW CREATE TABLE t_nest2;

SHOW CREATE TABLE t_nest2

Query id: 70b7cd13-ba42-40b5-933d-4035f433da1c

┌─statement───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ CREATE TABLE default.t_nest2
(
    `n` Nested(a UInt32, b UInt32)
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS index_granularity = 8192 │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

1 rows in set. Elapsed: 0.030 sec. 


INSERT INTO t_nest2 VALUES ([(1, 100)]);

2.5 Map

Map(key, value)數據類型存儲key:value對

  • key— 鍵。類型可以為:String、Integer、LowCardinality或FixedString。
  • value—值。類型可以為:String、Integer、Array、LowCardinality或FixedString
CREATE TABLE table_map (a Map(String, UInt64)) ENGINE=Memory;
INSERT INTO table_map VALUES ({'key1':1, 'key2':10}), ({'key1':2,'key2':20}), ({'key1':3,'key2':30});

-- 查詢
840013eee323 :) SELECT a['key2'] FROM table_map;
                

SELECT a['key2']
FROM table_map

Query id: 781bacf5-b11e-4b4a-9924-28e5e007f80a

┌─arrayElement(a, 'key2')─┐
│                      10 │
│                      20 │
│                      30 │
└─────────────────────────┘

3 rows in set. Elapsed: 0.020 sec.


-- 如果列中沒有此類key,則為數值類型返回0,空字符串或者空數組。
INSERT INTO table_map VALUES ({'key3':100}), ({});
840013eee323 :) SELECT a['key3'] FROM table_map;

SELECT a['key3']
FROM table_map

Query id: 605a8e55-182b-489d-b566-a14e0a0408cc

┌─arrayElement(a, 'key3')─┐
│                       0 │
│                       0 │
│                       0 │
└─────────────────────────┘
┌─arrayElement(a, 'key3')─┐
│                     100 │
│                       0 │
└─────────────────────────┘

5 rows in set. Elapsed: 0.032 sec.

3 特殊類型

3.1 Nullable

通過存儲特殊值NULL來表示缺失值,NULL是任何Nullable類型的默認值,除非在 ClickHouse 服務器配置中另有指定。需要與數據類型一起搭配使用。

  • Nullable(TypeName),這里TypeName只能是基礎類型而不能是復合數據類型Array和Tuple,如:Nullable(Int8)類型列可以存儲Int8類型值,而沒有值的行將存儲NULL
  • 但復合數據類型可以包含Nullable類型值,例如Array(Nullable(Int8))

注意:使用Nullable幾乎總是會對性能產生負面影響,在設計數據庫時請記住這一點。

  • 它只能和基礎類型搭配使用,不能用於數組和元組這些復合類型,也不能作為索引字段
  • 應該慎用Nullable類型,包括Nullable的數據表,不然會使查詢和寫入性能變慢。
    • 因為在正常情況下,每個列字段的數據會被存儲在對應的[Column].bin文件中。如果一個列字段被Nullable類型修飾后,會額外生成一個[Column].null.bin文件專門保存它的Null值。這意味着在讀取和寫入數據時,需要一倍的額外文件操作
CREATE TABLE nullable (`n` Nullable(UInt32)) ENGINE = MergeTree ORDER BY tuple();

INSERT INTO nullable VALUES (1) (NULL) (2) (NULL);

-- 可以通過使用null子列而不讀取整列來查找列中的NULL值。如果對應的值是NULL,則返回1,否則返回0
840013eee323 :) SELECT n.null FROM nullable;

SELECT n.`null`
FROM nullable

Query id: daea8aa1-82ed-41ae-90a9-8b89186970d5

┌─n.null─┐
│      0 │
│      1 │
│      0 │
│      1 │
└────────┘

4 rows in set. Elapsed: 0.031 sec. 

-- 使用示例
CREATE TABLE t_null(x Int8, y Nullable(Int8)) ENGINE Memory;
INSERT INTO t_null VALUES (1, NULL), (2, 3)

840013eee323 :) SELECT x + y FROM t_null;

SELECT x + y
FROM t_null

Query id: 041a6863-e49e-41c5-993c-9f53a304b37a

┌─plus(x, y)─┐
│       ᴺᵁᴸᴸ │
│          5 │
└────────────┘

2 rows in set. Elapsed: 0.031 sec.

3.2 Domain

  • IPv4是基於UInt32類型的域
  • IPv6是基於FixedString(16)類型的域

為什么不用字符串類型代替Domain?

  1. 出於便捷的考量,Domain類型支持格式校驗,人性化的輸入輸出格式
  2. 出於性能的考量,Pv4使用UInt32存儲,IPv6類型是基於FixedString(16),相比String更緊湊,占用空間少,查詢性能快。
CREATE TABLE hits (url String, from4 IPv4, from6 IPv6) ENGINE = MergeTree() ORDER BY url;

840013eee323 :) DESCRIBE TABLE hits;

DESCRIBE TABLE hits

Query id: 4bb5b4df-31b0-4fe1-8723-b54dbfaf1d1a

┌─name──┬─type───┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ url   │ String │              │                    │         │                  │                │
│ from4 │ IPv4   │              │                    │         │                  │                │
│ from6 │ IPv6   │              │                    │         │                  │                │
└───────┴────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘

3 rows in set. Elapsed: 0.023 sec. 

INSERT INTO hits (url, from4,from6) VALUES ('https://wikipedia.org', '116.253.40.133', '2a02:aa08:e000:3100::2')('https://clickhouse.com', '183.247.232.58', '2001:44c8:129:2632:33:0:252:2');


840013eee323 :) SELECT url, from4, toTypeName(from4), from6, toTypeName(from6) FROM hits;

SELECT
    url,
    from4,
    toTypeName(from4),
    from6,
    toTypeName(from6)
FROM hits

Query id: e9c2c4d2-62af-4282-91d8-0071c3d54f22

┌─url────────────────────┬─from4──────────┬─toTypeName(from4)─┬─from6─────────────────────────┬─toTypeName(from6)─┐
│ https://clickhouse.com │ 183.247.232.58 │ IPv4              │ 2001:44c8:129:2632:33:0:252:2 │ IPv6              │
│ https://wikipedia.org  │ 116.253.40.133 │ IPv4              │ 2a02:aa08:e000:3100::2        │ IPv6              │
└────────────────────────┴────────────────┴───────────────────┴───────────────────────────────┴───────────────────┘

2 rows in set. Elapsed: 0.048 sec. 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM