篇三|ClickHouse的數據類型

ClickHouse提供了許多數據類型,它們能夠劃分爲基礎類型、複合類型和特殊類型。咱們能夠在system.data_type_families表中檢查數據類型名稱以及是否區分大小寫。sql

SELECT * FROM system.data_type_families

上面的系統表,存儲了ClickHouse所支持的數據類型,注意不一樣版本的ClickHouse可能數據類型會有所不一樣,具體以下表所示:數據庫

┌─name────────────────────┬─case_insensitive─┬─alias_to────┐
│ IPv6                    │                0 │             │
│ IPv4                    │                0 │             │
│ LowCardinality          │                0 │             │
│ Decimal                 │                1 │             │
│ String                  │                0 │             │
│ Decimal64               │                1 │             │
│ Decimal32               │                1 │             │
│ Decimal128              │                1 │             │
│ Float64                 │                0 │             │
│ Float32                 │                0 │             │
│ Int64                   │                0 │             │
│ SimpleAggregateFunction │                0 │             │
│ Array                   │                0 │             │
│ Nothing                 │                0 │             │
│ UInt16                  │                0 │             │
│ Enum16                  │                0 │             │
│ UInt32                  │                0 │             │
│ Date                    │                1 │             │
│ Int8                    │                0 │             │
│ Int32                   │                0 │             │
│ Enum8                   │                0 │             │
│ UInt64                  │                0 │             │
│ IntervalSecond          │                0 │             │
│ Int16                   │                0 │             │
│ FixedString             │                0 │             │
│ Nullable                │                0 │             │
│ AggregateFunction       │                0 │             │
│ DateTime                │                1 │             │
│ Enum                    │                0 │             │
│ Tuple                   │                0 │             │
│ IntervalMonth           │                0 │             │
│ Nested                  │                0 │             │
│ IntervalMinute          │                0 │             │
│ IntervalHour            │                0 │             │
│ IntervalWeek            │                0 │             │
│ IntervalDay             │                0 │             │
│ UInt8                   │                0 │             │
│ IntervalQuarter         │                0 │             │
│ UUID                    │                0 │             │
│ IntervalYear            │                0 │             │
│ LONGBLOB                │                1 │ String      │
│ MEDIUMBLOB              │                1 │ String      │
│ TINYBLOB                │                1 │ String      │
│ BIGINT                  │                1 │ Int64       │
│ SMALLINT                │                1 │ Int16       │
│ TIMESTAMP               │                1 │ DateTime    │
│ INTEGER                 │                1 │ Int32       │
│ INT                     │                1 │ Int32       │
│ DOUBLE                  │                1 │ Float64     │
│ MEDIUMTEXT              │                1 │ String      │
│ TINYINT                 │                1 │ Int8        │
│ DEC                     │                1 │ Decimal     │
│ BINARY                  │                1 │ FixedString │
│ FLOAT                   │                1 │ Float32     │
│ CHAR                    │                1 │ String      │
│ VARCHAR                 │                1 │ String      │
│ TEXT                    │                1 │ String      │
│ TINYTEXT                │                1 │ String      │
│ LONGTEXT                │                1 │ String      │
│ BLOB                    │                1 │ String      │
└─────────────────────────┴──────────────────┴─────────────┘

數值類型

Int類型

固定長度的整數類型又包括有符號和無符號的整數類型。apache

  • 有符號整數類型
類型 字節 範圍
Int8 1 [-2^7 ~2^7-1]
Int16 2 [-2^15 ~ 2^15-1]
Int32 4 [-2^31 ~ 2^31-1]
Int64 8 [-2^63 ~ 2^63-1]
Int128 16 [-2^127 ~ 2^127-1]
Int256 32 [-2^255 ~ 2^255-1]
  • 無符號類型
類型 字節 範圍
UInt8 1 [0 ~2^8-1]
UInt16 2 [0 ~ 2^16-1]
UInt32 4 [0 ~ 2^32-1]
UInt64 8 [0 ~ 2^64-1]
UInt256 32 [0 ~ 2^256-1]

浮點類型

  • 單精度浮點數

Float32從小數點後第8位起會發生數據溢出數組

類型 字節 精度
Float32 4 7
  • 雙精度浮點數

Float32從小數點後第17位起會發生數據溢出bash

類型 字節 精度
Float64 8 16
  • 示例
-- Float32類型,從第8爲開始產生數據溢出
kms-1.apache.com :) select toFloat32(0.123456789);

SELECT toFloat32(0.123456789)

┌─toFloat32(0.123456789)─┐
│             0.12345679 │
└────────────────────────┘
-- Float64類型,從第17爲開始產生數據溢出
kms-1.apache.com :) select toFloat64(0.12345678901234567890);

SELECT toFloat64(0.12345678901234568)

┌─toFloat64(0.12345678901234568)─┐
│            0.12345678901234568 │
└────────────────────────────────┘

Decimal類型

有符號的定點數,可在加、減和乘法運算過程當中保持精度。ClickHouse提供了Decimal3二、Decimal64和Decimal128三種精度的定點數,支持幾種寫法:服務器

  • Decimal(P, S)
  • Decimal32(S)

    數據範圍:( -1 10^(9 - S), 1 10^(9 - S) )函數

  • Decimal64(S)

    數據範圍:( -1 10^(18 - S), 1 10^(18 - S) )大數據

  • Decimal128(S)

    數據範圍: ( -1 10^(38 - S), 1 10^(38 - S) )ui

  • Decimal256(S)

    數據範圍:( -1 10^(76 - S), 1 10^(76 - S) )url

其中:P表明精度,決定總位數(整數部分+小數部分),取值範圍是1~76

S表明規模,決定小數位數,取值範圍是0~P

根據P的範圍,能夠有以下的等同寫法:

P 取值 原生寫法示例 等同於
[ 1 : 9 ] Decimal(9,2) Decimal32(2)
[ 10 : 18 ] Decimal(18,2) Decimal64(2)
[ 19 : 38 ] Decimal(38,2) Decimal128(2)
[ 39 : 76 ] Decimal(76,2) Decimal256(2)

注意點:不一樣精度的數據進行四則運算時,精度(總位數)和規模(小數點位數)會發生變化,具體規則以下:

  • 精度對應的規則

    • Decimal64(S1) 運算符 Decimal32(S2) -> Decimal64(S)
    • Decimal128(S1) 運算符 Decimal32(S2) -> Decimal128(S)
    • Decimal128(S1) 運算符 Decimal64(S2) -> Decimal128(S)
    • Decimal256(S1) 運算符 Decimal<32|64|128>(S2) -> Decimal256(S)

能夠看出:兩個不一樣精度的數據進行四則運算時,結果數據已最大精度爲準

  • 規模(小數點位數)對應的規則

    • 加法|減法:S = max(S1, S2),即以兩個數據中小數點位數最多的爲準
    • 乘法: S = S1 + S2(注意:S1精度 >= S2精度),即以兩個數據的小數位相加爲準
  • 除法: S = S1,即被除數的小數位爲準
-- toDecimal32(value, S)
  -- 加法,S取二者最大的,P取二者最大的
  SELECT
      toDecimal64(2, 3) AS x,
      toTypeName(x) AS xtype,
      toDecimal32(2, 2) AS y,
      toTypeName(y) as ytype,
      x + y AS z,
      toTypeName(z) AS ztype;
  -- 結果輸出
  ┌─────x─┬─xtype──────────┬────y─┬─ytype─────────┬─────z─┬─ztype──────────┐
  │ 2.000 │ Decimal(18, 3) │ 2.00 │ Decimal(9, 2) │ 4.000 │ Decimal(18, 3) │
  └───────┴────────────────┴──────┴───────────────┴───────┴────────────────┘
  -- 乘法,比較特殊,與這兩個數的順序有關
  -- 以下:x類型是Decimal64,y類型是Decimal32,順序是x*y,小數位S=S1+S2
  SELECT
      toDecimal64(2, 3) AS x,
      toTypeName(x) AS xtype,
      toDecimal32(2, 2) AS y,
      toTypeName(y) as ytype,
      x * y AS z,
      toTypeName(z) AS ztype;
  -- 結果輸出   
  ┌─────x─┬─xtype──────────┬────y─┬─ytype─────────┬───────z─┬─ztype──────────┐
  │ 2.000 │ Decimal(18, 3) │ 2.00 │ Decimal(9, 2) │ 4.00000 │ Decimal(18, 5) │
  └───────┴────────────────┴──────┴───────────────┴─────────┴────────────────┘
  -- 交換相乘的順序,y*x,小數位S=S1*S2
  SELECT
      toDecimal64(2, 3) AS x,
      toTypeName(x) AS xtype,
      toDecimal32(2, 2) AS y,
      toTypeName(y) as ytype,
      y * x AS z,
      toTypeName(z) AS ztype;
  -- 結果輸出
  ┌─────x─┬─xtype──────────┬────y─┬─ytype─────────┬────────z─┬─ztype──────────┐
  │ 2.000 │ Decimal(18, 3) │ 2.00 │ Decimal(9, 2) │ 0.400000 │ Decimal(18, 6) │
  └───────┴────────────────┴──────┴───────────────┴──────────┴────────────────┘
  -- 除法,小數位與被除數保持一致
  SELECT
      toDecimal64(2, 3) AS x,
      toTypeName(x) AS xtype,
      toDecimal32(2, 2) AS y,
      toTypeName(y) as ytype,
      x / y AS z,
      toTypeName(z) AS ztype;
  -- 結果輸出
  ┌─────x─┬─xtype──────────┬────y─┬─ytype─────────┬─────z─┬─ztype──────────┐
  │ 2.000 │ Decimal(18, 3) │ 2.00 │ Decimal(9, 2) │ 1.000 │ Decimal(18, 3) │
  └───────┴────────────────┴──────┴───────────────┴───────┴────────────────┘

字符串類型

String

字符串能夠是任意長度的。它能夠包含任意的字節集,包含空字節。所以,字符串類型能夠代替其餘 DBMSs 中的VARCHAR、BLOB、CLOB 等類型。

FixedString

固定長度的N字節字符串,通常在在一些明確字符串長度的場景下使用,聲明方式以下:

-- N表示字符串的長度
<column_name> FixedString(N)

值得注意的是:FixedString使用null字節填充末尾字符。

-- 雖然hello只有5位,但最終字符串是6位
select toFixedString('hello',6) as a,length(a) as alength;
-- 結果輸出

┌─a─────┬─alength─┐
│ hello │       6 │
└───────┴─────────┘
-- 注意對於固定長度的字符串進行比較時,會出現不同的結果
-- 以下:因爲a是6位字符,而hello是5位,因此二者不相等
select toFixedString('hello',6) as a,a = 'hello' ,length(a) as alength;    
-- 結果輸出
┌─a─────┬─equals(toFixedString('hello', 6), 'hello')─┬─alength─┐
│ hello │                                          0 │       6 │
└───────┴────────────────────────────────────────────┴─────────┘

-- 須要使用下面的方式
select toFixedString('hello',6) as a,a = 'hello\0' ,length(a) as alength;
-- 結果輸出

┌─a─────┬─equals(toFixedString('hello', 6), 'hello\0')─┬─alength─┐
│ hello │                                            1 │       6 │
└───────┴──────────────────────────────────────────────┴─────────┘

UUID

UUID是一種數據庫常見的主鍵類型,在ClickHouse中直接把它做爲一種數據類型。UUID共有32位,它的格式爲8-4-4-4-12,好比:

61f0c404-5cb3-11e7-907b-a6006ad3dba0
-- 當不指定uuid列的值時,填充爲0
00000000-0000-0000-0000-000000000000

使用示例以下:

-- 建表
CREATE TABLE t_uuid (x UUID, y String) ENGINE=TinyLog;
-- insert數據
INSERT INTO t_uuid SELECT generateUUIDv4(), 'Example 1';
INSERT INTO t_uuid (y) VALUES ('Example 2');
SELECT * FROM t_uuid;
-- 結果輸出,默認被填充爲0
┌────────────────────────────────────x─┬─y─────────┐
│ b6b019b5-ee5c-4967-9c4d-8ff95d332230 │ Example 1 │
│ 00000000-0000-0000-0000-000000000000 │ Example 2 │
└──────────────────────────────────────┴───────────┘

日期類型

時間類型分爲DateTime、DateTime64和Date三類。須要注意的是ClickHouse目前沒有時間戳類型,也就是說,時間類型最高的精度是秒,因此若是須要處理毫秒、微秒精度的時間,則只能藉助UInt類型實現。

Date類型

用兩個字節存儲,表示從 1970-01-01 (無符號) 到當前的日期值。日期中沒有存儲時區信息。

CREATE TABLE t_date (x date) ENGINE=TinyLog;
INSERT INTO t_date VALUES('2020-10-01');
SELECT x,toTypeName(x) FROM t_date;
┌──────────x─┬─toTypeName(x)─┐
│ 2020-10-01 │ Date          │
└────────────┴───────────────┘

DateTime類型

用四個字節(無符號的)存儲 Unix 時間戳。容許存儲與日期類型相同的範圍內的值。最小值爲 0000-00-00 00:00:00。時間戳類型值精確到秒(沒有閏秒)。時區使用啓動客戶端或服務器時的系統時區。

CREATE TABLE t_datetime(`timestamp` DateTime) ENGINE = TinyLog;
INSERT INTO t_datetime Values('2020-10-01 00:00:00');
SELECT * FROM t_datetime;
-- 結果輸出
┌───────────timestamp─┐
│ 2020-10-01 00:00:00 │
└─────────────────────┘
-- 注意,DateTime類型是區分時區的
SELECT 
    toDateTime(timestamp, 'Asia/Shanghai') AS column,
    toTypeName(column) AS x 
FROM t_datetime;
-- 結果輸出
┌──────────────column─┬─x─────────────────────────┐
│ 2020-10-01 00:00:00 │ DateTime('Asia/Shanghai') │
└─────────────────────┴───────────────────────────┘
SELECT
     toDateTime(timestamp, 'Europe/Moscow') AS column,
     toTypeName(column) AS x 
FROM t_datetime; 
-- 結果輸出
┌──────────────column─┬─x─────────────────────────┐
│ 2020-09-30 19:00:00 │ DateTime('Europe/Moscow') │
└─────────────────────┴───────────────────────────┘

布爾類型

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

數組類型

Array(T),由 T 類型元素組成的數組。T 能夠是任意類型,包含數組類型。但不推薦使用多維數組,ClickHouse對多維數組的支持有限。例如,不能在MergeTree表中存儲多維數組。

SELECT array(1, 2) AS x, toTypeName(x);
-- 結果輸出
┌─x─────┬─toTypeName(array(1, 2))─┐
│ [1,2] │ Array(UInt8)            │
└───────┴─────────────────────────┘
SELECT [1, 2] AS x, toTypeName(x);
-- 結果輸出
┌─x─────┬─toTypeName([1, 2])─┐
│ [1,2] │ Array(UInt8)       │
└───────┴────────────────────┘

須要注意的是,數組元素中若是存在Null值,則元素類型將變爲Nullable。

SELECT array(1, 2, NULL) AS x, toTypeName(x);
-- 結果輸出
┌─x──────────┬─toTypeName(array(1, 2, NULL))─┐
│ [1,2,NULL] │ Array(Nullable(UInt8))        │
└────────────┴───────────────────────────────┘

另外,數組類型裏面的元素必須具備相同的數據類型,不然會報異常

SELECT array(1, 'a')
-- 報異常
DB::Exception: There is no supertype for types UInt8, String because some of them are String/FixedString and some of them are not

枚舉類型

枚舉類型一般在定義常量時使用,ClickHouse提供了Enum8和Enum16兩種枚舉類型。

-- 建表
CREATE TABLE t_enum
(
    x Enum8('hello' = 1, 'world' = 2)
)
ENGINE = TinyLog;
-- INSERT數據
INSERT INTO t_enum VALUES ('hello'), ('world'), ('hello');
-- 若是定義了枚舉類型值以後,不能寫入其餘值的數據
INSERT INTO t_enum values('a')
-- 報異常:Unknown element 'a' for type Enum8('hello' = 1, 'world' = 2)

Tuple類型

Tuple(T1, T2, ...),元組,與Array不一樣的是,Tuple中每一個元素都有單獨的類型,不能在表中存儲元組(除了內存表)。它們能夠用於臨時列分組。在查詢中,IN表達式和帶特定參數的 lambda 函數能夠來對臨時列進行分組。

SELECT tuple(1,'a') AS x, toTypeName(x);
--結果輸出
┌─x───────┬─toTypeName(tuple(1, 'a'))─┐
│ (1,'a') │ Tuple(UInt8, String)      │
└─────────┴───────────────────────────┘
-- 建表
CREATE TABLE t_tuple(
   c1 Tuple(String,Int8)
) engine=TinyLog;
-- INSERT數據
INSERT INTO t_tuple VALUES(('jack',20));
--查詢數據
SELECT * FROM t_tuple;
┌─c1──────────┐
│ ('jack',20) │
└─────────────┘
-- 若是插入數據類型不匹配,會報異常
INSERT INTO t_tuple VALUES(('tom','20'));
-- Type mismatch in IN or VALUES section. Expected: Int8. Got: String

特殊數據類型

Nullable

Nullable類型表示某個基礎數據類型能夠是Null值。其具體用法以下所示:

-- 建表
CREATE TABLE t_null(x Int8, y Nullable(Int8)) ENGINE TinyLog
-- 寫入數據
INSERT INTO t_null VALUES (1, NULL), (2, 3);
SELECT x + y FROM t_null;
-- 結果
┌─plus(x, y)─┐
│       ᴺᵁᴸᴸ │
│          5 │
└────────────┘

Domain

Domain類型是特定實現的類型:

IPv4是與UInt32類型保持二進制兼容的Domain類型,用於存儲IPv4地址的值。它提供了更爲緊湊的二進制存儲的同時支持識別可讀性更加友好的輸入輸出格式。

IPv6是與FixedString(16)類型保持二進制兼容的Domain類型,用於存儲IPv6地址的值。它提供了更爲緊湊的二進制存儲的同時支持識別可讀性更加友好的輸入輸出格式。

注意低版本的ClickHouse不支持此類型。

-- 建表
CREATE TABLE hits
(url String, 
 from IPv4
) ENGINE = MergeTree()
ORDER BY from;
-- 寫入數據
INSERT INTO hits (url, from) VALUES
('https://wikipedia.org', '116.253.40.133')
('https://clickhouse.tech', '183.247.232.58');

-- 查詢
SELECT * FROM hits;
┌─url─────────────────────┬───────────from─┐
│ https://wikipedia.org   │ 116.253.40.133 │
│ https://clickhouse.tech │ 183.247.232.58 │
└─────────────────────────┴────────────────┘

公衆號『大數據技術與數倉』,回覆『資料』領取大數據資料包

相關文章
相關標籤/搜索