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