從使用場(chǎng)景來(lái)說(shuō)诸典,Clickhouse是個(gè)分析型數(shù)據(jù)庫(kù)。這種場(chǎng)景下今膊,數(shù)據(jù)一般是不變的些阅,因此Clickhouse對(duì)update、delete的支持是比較弱的斑唬,實(shí)際上并不支持標(biāo)準(zhǔn)的update市埋、delete操作。
下面介紹一下Clickhouse中update恕刘、delete的使用缤谎。
更新、刪除語(yǔ)法
Clickhouse通過(guò)alter方式實(shí)現(xiàn)更新褐着、刪除弓千,它把update、delete操作叫做mutation(突變)献起。語(yǔ)法為:
ALTER TABLE [db.]table DELETE WHERE filter_expr
ALTER TABLE [db.]table UPDATE column1 = expr1 [, ...] WHERE filter_expr
那么洋访,mutation與標(biāo)準(zhǔn)的update镣陕、delete有什么區(qū)別呢?
標(biāo)準(zhǔn)SQL的更新姻政、刪除操作是同步的呆抑,即客戶(hù)端要等服務(wù)端反回執(zhí)行結(jié)果(通常是int值);而Clickhouse的update汁展、delete是通過(guò)異步方式實(shí)現(xiàn)的鹊碍,當(dāng)執(zhí)行update語(yǔ)句時(shí),服務(wù)端立即反回食绿,但是實(shí)際上此時(shí)數(shù)據(jù)還沒(méi)變侈咕,而是排隊(duì)等著。
查看mutation隊(duì)列
那么器紧,怎么查看數(shù)據(jù)是否更新完成了呢耀销?
可以通過(guò)system.mutations表查看相關(guān)信息:
SELECT
database,
table,
command,
create_time,
is_done
FROM system.mutations
LIMIT 10
┌─database─┬─table─────────────────┬─command─────────────────────────────────────────────────────────────────────────────┬─────────create_time─┬─is_done─┐
│ app │ scene_model │ UPDATE status = '2' WHERE id = '208209306' │ 2020-03-30 15:38:58 │ 1 │
│ app │ scene_model │ UPDATE status = '2' WHERE id = '100000004' │ 2020-03-30 15:40:00 │ 1 │
│ app │ scene_model │ UPDATE status = '2' WHERE id = '100000004' │ 2020-03-30 15:41:09 │ 1 │
│ app │ user_model │ UPDATE name = 'zhuweiming' WHERE id = '0000000047fd31e40147fd3477cc0000' │ 2020-03-19 18:34:59 │ 1 │
│ app │ work_statistics_total │ UPDATE pv = 10000, uv = 10000 WHERE (id = '1000900') AND (product = 'tracker_view') │ 2020-03-31 14:45:59 │ 1 │
│ app │ work_statistics_total │ UPDATE pv = 10000, uv = 10000 WHERE (id = '1000901') AND (product = 'tracker_view') │ 2020-03-31 14:45:59 │ 1 │
│ app │ work_statistics_total │ UPDATE pv = 10000, uv = 10000 WHERE (id = '1000902') AND (product = 'tracker_view') │ 2020-03-31 14:45:59 │ 1 │
│ app │ work_statistics_total │ UPDATE pv = 10000, uv = 10000 WHERE (id = '1000903') AND (product = 'tracker_view') │ 2020-03-31 14:45:59 │ 1 │
│ app │ work_statistics_total │ UPDATE pv = 10000, uv = 10000 WHERE (id = '1000904') AND (product = 'tracker_view') │ 2020-03-31 14:45:59 │ 1 │
│ app │ work_statistics_total │ UPDATE pv = 10000, uv = 10000 WHERE (id = '1000905') AND (product = 'tracker_view') │ 2020-03-31 14:45:59 │ 1 │
└──────────┴───────────────────────┴─────────────────────────────────────────────────────────────────────────────────────┴─────────────────────┴─────────┘
- database: 庫(kù)名
- table: 表名
- command: 更新/刪除語(yǔ)句
- create_time: mutation任務(wù)創(chuàng)建時(shí)間,系統(tǒng)按這個(gè)時(shí)間順序處理數(shù)據(jù)變更
- is_done: 是否完成铲汪,1為完成熊尉,0為未完成
除了上述的,還有一些其他的字段掌腰,詳見(jiàn):官方文檔狰住。
通過(guò)以上信息,可以查看當(dāng)前有哪些mutation已經(jīng)完成齿梁,is_done為1即表示已經(jīng)完成催植。
Mutation具體過(guò)程
首先,使用where條件找到需要修改的分區(qū)勺择;
然后查邢,重建每個(gè)分區(qū),用新的分區(qū)替換舊的酵幕,分區(qū)一旦被替換,就不可回退缓苛;
對(duì)于每個(gè)分區(qū)芳撒,可以認(rèn)為是原子性的;但對(duì)于整個(gè)mutation未桥,如果涉及多個(gè)分區(qū)笔刹,則不是原子性的。
注意事項(xiàng)
- 更新功能不支持更新有關(guān)主鍵或分區(qū)鍵的列
- 更新操作沒(méi)有原子性冬耿,即在更新過(guò)程中select結(jié)果很可能是一部分變了舌菜,一部分沒(méi)變,從上邊的具體過(guò)程就可以知道
- 更新是按提交的順序執(zhí)行的
- 更新一旦提交亦镶,不能撤銷(xiāo)日月,即使重啟clickhouse服務(wù)袱瓮,也會(huì)繼續(xù)按照system.mutations的順序繼續(xù)執(zhí)行
- 已完成更新的條目不會(huì)立即刪除,保留條目的數(shù)量由finished_mutations_to_keep存儲(chǔ)引擎參數(shù)確定爱咬。 超過(guò)數(shù)據(jù)量時(shí)舊的條目會(huì)被刪除
- 更新可能會(huì)卡住尺借,比如
update intvalue='abc'
這種類(lèi)型錯(cuò)誤的更新語(yǔ)句執(zhí)行不過(guò)去,那么會(huì)一直卡在這里精拟,此時(shí)燎斩,可以使用KILL MUTATION
來(lái)取消,語(yǔ)法:
kill kutation where database='app' and table='test' // database蜂绎、table是system.mutations表中的字段
使用建議
按照官方的說(shuō)明栅表,update/delete 的使用場(chǎng)景是一次更新大量數(shù)據(jù),也就是where條件篩選的結(jié)果應(yīng)該是一大片數(shù)據(jù)师枣。
舉例:alter table test update status=1 where status=0 and day='2020-04-01'
怪瓶,一次更新一天的數(shù)據(jù)。
那么坛吁,能否一次只更新一條數(shù)據(jù)呢劳殖?例如:alter table test update pv=110 where id=100
當(dāng)然也可以,但頻繁的這種操作拨脉,可能會(huì)對(duì)服務(wù)造成壓力哆姻。這很容易理解,如上文提到玫膀,更新的單位是分區(qū)矛缨,如果只更新一條數(shù)據(jù),那么需要重建一個(gè)分區(qū)帖旨;如果更新100條數(shù)據(jù)箕昭,而這100條可能落在3個(gè)分區(qū)上,則需重建3個(gè)分區(qū)解阅;相對(duì)來(lái)說(shuō)一次更新一批數(shù)據(jù)的整體效率遠(yuǎn)高于一次更新一行落竹。
對(duì)于頻繁單條更新的這種場(chǎng)景,建議使用ReplacingMergeTree
引擎來(lái)變相解決货抄。具體如何使用述召,以后有時(shí)間再整理。