來(lái)自俄羅斯的兇猛彪悍的分析數(shù)據(jù)庫(kù)-ClickHouse
點(diǎn)擊上方藍(lán)色字體,選擇“設(shè)為星標(biāo)”

ClickHouse相關(guān)文章推薦:
ClickHouse 是一款由俄羅斯Yandex公司開源的OLAP數(shù)據(jù)庫(kù),擁有者卓越的性能表現(xiàn),在官方公布的基準(zhǔn)測(cè)試中,ClickHouse的平均響應(yīng)速度是Vertica的2.63倍、InfiniDB的17倍、MonetDB的27倍、Hive的126倍、MySQL的429倍以及Greenplum的10倍。
自2016年開源以來(lái),ClickHouse一直保持著飛速的發(fā)展,是目前業(yè)界公認(rèn)的OLAP數(shù)據(jù)庫(kù)黑馬,已在頭條、阿里、騰訊、新浪、青云等眾多公司得以應(yīng)用。
作為一款分析型數(shù)據(jù)庫(kù),ClickHouse提供了許多數(shù)據(jù)類型,它們可以劃分為基礎(chǔ)類型、復(fù)合類型和特殊類型。其中基礎(chǔ)類型使ClickHouse具備了描述數(shù)據(jù)的基本能力,而另外兩種類型則使ClickHouse的數(shù)據(jù)表達(dá)能力更加豐富立體。
本文主要來(lái)談ClickHouse的復(fù)合類型,ClickHouse提供了數(shù)組、元組、枚舉和嵌套四類復(fù)合類型。這些類型通常是其他數(shù)據(jù)庫(kù)原生不具備的特性。擁有了復(fù)合類型之后,ClickHouse的數(shù)據(jù)模型表達(dá)能力更強(qiáng)了。
Array
數(shù)組有兩種定義形式,常規(guī)方式array(T):
SELECT array(1, 2) as a , toTypeName(a)
┌─a───┬─toTypeName(array(1, 2))─┐
│ [1,2] │ Array(UInt8) ?????????????│
└─────┴────────────────┘
或者簡(jiǎn)寫方式[T]:
SELECT [1, 2]
通過(guò)上述的例子可以發(fā)現(xiàn),在查詢時(shí)并不需要主動(dòng)聲明數(shù)組的元素類型。因?yàn)镃lickHouse的數(shù)組擁有類型推斷的能力,推斷依據(jù):以最小存儲(chǔ)代價(jià)為原則,即使用最小可表達(dá)的數(shù)據(jù)類型。例如在上面的例子中,array(1, 2)會(huì)通過(guò)自動(dòng)推斷將UInt8作為數(shù)組類型。但是數(shù)組元素中如果存在Null值,則元素類型將變?yōu)镹ullable,例如:
?SELECT [1, 2, null] as a , toTypeName(a)
┌─a──────┬─toTypeName([1, 2, NULL])─┐
│ [1,2,NULL] │ Array(Nullable(UInt8)) ???│
└────────┴─────────────────┘
細(xì)心的讀者可能已經(jīng)發(fā)現(xiàn),在同一個(gè)數(shù)組內(nèi)可以包含多種數(shù)據(jù)類型,例如數(shù)組[1, 2.0]是可行的。但各類型之間必須兼容,例如數(shù)組[1, '2']則會(huì)報(bào)錯(cuò)。
在定義表字段時(shí),數(shù)組需要指定明確的元素類型,例如:
CREATE TABLE Array_TEST (
????c1 Array(String)
) engine = Memory
2. Tuple
元組類型由1~n個(gè)元素組成,每個(gè)元素之間允許設(shè)置不同的數(shù)據(jù)類型,且彼此之間不要求兼容。元組同樣支持類型推斷,其推斷依據(jù)仍然以最小存儲(chǔ)代價(jià)為原則。與數(shù)組類似,元組也可以使用兩種方式定義,常規(guī)方式tuple(T):
SELECT tuple(1,'a',now()) AS x, toTypeName(x)
┌─x─────────────────┬─toTypeName(tuple(1, 'a', now()))─┐
│ (1,'a','2019-08-28 21:36:32') │ Tuple(UInt8, String, DateTime) ???│
└───────────────────┴─────────────────────┘
或者簡(jiǎn)寫方式(T):
SELECT (1,2.0,null) AS x, toTypeName(x)
┌─x──────┬─toTypeName(tuple(1, 2., NULL))───────┐
│ (1,2,NULL) │ Tuple(UInt8, Float64, Nullable(Nothing)) │
└───────┴──────────────────────────┘
在定義表字段時(shí),元組也需要指定明確的元素類型:
CREATE TABLE Tuple_TEST (
????c1 Tuple(String,Int8)
) ENGINE = Memory;
元素類型和泛型的作用類似,可以進(jìn)一步保障數(shù)據(jù)質(zhì)量。在數(shù)據(jù)寫入的過(guò)程中會(huì)進(jìn)行類型檢查。例如,寫入INSERT INTO Tuple_TEST VALUES( ('abc' , 123) )是可行的,而寫入INSERT INTO Tuple_TEST VALUES( ('abc' , 'efg') )則會(huì)報(bào)錯(cuò)。
3. Enum
ClickHouse支持枚舉類型,這是一種在定義常量時(shí)經(jīng)常會(huì)使用的數(shù)據(jù)類型。ClickHouse提供了Enum8和Enum16兩種枚舉類型,它們除了取值范圍不同之外,別無(wú)二致。枚舉固定使用(String:Int) Key/Value鍵值對(duì)的形式定義數(shù)據(jù),所以Enum8和Enum16分別會(huì)對(duì)應(yīng)(String:Int8)和(String:Int16),例如:
CREATE TABLE Enum_TEST (
????c1 Enum8('ready' = 1, 'start' = 2, 'success' = 3, 'error' = 4)
) ENGINE = Memory;
在定義枚舉集合的時(shí)候,有幾點(diǎn)需要注意。首先,Key和Value是不允許重復(fù)的,要保證唯一性。其次,Key和Value的值都不能為Null,但Key允許是空字符串。在寫入枚舉數(shù)據(jù)的時(shí)候,只會(huì)用到Key字符串部分,例如:
INSERT INTO Enum_TEST VALUES('ready');
INSERT INTO Enum_TEST VALUES('start');
數(shù)據(jù)在寫入的過(guò)程中,會(huì)對(duì)照枚舉集合項(xiàng)的內(nèi)容逐一檢查。如果Key字符串不在集合范圍內(nèi)則會(huì)拋出異常,比如執(zhí)行下面的語(yǔ)句就會(huì)出錯(cuò):
INSERT INTO Enum_TEST VALUES('stop');
可能有人會(huì)覺得,完全可以使用String代替枚舉,為什么還需要專門的枚舉類型呢?這是出于性能的考慮。因?yàn)殡m然枚舉定義中的Key屬于String類型,但是在后續(xù)對(duì)枚舉的所有操作中(包括排序、分組、去重、過(guò)濾等),會(huì)使用Int類型的Value值。
4. Nested
嵌套類型,顧名思義是一種嵌套表結(jié)構(gòu)。一張數(shù)據(jù)表,可以定義任意多個(gè)嵌套類型字段,但每個(gè)字段的嵌套層級(jí)只支持一級(jí),即嵌套表內(nèi)不能繼續(xù)使用嵌套類型。對(duì)于簡(jiǎn)單場(chǎng)景的層級(jí)關(guān)系或關(guān)聯(lián)關(guān)系,使用嵌套類型也是一種不錯(cuò)的選擇。例如,下面的nested_test是一張模擬的員工表,它的所屬部門字段就使用了嵌套類型:
CREATE TABLE nested_test (
????name String,
????age ?UInt8 ,
????dept Nested(
????????id UInt8,
????????name String
????)
) ENGINE = Memory;
ClickHouse的嵌套類型和傳統(tǒng)的嵌套類型不相同,導(dǎo)致在初次接觸它的時(shí)候會(huì)讓人十分困惑。以上面這張表為例,如果按照它的字面意思來(lái)理解,會(huì)很容易理解成nested_test與dept 是一對(duì)一的包含關(guān)系,其實(shí)這是錯(cuò)誤的。不信可以執(zhí)行下面的語(yǔ)句,看看會(huì)是什么結(jié)果:
INSERT INTO nested_test VALUES ('nauu',18, 10000, '研發(fā)部');
Exception on client:
Code: 53. DB::Exception: Type mismatch in IN or VALUES section. Expected: Array(UInt8). Got: UInt64
注意上面的異常信息,它提示期望寫入的是一個(gè)Array數(shù)組類型。
現(xiàn)在大家應(yīng)該明白了,嵌套類型本質(zhì)是一種多維數(shù)組的結(jié)構(gòu)。嵌套表中的每個(gè)字段都是一個(gè)數(shù)組,并且行與行之間數(shù)組的長(zhǎng)度無(wú)須對(duì)齊。所以需要把剛才的INSERT語(yǔ)句調(diào)整成下面的形式:
INSERT INTO nested_test VALUES ('bruce' , 30 , [10000,10001,10002], ['研發(fā)部','技術(shù)支持中心','測(cè)試部']);
--行與行之間,數(shù)組長(zhǎng)度無(wú)須對(duì)齊
INSERT INTO nested_test VALUES ('bruce' , 30 , [10000,10001], ['研發(fā)部','技術(shù)支持中心']);
需要注意的是,在同一行數(shù)據(jù)內(nèi)每個(gè)數(shù)組字段的長(zhǎng)度必須相等。例如,在下面的示例中,由于行內(nèi)數(shù)組字段的長(zhǎng)度沒(méi)有對(duì)齊,所以會(huì)拋出異常:
INSERT INTO nested_test VALUES ('bruce' , 30 , [10000,10001], ['研發(fā)部','技術(shù)支持中心',
'測(cè)試部']);
DB::Exception: Elements 'dept.id' and 'dept.name' of Nested data structure 'dept' (Array columns) have different array sizes..
在訪問(wèn)嵌套類型的數(shù)據(jù)時(shí)需要使用點(diǎn)符號(hào),例如:
SELECT name, dept.id, dept.name FROM nested_test
┌─name─┬─dept.id──┬─dept.name─────────────┐
│ bruce │ [16,17,18] │ ['研發(fā)部','技術(shù)支持中心','測(cè)試部'] │
└────┴───────┴────────────────────┘
關(guān)于作者:
朱凱,ClickHouse貢獻(xiàn)者之一,ClickHouse布道者,資深架構(gòu)師,十多年IT從業(yè)經(jīng)驗(yàn),對(duì)大數(shù)據(jù)領(lǐng)域主流技術(shù)與解決方案有深入研究,擅長(zhǎng)分布式系統(tǒng)的架構(gòu)設(shè)計(jì)與整合。曾主導(dǎo)過(guò)多款大數(shù)據(jù)平臺(tái)級(jí)產(chǎn)品的規(guī)劃、設(shè)計(jì)與研發(fā)工作,一線實(shí)戰(zhàn)經(jīng)驗(yàn)豐富?,F(xiàn)就職于遠(yuǎn)光軟件股份有限公司,任大數(shù)據(jù)事業(yè)部平臺(tái)開發(fā)部總經(jīng)理。著有《企業(yè)級(jí)大數(shù)據(jù)平臺(tái)構(gòu)建:架構(gòu)與實(shí)現(xiàn)》?《ClickHouse原理解析與應(yīng)用實(shí)踐》等書。
國(guó)內(nèi)首本全方位講解ClickHouse的技術(shù)書,這是一本可幫助讀者深度理解并全面掌握ClickHouse運(yùn)行原理并進(jìn)行實(shí)踐開發(fā)的工具書,涵蓋了ClickHouse的時(shí)代背景、發(fā)展歷程、核心概念、基礎(chǔ)功能、運(yùn)行原理、實(shí)踐指導(dǎo)等多個(gè)維度的內(nèi)容。一本書幫你駕馭ClickHouse。

版權(quán)聲明:
文章不錯(cuò)?點(diǎn)個(gè)【在看】吧!??




