11_CollapsingMergeTree,(State行和Cancel行匹配示例),聚合查询,Cancel状态行取反的聚合查询
10.CollapsingMergeTree
10.1.CollapsingMergeTree
10.2.案例(State行和Cancel行匹配示例)
10.3.示例2:聚合查詢
10.4.示例3:Cancel狀態(tài)行取反的聚合查詢
10.CollapsingMergeTree
10.1.CollapsingMergeTree
1、在排序鍵(ORDER BY)的所有字段都相同的條件下,如果特定的字段具有1和-1的值,CollapsingMergeTree將異步刪除(折疊)成對(duì)的行。沒(méi)有配對(duì)的行將保留。
2、能顯著降低存儲(chǔ)空間并提升SELECT查詢的效率。
3、變相的實(shí)現(xiàn)了數(shù)據(jù)的更新和刪除邏輯。
指定表引擎:
CollapsingMergeTree(sign)
參數(shù):sign,標(biāo)識(shí)行類型的列名稱,1是狀態(tài)行,-1是取消行。列的數(shù)據(jù)類型是Int8。
使用特定的列Sign,如果Sign=1,則表示該行是對(duì)象的狀態(tài),稱之為"狀態(tài)"行。如果Sign=-1,則表示取消具有屬性的對(duì)象的狀態(tài),稱之為"取消"行。
例如,計(jì)算用戶在某個(gè)站點(diǎn)訪問(wèn)的頁(yè)面數(shù)以及停留的時(shí)長(zhǎng)。在某個(gè)時(shí)刻,將用戶的活動(dòng)狀態(tài)寫入下面的行:
一段時(shí)間后,將用戶活動(dòng)的變化寫入以下兩行:
第一行取消對(duì)象(用戶)的先前狀態(tài),它應(yīng)該復(fù)制被取消狀態(tài)行的排序鍵字段,字段sign設(shè)置為-1標(biāo) 識(shí)取消狀態(tài)。
第二行包含當(dāng)前狀態(tài)
取消狀態(tài)的行包含:排序鍵字段的拷貝和相反的Sign值。 取消狀態(tài)的行增加了存儲(chǔ)的大小,但是卻可以 快速寫入數(shù)據(jù)。
合并算法
當(dāng)ClickHouse合并數(shù)據(jù)片段時(shí),具有相同排序鍵的每一組連續(xù)行被縮減為不超過(guò)兩行,一行的Sign=1, 另一行的Sign=-1。換句話說(shuō),條目將折疊。
Note:當(dāng)”state”行比”cancel”行數(shù)目至少多2個(gè),或者”cancel”行比”state”行多至少2個(gè)時(shí),合并將繼續(xù),但是ClickHouse將此情況視為邏輯錯(cuò)誤并將其在server的日志記錄下來(lái)。如果同一份數(shù)據(jù)被插入了多次,則會(huì)發(fā)生此錯(cuò)誤。
聚合統(tǒng)計(jì)
合并算法不能保證所有具有相同排序鍵的行都位于相同的結(jié)果數(shù)據(jù)片段中,甚至位于同一個(gè)物理服務(wù)器上。 ClickHouse使用多線程處理SELECT查詢,并且無(wú)法預(yù)測(cè)結(jié)果中的行順序。如果需要從CollapsingMergeTree表中完全”折疊”數(shù)據(jù),則需要結(jié)合Sign字段使用聚合。
例如:計(jì)算使用,使用sum(Sign)而不是count()。計(jì)算sum,使用sum(Sign * x)而不是sum(x),以此類推。
并且需要添加HAVING sum(Sign) > 0.
聚合的count、sum和avg可以通過(guò)這種方式計(jì)算,如果一個(gè)對(duì)象的至少一個(gè)狀態(tài)未折疊,則可以計(jì)算聚合 uniq。無(wú)法計(jì)算聚合的最小值和最大值,因?yàn)镃ollapsingMergeTree不會(huì)保存折疊狀態(tài)的歷史記錄。
如果要提取數(shù)據(jù)但不想使用聚合,則可以對(duì)FROM子句使用FINAL修飾符,這種方法效率明顯不高。
10.2.案例(State行和Cancel行匹配示例):
示例:State行和Cancel行匹配示例
驗(yàn)證:如果"state"行與"cancel"行的數(shù)目匹配,且最后一行是"state"行,則保留第一個(gè)"cancel"行和最后一個(gè)"state"行。
建表語(yǔ)句:
CREATE TABLE UAct (UserID UInt64,PageViews UInt8,Duration UInt8,Sign Int8 ) ENGINE = CollapsingMergeTree(Sign) ORDER BY UserID;首先清空表:
truncate table UAct;執(zhí)行如下的數(shù)據(jù)插入語(yǔ)法:
INSERT INTO UAct VALUES (4324182021466249494, 1, 11, -1),(4324182021466249494, 2, 12, -1); INSERT INTO UAct VALUES (4324182021466249494, 3, 13, 1); INSERT INTO UAct VALUES (4324182021466249494, 4, 14, 1);查看數(shù)據(jù):
xxxx2 :) select * from UAct;SELECT * FROM UAct┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐ │ 4324182021466249494 │ 4 │ 14 │ 1 │ └─────────────────────┴───────────┴──────────┴──────┘ ┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐ │ 4324182021466249494 │ 1 │ 11 │ -1 │ │ 4324182021466249494 │ 2 │ 12 │ -1 │ └─────────────────────┴───────────┴──────────┴──────┘ ┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐ │ 4324182021466249494 │ 3 │ 13 │ 1 │ └─────────────────────┴───────────┴──────────┴──────┘4 rows in set. Elapsed: 0.010 sec. xxxx2 :)執(zhí)行計(jì)劃外的片段合并操作:
xxxx2 :) optimize table UAct;OPTIMIZE TABLE UActOk.0 rows in set. Elapsed: 0.004 sec. xxxx2 :) select * from UAct;SELECT * FROM UAct┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐ │ 4324182021466249494 │ 1 │ 11 │ -1 │ │ 4324182021466249494 │ 4 │ 14 │ 1 │ └─────────────────────┴───────────┴──────────┴──────┘2 rows in set. Elapsed: 0.008 sec. xxxx2 :)從示例中可以觀察到,最終的數(shù)據(jù)片段保留了第一個(gè)"cancel"行和最后一個(gè)"state"行。
10.3.示例2:聚合查詢
示例數(shù)據(jù):
┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐ │ 4324182021466249494 │ 5 │ 146 │ 1 │ │ 4324182021466249494 │ 5 │ 146 │ -1 │ │ 4324182021466249494 │ 6 │ 185 │ 1 │ └─────────────────────┴───────────┴──────────┴──────┘建表:
DROP TABLE UAct; CREATE TABLE UAct (UserID UInt64,PageViews UInt8,Duration UInt8,Sign Int8 ) ENGINE = CollapsingMergeTree(Sign) ORDER BY UserID;插入數(shù)據(jù):
INSERT INTO UAct VALUES (4324182021466249494, 5, 146, 1);
INSERT INTO UAct VALUES (4324182021466249494, 5, 146, -1),(4324182021466249494, 6, 185, 1);
上面執(zhí)行了兩個(gè)INSERT語(yǔ)句,創(chuàng)建了兩個(gè)不同的數(shù)據(jù)片段。如果使用一個(gè)INSERT語(yǔ)句,ClickHouse將創(chuàng)建一個(gè)數(shù)據(jù)片段,并且將永遠(yuǎn)不會(huì)執(zhí)行任何合并。
查詢數(shù)據(jù):
通過(guò)兩個(gè)INSERT語(yǔ)句,創(chuàng)建了兩個(gè)數(shù)據(jù)片段。SELECT查詢是在兩個(gè)線程中執(zhí)行的,我們得到了隨機(jī)順序的行。由于尚未合并數(shù)據(jù)片段,折疊還未發(fā)生。
我們無(wú)法預(yù)測(cè)ClickHouse在何時(shí)執(zhí)行數(shù)據(jù)片段的合并。因此,我們需要使用聚合:
如果不使用聚合,可以對(duì)FROM子句使用FINAL修飾符進(jìn)行強(qiáng)制合并:
select * from UAct FINAL;效果如下:
xxxx2 :) select * from UAct FINAL;SELECT * FROM UAct FINAL┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐ │ 4324182021466249494 │ 6 │ 185 │ 1 │ └─────────────────────┴───────────┴──────────┴──────┘1 rows in set. Elapsed: 0.010 sec. xxxx2 :)10.4.示例3:Cancel狀態(tài)行取反的聚合查詢
示例數(shù)據(jù):
┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐ │ 4324182021466249494 │ 5 │ 146 │ 1 │ │ 4324182021466249494 │ -5 │ -146 │ -1 │ │ 4324182021466249494 │ 6 │ 185 │ 1 │ └─────────────────────┴───────────┴──────────┴──────┘這個(gè)方法的核心思想是僅考慮關(guān)鍵字段,在"cancel"行中,可以指定負(fù)數(shù),這些負(fù)數(shù)的值等于行的前一個(gè)版本的關(guān)鍵字段值的取反,這樣在求和時(shí)就可以不使用Sign列。對(duì)于這種方法,必須更改PageViews和Duration字段的數(shù)據(jù)類型,從UIn8改成Int16。
CREATE TABLE UAct (UserID UInt64,PageViews Int16,Duration Int16,Sign Int8 ) ENGINE = CollapsingMergeTree(Sign) ORDER BY UserID;插入數(shù)據(jù),并測(cè)試:
insert into UAct values(4324182021466249494, 5, 146, 1); insert into UAct values(4324182021466249494, -5, -146, -1); insert into UAct values(4324182021466249494, 6, 185, 1);總結(jié)
以上是生活随笔為你收集整理的11_CollapsingMergeTree,(State行和Cancel行匹配示例),聚合查询,Cancel状态行取反的聚合查询的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。