基本語法演示
-- show databases ; -- create database if not exists test1 ; -- use test1 ; -- select currentDatabase() ; -- drop database test1 ;
1 數據類型
注意在CK中關鍵字嚴格區分大小寫
create table tb_test1( id Int8 , name String )engine=Memory; ┌─name─┬─type───┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐ │ id │ Int8 │ │ │ │ │ │ │ name │ String │ │ │ │ │ │ └──────┴────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
1.1 數值類型
1) IntX和UIntX

*ClickHouse支持無符號的整數,使用前綴U表示*

create table test_int(
id Int8 ,
age UInt8 ,
cdId Int32
)engine=Memory ;
注意: 和我以前的認知是一樣的,這種數據類型在數據特別精准的情況下可能出現數據精度問題!
Select 8.0/0 -->inf 正無窮
Select -8.0/0 -->inf 負無窮
Select 0/0 -->nan 非數字
如果要求更高精度的數值運算,則需要使用定點數。ClickHouse提 供了Decimal32、Decimal64和Decimal128三種精度的定點數。可以通過 兩種形式聲明定點:簡寫方式有Decimal32(S)、Decimal64(S)、
Decimal128(S)三種,原生方式為Decimal(P,S),其中:
·P代表精度,決定總位數(整數部分+小數部分),取值范圍是1 ~38;·S代表規模,決定小數位數,取值范圍是0~P

在使用兩個不同精度的定點數進行四則運算的時候,它們的小數點 位數S會發生變化。
在進行加法運算時,S取最大值。例如下面的查詢,toDecimal64(2,4)與toDecimal32(2,2)相加后S=4:
在進行減法運算時,S取最大值。例如下面的查詢,toDecimal64(2,4)與toDecimal32(2,2)相減后S=4:
在進行乘法運算時,S取最和。例如下面的查詢,toDecimal64(2,4)與toDecimal32(2,2)相乘后S=4+2:
在進行除法運算時,S取最大值。例如下面的查詢,toDecimal64(2,4)與toDecimal32(2,2)相除后S=4:但是要保證被除數的S大於除數的S,否則會報錯

1.2 字符串類型
1) String
字符串由String定義,長度不限。因此在使用String的時候無須聲明大小。它完全代替了傳統意義上數據庫的Varchar、Text、Clob和Blob等字符類型。String類型不限定字符集,因為它根本就沒有這個概念,所以可以將任意編碼的字符串存入其中。但是為了程序的規范性和可維護性,在同一套程序中應該遵循使用統一的編碼,例如“統一保持UTF-8編碼”就是一種很好的約定。所以在對數據操作的時候我們不在需要區關注編碼和亂碼問題!
2) FixedString
FixedString類型和傳統意義上的Char類型有些類似,對於一些字符有明確長度的場合,可以使用固定長度的字符串。定長字符串通過FixedString(N)聲明,其中N表示字符串長度。但與Char不同的是,FixedString使用null字節填充末尾字符,而Char通常使用空格填充。比如在下面的例子中,字符串‘abc’雖然只有3位,但長度卻是5,因為末尾有2位空字符填充 !
create table test_str( name String , job FixedString(4) -- 最長4個字符 )engine=Memory ;
3) UUID
CREATE TABLE test_uuid
(
`uid` UUID,
`name` String
)
ENGINE = Memory ;
DESCRIBE TABLE test_uuid
┌─name─┬─type───┬
│ uid │ UUID │
│ name │ String │
└──────┴────────┴
insert into test_uuid select generateUUIDv4() , 'zss' ;
select * from test_uuid ;
┌──────────────────────────────────uid─┬─name─┐
│ 47e39e22-d2d6-46fd-8014-7cd3321f4c7b │ zss │
└──────────────────────────────────────┴──────┘
-------------------------UUID類型的字段默認補位0-----------------------------
insert into test_uuid (name) values('hangge') ;
┌──────────────────────────────────uid─┬─name─┐
│ 47e39e22-d2d6-46fd-8014-7cd3321f4c7b │ zss │
└──────────────────────────────────────┴──────┘
┌──────────────────────────────────uid─┬─name───┐
│ 00000000-0000-0000-0000-000000000000 │ hangge │
└──────────────────────────────────────┴────────┘
1) Date
Date類型不包含具體的時間信息,只精確到天,支持字符串形式寫入:
CREATE TABLE test_date
(
`id` int,
`ct` Date
)
ENGINE = Memory ;
DESCRIBE TABLE test_date ;
┌─name─┬─type──┬
│ id │ Int32 │
│ ct │ Date │
└──────┴───────┴
insert into test_date vlaues(1,'2021-09-11'),(2,now()) ;
select id , ct from test_date ;
┌─id─┬─────────ct─┐
│ 1 │ 2021-09-11 │
│ 2 │ 2021-05-17 │
└────┴────────────┘
DateTime類型包含時、分、秒信息,精確到秒,支持字符串形式寫入:
create table testDataTime(ctime DateTime) engine=Memory ;
insert into testDataTime values('2021-12-27 01:11:12'),(now()) ;
select * from testDataTime ;
DateTime64可以記錄亞秒,它在DateTime之上增加了精度的設置
-- 建表
CREATE TABLE test_date_time64
(
`ctime` DateTime64
)
ENGINE = Memory ;
-- 建表
CREATE TABLE test_date_time64_2
(
`ctime` DateTime64(2)
)
ENGINE = Memory ;
-- 分別插入數據
insert into test_date_time64 values('2021-11-11 11:11:11'),(now()) ;
insert into test_date_time64_2 values('2021-11-11 11:11:11'),(now()) ;
-- 查詢數據
SELECT *
FROM test_date_time64;
┌───────────────────ctime─┐
│ 2021-11-11 11:11:11.000 │
│ 2021-05-17 10:40:51.000 │
└─────────────────────────┘
SELECT
*, toTypeName(ctime)
FROM test_date_time64
┌───────────────────ctime─┬─toTypeName(ctime)─┐
│ 2021-11-11 11:11:11.000 │ DateTime64(3) │
│ 2021-05-17 10:40:51.000 │ DateTime64(3) │
------------------------------------------------
SELECT
*, toTypeName(ctime)
FROM test_date_time64_2
┌──────────────────ctime─┬─toTypeName(ctime)─┐
│ 2021-11-11 11:11:11.00 │ DateTime64(2) │
│ 2021-05-17 10:41:26.00 │ DateTime64(2) │
└────────────────────────┴───────────────────┘
1.4 復雜類型
1) Enum
create table test_enum(id Int8 , color Enum('red'=1 , 'green'=2 , 'blue'=3)) engine=Memory ;
insert into test_enum values(1,'red'),(1,'red'),(2,'green');
也可以使用這種方式進行插入數據:
insert into test_enum values(3,3) ;
在定義枚舉集合的時候,有幾點需要注意。首先,Key和Value是不允許重復的,要保證唯一性。其次,Key和Value的值都不能為Null,但Key允許是空字符串。在寫入枚舉數據的時候,只會用到Key字符串部分,
注意: 其實我們可以使用字符串來替代Enum類型來存儲數據,那么為什么是要使用枚舉類型呢?這是出於性能的考慮。因為雖然枚舉定義中的Key屬於String類型,但是在后續對枚舉的所有操作中(包括排序、分組、去重、過濾等),會使用Int類型的Value值 ,提高處理數據的效率!
-
限制枚舉類型字段的值
-
底層存儲的是對應的Int類型的數據
-
可以使用String
2) Array(T)
CK支持數組這種復合數據類型 , 並且數據在操作在今后的數據分析中起到非常便利的效果!數組的定義方式有兩種 : array(T) [e1,e2...] , 我們在這里要求數組中的數據類型是一致的!
數組的定義
[1,2,3,4,5]
array('a' , 'b' , 'c')
[1,2,3,'hello'] -- 錯誤
create table test_array(
id Int8 ,
hobby Array(String)
)engine=Memory ;
insert into test_array values(1,['eat','drink','la']),(2,array('sleep','palyg','sql'));
┌─id─┬─hobby───────────────────┐
│ 1 │ ['eat','drink','la'] │
│ 2 │ ['sleep','palyg','sql'] │
└────┴─────────────────────────┘
select id , hobby , toTypeName(hobby) from test_array ;
┌─id─┬─hobby───────────────────┬─toTypeName(hobby)─┐
│ 1 │ ['eat','drink','la'] │ Array(String) │
│ 2 │ ['sleep','palyg','sql'] │ Array(String) │
└────┴─────────────────────────┴───────────────────┘
select id , hobby[2] , toTypeName(hobby) from test_array ; -- 數組的取值 [index] 1-based
3) Tuple
select tuple(1,'asb',12.23) as x , toTypeName(x) ;
┌─x───────────────┬─toTypeName(tuple(1, 'asb', 12.23))─┐
│ (1,'asb',12.23) │ Tuple(UInt8, String, Float64) │
└─────────────────┴────────────────────────────────────┘
---簡寫形式
SELECT
(1, 'asb', 12.23) AS x,
toTypeName(x)
┌─x───────────────┬─toTypeName(tuple(1, 'asb', 12.23))─┐
│ (1,'asb',12.23) │ Tuple(UInt8, String, Float64) │
└─────────────────┴────────────────────────────────────┘
注意:建表的時候使用元組的需要制定元組的數據類型
CREATE TABLE test_tuple (
c1 Tuple(UInt8, String, Float64)
) ENGINE = Memory;
-
-
tuple(1,2,3,'abc')
-
4) Nested
Nested是一種嵌套表結構。一張數據表,可以定義任意多個嵌套類型字段,但每個字段的嵌套層級只支持一級,即嵌套表內不能繼續使用嵌套類型。對於簡單場景的層級關系或關聯關系,使用嵌套類型也是一種不錯的選擇。
create table test_nested(
uid Int8 ,
name String ,
props Nested(
pid Int8,
pnames String ,
pvalues String
)
)engine = Memory ;
desc test_nested ;
┌─name──────────┬─type──────────┬
│ uid │ Int8 │
│ name │ String │
│ props.pid │ Array(Int8) │
│ props.pnames │ Array(String) │
│ props.pvalues │ Array(String) │
└───────────────┴───────────────┴
嵌套類型本質是一種多維數組的結構。嵌套表中的每個字段都是一個數組,並且行與行之間數組的長度無須對齊。需要注意的是,在同一行數據內每個數組字段的長度必須相等。
insert into test_nested values(1,'hadoop',[1,2,3],['p1','p2','p3'],['v1','v2','v3']);
-- 行和行之間的屬性的個數可以不一致 ,但是當前行的Nested類型中的數組個數必須一致
insert into test_nested values(2,'spark',[1,2],['p1','p2'],['v1','v2']);
SELECT *
FROM test_nested
┌─uid─┬─name───┬─props.pid─┬─props.pnames─────┬─props.pvalues────┐
│ 1 │ hadoop │ [1,2,3] │ ['p1','p2','p3'] │ ['v1','v2','v3'] │
└─────┴────────┴───────────┴──────────────────┴──────────────────┘
┌─uid─┬─name──┬─props.pid─┬─props.pnames─┬─props.pvalues─┐
│ 2 │ spark │ [1,2] │ ['p1','p2'] │ ['v1','v2'] │
└─────┴───────┴───────────┴──────────────┴───────────────┘
SELECT
uid,
name,
props.pid,
props.pnames[1]
FROM test_nested;
┌─uid─┬─name───┬─props.pid─┬─arrayElement(props.pnames, 1)─┐
│ 1 │ hadoop │ [1,2,3] │ p1 │
└─────┴────────┴───────────┴───────────────────────────────┘
┌─uid─┬─name──┬─props.pid─┬─arrayElement(props.pnames, 1)─┐
│ 2 │ spark │ [1,2] │ p1 │
└─────┴───────┴───────────┴───────────────────────────────┘
create table test_nested(
id Int8 ,
name String ,
scores Nested(
seq UInt8 ,
sx Float64 ,
yy Float64 ,
yw Float64
)
)engine = Memory ;
insert into test_nested values (1,'wbb',[1,2,3],[11,12,13],[14,14,11],[77,79,10]);
insert into test_nested values (2,'taoge',[1,2],[99,10],[14,40],[77,11]);
-- 注意 每行中的數組的個數一致 行和行之間可以不一直被
┌─id─┬─name─┬─scores.seq─┬─scores.sx──┬─scores.yy──┬─scores.yw──┐
│ 1 │ wbb │ [1,2,3] │ [11,12,13] │ [14,14,11] │ [77,79,10] │
└────┴──────┴────────────┴────────────┴────────────┴────────────┘
┌─id─┬─name──┬─scores.seq─┬─scores.sx─┬─scores.yy─┬─scores.yw─┐
│ 2 │ taoge │ [1,2] │ [99,10] │ [14,40] │ [77,11] │
└────┴───────┴────────────┴───────────┴───────────┴───────────┘
SELECT
name,
scores.sx
FROM test_nested;
┌─name─┬─scores.sx──┐
│ wbb │ [11,12,13] │
└──────┴────────────┘
┌─name──┬─scores.sx─┐
│ taoge │ [99,10] │
└───────┴───────────┘
https://repo.yandex.ru/clickhouse/rpm/testing/x86_64/ 下載新版本的CK安裝包
SET allow_experimental_geo_types = 1; CREATE TABLE geo_point (p Point) ENGINE = Memory(); INSERT INTO geo_point VALUES((10, 10)); SELECT p, toTypeName(p) FROM geo_point; ┌─p───────┬─toTypeName(p)─┐ │ (10,10) │ Point │ └─────────┴───────────────┘
SET allow_experimental_geo_types = 1; CREATE TABLE geo_ring (r Ring) ENGINE = Memory(); INSERT INTO geo_ring VALUES([(0, 0), (10, 0), (10, 10), (0, 10)]); SELECT r, toTypeName(r) FROM geo_ring; ┌─r─────────────────────────────┬─toTypeName(r)─┐ │ [(0,0),(10,0),(10,10),(0,10)] │ Ring │ └───────────────────────────────┴───────────────┘
SET allow_experimental_geo_types = 1; CREATE TABLE geo_polygon (pg Polygon) ENGINE = Memory(); INSERT INTO geo_polygon VALUES([[(20, 20), (50, 20), (50, 50), (20, 50)], [(30, 30), (50, 50), (50, 30)]]); SELECT pg, toTypeName(pg) FROM geo_polygon;
SET allow_experimental_geo_types = 1; CREATE TABLE geo_multipolygon (mpg MultiPolygon) ENGINE = Memory(); INSERT INTO geo_multipolygon VALUES([[[(0, 0), (10, 0), (10, 10), (0, 10)]], [[(20, 20), (50, 20), (50, 50), (20, 50)],[(30, 30), (50, 50), (50, 30)]]]); SELECT mpg, toTypeName(mpg) FROM geo_multipolygon;
7)IPV4
域名類型分為IPv4和IPv6兩類,本質上它們是對整型和字符串的進一步封裝。IPv4類型是基於UInt32封裝的
(1)出於便捷性的考量,例如IPv4類型支持格式檢查,格式錯誤的IP數據是無法被寫入的,例如:
INSERT INTO IP4_TEST VALUES ('www.51doit.com','192.0.0')
Code: 441. DB::Exception: Invalid IPv4 value.
(2)出於性能的考量,同樣以IPv4為例,IPv4使用UInt32存儲,相比String更加緊湊,占用的空間更小,查詢性能更快。IPv6類型是基於FixedString(16)封裝的,它的使用方法與IPv4別無二致, 在使用Domain類型的時候還有一點需要注意,雖然它從表象上看起來與String一樣,但Domain類型並不是字符串,所以它不支持隱式的自動類型轉換。如果需要返回IP的字符串形式,則需要顯式調用 IPv4NumToString或IPv6NumToString函數進行轉換。
create table test_domain( id Int8 , ip IPv4 )engine=Memory ; insert into test_domain values(1,'192.168.133.2') ; insert into test_domain values(1,'192.168.133') ; 在插入數據的會進行數據的檢查所以這行數據會報錯 -- Exception on client: -- Code: 441. DB::Exception: Invalid IPv4 value. -- Connecting to database doit1 at localhost:9000 as user default. -- Connected to ClickHouse server version 20.8.3 revision 54438.
8) Boolean和Nullable
ck中沒有Boolean類型 ,使用1和0來代表true和false
Nullable 某種數據類型允許為null , 或者是沒有給值的情況下模式是NULL
create table test_null( id Int8 , age Int8 )engine = Memory ; create table test_null2( id Int8 , age Nullable(Int8) )engine = Memory ;
2.1 DDL基礎
-
建表
目前只有MergeTree、Merge和Distributed這三類表引擎支持 ALTER查詢,所以在進行alter操作的時候注意表的引擎!
注意在建表的時候一般要求指定表的引擎
CREATE TABLE tb_test1
(
`id` Int8,
`name` String
)
ENGINE = Memory() ;
-- 只有 MergeTree支持表結構的修改
-- MergeTree一定指定主鍵和排序字段 order by 代表兩個含義
CREATE TABLE test_alter1
(
`id` Int8,
`name` String
)
ENGINE = MergeTree()
order by id ;
-- 查看建表語句 查看引擎類型參數值
show create table test_alter1 ;
-----------------------------------
CREATE TABLE doit23.test_alter1
(
`id` Int8,
`name` String
)
ENGINE = MergeTree()
ORDER BY id
SETTINGS index_granularity = 8192;
-- 查看表結構
desc tb_test1 ;
┌─name─┬─type───┬
│ id │ Int8 │
│ name │ String │
└──────┴────────┴
-- 添加字段
alter table tb_test1 add column age UInt8 ;-- 報錯 , 因為修改的表引擎是內存引擎,不支持表結構的修改
-- 創建一張MergeTree引擎的表
CREATE TABLE tb_test2
(
`id` Int8,
`name` String
)
ENGINE = MergeTree()
ORDER BY id ;
┌─name─┬─type───┬
│ id │ Int8 │
│ name │ String │
└──────┴────────┴
-- 添加字段
alter table tb_test2 add column age UInt8 ;
┌─name─┬─type───┬
│ id │ Int8 │
│ name │ String │
│ age │ UInt8 │
└──────┴────────┴
alter table tb_test2 add column gender String after name ;
┌─name───┬─type───┬
│ id │ Int8 │
│ name │ String │
│ gender │ String │
│ age │ UInt8 │
└────────┴────────┴
-- 刪除字段
alter table tb_test2 drop column age ;
-- 修改字段的數據類型
alter table tb_test2 modify column gender UInt8 default 0 ;
┌─name───┬─type───┬─default_type─┬─default_expression─┬
│ id │ Int8 │ │ │
│ name │ String │ │ │
│ gender │ UInt8 │ DEFAULT │ 0 │
└────────┴────────┴──────────────┴────────────────────┴
-- 作為一個優秀的程序員,表的字段使用注釋一種良好的習慣, 所以建議大家在操作的時候使用注釋來描述字段的意義
-- 修改 / 添加字段的注釋 內部使用的編碼默認是UTF8
alter table tb_test2 comment column name '用戶名' ;
┌─name───┬─type───┬─default_type─┬─default_expression─┬─comment─┬
│ id │ Int8 │ │ │ │
│ name │ String │ │ │ 用戶名 │
│ gender │ UInt8 │ DEFAULT │ 0 │ │
└────────┴────────┴──────────────┴────────────────────┴─────────┴
-
移動表
在Linux系統中,mv命令的本意是將一個文件從原始位置A移動到目標位置B,但是如果位 置A與位置B相同,則可以變相實現重命名的作用。ClickHouse的RENAME查詢就與之有着異曲同工之妙,RENAME語句的完整語法如下所示:
-- 修改表名 rename table tb_test1 to t1 ; -- 修改多張表名 rename table tb_test2 to t2 , t1 to tt1 ; -- 移動表到另一數據庫中 rename table t2 to test1.t ; -- 查看數據庫下的所有的表 show tables ; show tables from db_name ;
-
設置表屬性
-- 設置列的默認值
create table tb_test3(
id Int8 ,
name String comment '用戶名' ,
role String comment '角色' default 'VIP'
)engine = Log ;
┌─name─┬─type───┬─default_type─┬─default_expression─┬
│ id │ Int8 │ │ │
│ name │ String │ │ │
│ role │ String │ DEFAULT │ 'VIP' │
└──────┴────────┴──────────────┴────────────────────┴
insert into tb_test3 (id , name) values(1,'HANGGE') ;
SELECT *
FROM tb_test3 ;
┌─id─┬─name───┬─role─┐
│ 1 │ HANGGE │ VIP │
└────┴────────┴──────┘
2.2 DML基礎
1) 插入數據
INSERT語句支持三種語法范式,三種范式各有不同,可以根據寫入的需求靈活運用。
第一種方式
使用VALUES格式的常規語法
INSERT INTO [db.]table [(c1, c2, c3…)] VALUES (v11, v12, v13…), (v21, v22, v23…), ...
其中,c1、c2、c3是列字段聲明,可省略。VALUES后緊跟的是由元組組成的待寫入數據,通過下標位 與列字段聲明一一對應。數據支持批量聲明寫入,多行數據之間使用逗號分隔
第二種方式
靜態數據: cat user.txt
1,zss,23,BJ,M
2,lss,33,NJ,M
3,ww,21,SH,F
create table test_load1(
id UInt8 ,
name String ,
age UInt8 ,
city String ,
gender String
)engine=Log ;
-- 將數據導入到表中
cat user.txt | clickhouse-client -q 'insert into default.test_load1 format CSV'
clickhouse-client -q 'insert into default.test_load1 format CSV' < user.txt
上面的兩種方式都可以將數據導入到表中
-- 我們還可以執行數據行屬性的分割符
clickhouse-client --format_csv_delimiter=',' -q 'insert into default.test_load1 format CSV' < user.txt
第三種方式
INSERT INTO [db.]table [(c1, c2, c3…)] SELECT ...
雖然VALUES和SELECT子句的形式都支持聲明表達式或函數,但是表達式和函數會帶來額外的性能開銷,從而導致寫入性能的下降。所以如果追求極致的寫入性能,就應該盡可能避免使用它們。
create table log3 as log2 ; Insert into log3 select * from log2 ;
ClickHouse內部所有的數據操作都是面向Block數據塊的,所以INSERT查詢最終會將數據轉換為Block數據塊。也正因如此,INSERT語句在單個數據塊的寫入過程中是具有原子性的。在默認的情況下,每個數據塊最多可以寫入1048576行數據(由max_insert_block_size參數控制)。也就是說,如果一條INSERT語句寫入的數據少於max_insert_block_size行,那么這批數據的寫入是具有原子性的,即要么全部成功,要么全部失敗。需要注意的是,只有在ClickHouse服務端處理數據的時候才具有這種原子寫入的特性,例如使用JDBC或者HTTP接口時。因為max_insert_block_size參數在使用CLI命令行或 者INSERT SELECT子句寫入時是不生效的。
2) 更新刪除數據
ClickHouse提供了DELETE和UPDATE的能力,這類操作被稱為Mutation查詢,它可以看作ALTER語句的變種。雖然Mutation能最終實現修改和刪除,但不能完全以通常意義上的UPDATE和DELETE來理解,我們必須清醒地認識到它的不同:首先,Mutation語句是一種“很重”的操作,更適用於批量數據的修改和刪除;其次,它不支持事務,一旦語句被提交執行,就會立刻對現有數據產生影響,無法回滾;最后, Mutation語句的執行是一個異步的后台過程,語句被提交之后就會立即返回。所以這並不代表具體邏輯已經執行完畢,它的具體執行進度需要通過system.mutations系統表查詢。注意數據的修改和刪除操作是使用用MergeTree家族引擎:
只有MergeTree引擎的數據才能修改
刪除分區數據
-- 創建表
create table test_muta(
id UInt8 ,
name String ,
city String
)engine=MergeTree()
partition by city
order by id ;
-- 導入數據
clickhouse-client -q 'insert into test_muta format CSV' < data.csv
-- 刪除分區數據
alter table test_muta drop partition 'SH' ;
條件刪除數據
alter table test_muta delete where id=3 ; -- 一定加條件
條件更新數據
ALTER TABLE [db_name.]table_name UPDATE column1 = expr1 [, ...] WHERE filter_expr ALTER TABLE test_ud UPDATE name = 'my', job = 'teacher' WHERE id = '2' ; alter table test_muta update name='李思思' where id=3 ;
但是注意的時候一定指定where條否則會報錯,這種語法的where條件也可以使用子查詢 ;
2.3 分區表操作
目前只有MergeTree系列 的表引擎支持數據分區,分區的基本概念和意義和hive中的意義一樣,這里不過多贅述!
區內排序 , 合並 ,去重
create table test_partition1(
id String ,
ctime DateTime
)engine=MergeTree()
partition by toYYYYMM(ctime)
order by (id) ;
-- 查看建表語句
│ CREATE TABLE default.test_partition1
(
`id` String,
`ctime` DateTime
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(ctime)
ORDER BY id
SETTINGS index_granularity = 8192 │
-- 插入數據
insert into test_partition1 values(1,now()) ,(2,'2021-06-11 11:12:13') ;
-- 查看數據
SELECT *
FROM test_partition1 ;
┌─id─┬───────────────ctime─┐
│ 2 │ 2021-06-11 11:12:13 │
└────┴─────────────────────┘
┌─id─┬───────────────ctime─┐
│ 1 │ 2021-05-19 13:38:29 │
└────┴─────────────────────┘
-- 查看表中的分區
ClickHouse內置了許多system系統表,用於查詢自身的狀態信息。 其中parts系統表專門用於查詢數據表的分區信息。
SELECT
name,
table,
partition
FROM system.parts
WHERE table = 'test_partition1' ;
┌─name─────────┬─table───────────┬─partition─┐
│ 202105_1_1_0 │ test_partition1 │ 202105 │
│ 202106_2_2_0 │ test_partition1 │ 202106 │
└──────────────┴─────────────────┴───────────┘
insert into test_partition1 values(1,now()) ,(2,'2021-06-12 11:12:13') ;
┌─name─────────┬─table───────────┬─partition─┐
│ 202105_1_1_0 │ test_partition1 │ 202105 │
│ 202105_3_3_0 │ test_partition1 │ 202105 │
│ 202106_2_2_0 │ test_partition1 │ 202106 │
│ 202106_4_4_0 │ test_partition1 │ 202106 │
└──────────────┴─────────────────┴───────────┘
-- 刪除分區
alter table test_partition1 drop partition '202105' ;
刪除分區以后 , 分區中的所有的數據全部刪除
SELECT
name,
table,
partition
FROM system.parts
WHERE table = 'test_partition1'
┌─name─────────┬─table───────────┬─partition─┐
│ 202106_2_2_0 │ test_partition1 │ 202106 │
│ 202106_4_4_0 │ test_partition1 │ 202106 │
└──────────────┴─────────────────┴───────────┘
SELECT *
FROM test_partition1
┌─id─┬───────────────ctime─┐
│ 2 │ 2021-06-12 11:12:13 │
└────┴─────────────────────┘
┌─id─┬───────────────ctime─┐
│ 2 │ 2021-06-11 11:12:13 │
└────┴─────────────────────┘
-- 復制分區
clickHouse支持將A表的分區數據復制到B表,這項特性可以用於快速數據寫入、多表間數據同步和備份等場景,它的完整語法如下:
ALTER TABLE B REPLACE PARTITION partition_expr FROM A
不過需要注意的是,並不是任意數據表之間都能夠相互復制,它們還需要滿足兩個前提 條件:
·兩張表需要擁有相同的分區鍵
·它們的表結構完全相同。
create table test_partition2 as test_partition1 ;
show create table test_partition2 ; -- 查看表2的建表語句
│ CREATE TABLE default.test_partition2
(
`id` String,
`ctime` DateTime
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(ctime)
ORDER BY id
SETTINGS index_granularity = 8192 │ -- 兩張表的結構完全一致
-- 復制一張表的分區到另一張表中
SELECT *
FROM test_partition2
┌─id─┬───────────────ctime─┐
│ 2 │ 2021-06-12 11:12:13 │
└────┴─────────────────────┘
┌─id─┬───────────────ctime─┐
│ 2 │ 2021-06-11 11:12:13 │
└────┴─────────────────────┘
┌─id─┬───────────────ctime─┐
│ 2 │ 2021-06-21 11:12:13 │
└────┴─────────────────────┘
----------------------------
alter table test_partition2 replace partition '202106' from test_partition1
SELECT
name,
table,
partition
FROM system.parts
WHERE table = 'test_partition2'
┌─name─────────┬─table───────────┬─partition─┐
│ 202106_2_2_0 │ test_partition2 │ 202106 │
│ 202106_3_3_0 │ test_partition2 │ 202106 │
│ 202106_4_4_0 │ test_partition2 │ 202106 │
└──────────────┴─────────────────┴───────────┘
-- 重置分區數據
如果數據表某一列的數據有誤,需要將其重置為初始值,如果設置了默認值那么就是默認值數據,如果沒有設置默認值,系統會給出默認的初始值,此時可以使用下面的語句實現:
ALTER TABLE tb_name CLEAR COLUMN column_name IN PARTITION partition_expr ;
注意: 不能重置主鍵和分區字段
示例:
alter table test_rep clear column name in partition '202105' ;
-- 卸載分區
表分區可以通過DETACH語句卸載,分區被卸載后,它的物理數據並沒有刪除,而是被轉移到了當前數據表目錄的detached子目錄下。而裝載分區則是反向操作,它能夠將detached子目錄下的某個分區重新裝載回去。卸載與裝載這一對伴生的操作,常用於分區數據的遷移和備份場景
┌─id─┬─name─┬───────────────ctime─┐
│ 1 │ │ 2021-05-19 13:59:49 │
│ 2 │ │ 2021-05-19 13:59:49 │
└────┴──────┴─────────────────────┘
┌─id─┬─name─┬───────────────ctime─┐
│ 3 │ ww │ 2021-04-11 11:12:13 │
└────┴──────┴─────────────────────┘
alter table test_rep detach partition '202105' ;
┌─id─┬─name─┬───────────────ctime─┐
│ 3 │ ww │ 2021-04-11 11:12:13 │
└────┴──────┴─────────────────────┘
-- 裝載分區
alter table test_rep attach partition '202105' ;
┌─id─┬─name─┬───────────────ctime─┐
│ 1 │ │ 2021-05-19 13:59:49 │
│ 2 │ │ 2021-05-19 13:59:49 │
└────┴──────┴─────────────────────┘
┌─id─┬─name─┬───────────────ctime─┐
│ 3 │ ww │ 2021-04-11 11:12:13 │
└────┴──────┴─────────────────────┘

