基本語法演示
-- 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 │ └────┴──────┴─────────────────────┘