目錄
- 建表
- 折疊
- 資料
- 演算法
- 資料分享
- 參考文章
該引擎繼承于MergeTree,并在資料塊合并演算法中添加了折疊行的邏輯,CollapsingMergeTree會異步的洗掉(折疊)這些除了特定列Sign有1和-1的值以外,其余所有欄位的值都相等的成對的行,沒有成對的行會被保留,因此,該引擎可以顯著的降低存盤量并提高SELECT查詢效率,
簡單來說就是,clickhouse會自動的合并有效和無效的資料,減少資料存盤,并減少update所產生的性能消耗,具體的邏輯,下面介紹,
建表
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
...
) ENGINE = CollapsingMergeTree(sign)
[PARTITION BY expr]
[ORDER BY expr]
[SAMPLE BY expr]
[SETTINGS name=value, ...]
sign — 型別列的名稱:1是?狀態?行,也就是最后的有效行,-1是?取消?行,也就是無效行,列資料型別 — Int8,
創建CollapsingMergeTree表時,需要與創建 MergeTree 表時相同的子句,
折疊
資料
考慮你需要為某個物件保存不斷變化的資料的情景,似乎為一個物件保存一行記錄并在其發生任何變化時更新記錄是合乎邏輯的,但是更新操作對DBMS來說是昂貴且緩慢的,因為它需要重寫存盤中的資料,如果你需要快速的寫入資料,則更新操作是不可接受的,但是你可以按下面的描述順序地更新一個物件的變化,
在寫入行的時候使用特定的列Sign,如果Sign=1則表示這一行是物件的狀態,我們稱之為?狀態?行,如果Sign=-1則表示是對具有相同屬性的狀態行的取消,我們稱之為?取消?行,
例如,我們想要計算用戶在某個站點訪問的頁面頁面數以及他們在那里停留的時間,在某個時候,我們將用戶的活動狀態寫入下面這樣的行,
┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐
│ 4324182021466249494 │ 5 │ 146 │ 1 │
└─────────────────────┴───────────┴──────────┴──────┘
一段時間后,我們寫入下面的兩行來記錄用戶活動的變化,
┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐
│ 4324182021466249494 │ 5 │ 146 │ -1 │
│ 4324182021466249494 │ 6 │ 185 │ 1 │
└─────────────────────┴───────────┴──────────┴──────┘
第一行取消了這個物件(用戶)的狀態,它需要復制被取消的狀態行的所有除了Sign的屬性,
第二行包含了當前的狀態,因為我們只需要用戶活動的最后狀態,這些行可以在折疊物件的失效(老的)狀態的時候被洗掉,CollapsingMergeTree會在合并資料片段的時候做這件事,
┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐
│ 4324182021466249494 │ 5 │ 146 │ 1 │
│ 4324182021466249494 │ 5 │ 146 │ -1 │
└─────────────────────┴───────────┴──────────┴──────┘
這種方法的特殊屬性
- 寫入的程式應該記住物件的狀態從而可以取消它,?取消?字串應該是?狀態?字串的復制,除了相反的Sign,它增加了存盤的初始資料的大小,但使得寫入資料更快速,
- 由于寫入的負載,列中長的增長陣列會降低引擎的效率,資料越簡單,效率越高,
- SELECT的結果很大程度取決于物件變更歷史的一致性,在準備插入資料時要準確,在不一致的資料中會得到不可預料的結果,例如,像會話深度這種非負指標的負值,
演算法
當ClickHouse合并資料片段時,每組具有相同主鍵的連續行被減少到不超過兩行,一行Sign=1(?狀態?行),另一行Sign=-1(?取消?行),換句話說,資料項被折疊了,
對每個結果的資料部分ClickHouse保存的演算法:
- 如果?取消?和?狀態?行數量相同,并且最后一行?狀態?行,保留第一個?取消?和最后一個?狀態?行,
- 如果?狀態?行比?取消?行多一個或一個以上,保留最后一個?狀態?行,
- 如果?取消?行比?狀態?行多一個或一個以上,保留第一個?取消?行,
- 沒有行,在其他所有情況下,合并會繼續,但ClickHouse會把此情況視為邏輯錯誤并將其記錄在服務日志中,這個錯誤會在相同的資料被插入超過一次時出現,
因此,折疊不應該改變統計資料的結果,變化逐漸地被折疊,因此最終幾乎每個物件都只剩下了最后的狀態,
Sign是必須的因為合并演算法不保證所有有相同主鍵的行都會在同一個結果資料片段中,甚至是在同一臺物理服務器上,ClickHouse用多執行緒來處理SELECT請求,所以它不能預測結果中行的順序,如果要從CollapsingMergeTree表中獲取完全?折疊?后的資料,則需要聚合,
要完成折疊,請使用GROUP BY子句和用于處理符號的聚合函式撰寫請求,例如,要計算數量,使用sum(Sign)而不是 count(),要計算某物的總和,使用sum(Sign * x)而不是sum(x),并添加HAVING sum(Sign) > 0子句,
聚合體count,sum和avg可以用這種方式計算,如果一個物件至少有一個未被折疊的狀態,則可以計算uniq聚合,min和 max聚合無法計算,因為CollaspingMergeTree不會保存折疊狀態的值的歷史記錄,
如果你需要在不進行聚合的情況下獲取資料(例如,要檢查是否存在最新值與特定條件匹配的行),你可以在 FROM 從句中使用 FINAL 修飾符,這種方法顯然是更低效的,
# 示例:
┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐
│ 4324182021466249494 │ 5 │ 146 │ 1 │
│ 4324182021466249494 │ 5 │ 146 │ -1 │
│ 4324182021466249494 │ 6 │ 185 │ 1 │
└─────────────────────┴───────────┴──────────┴──────┘
# 建表:
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請求來創建兩個不同的資料片段,如果我們使用一個請求插入資料,ClickHouse只會創建一個資料片段且不會執行任何合并操作,
#獲取資料:
SELECT * FROM UAct
┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐
│ 4324182021466249494 │ 5 │ 146 │ -1 │
│ 4324182021466249494 │ 6 │ 185 │ 1 │
└─────────────────────┴───────────┴──────────┴──────┘
┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐
│ 4324182021466249494 │ 5 │ 146 │ 1 │
└─────────────────────┴───────────┴──────────┴──────┘
#我們看到了什么,哪里有折疊?
#通過兩個 INSERT 請求,我們創建了兩個資料片段,
#SELECT請求在兩個執行緒中被執行,我們得到了隨機順序的行,
#沒有發生折疊是因為還沒有合并資料片段,
#ClickHouse 在一個我們無法預料的未知時刻合并資料片段,
#因此我們需要聚合:
SELECT
UserID,
sum(PageViews * Sign) AS PageViews,
sum(Duration * Sign) AS Duration
FROM UAct
GROUP BY UserID
HAVING sum(Sign) > 0
┌──────────────UserID─┬─PageViews─┬─Duration─┐
│ 4324182021466249494 │ 6 │ 185 │
└─────────────────────┴───────────┴──────────┘
# 如果我們不需要聚合并想要強制進行折疊,我們可以在 FROM 從句中使用 FINAL 修飾語,
SELECT * FROM UAct FINAL
┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐
│ 4324182021466249494 │ 6 │ 185 │ 1 │
└─────────────────────┴───────────┴──────────┴──────┘
# 這種查詢資料的方法是非常低效的,不要在大表中使用它,
資料分享
ClickHouse經典中文檔案分享
參考文章
- ClickHouse(01)什么是ClickHouse,ClickHouse適用于什么場景
- ClickHouse(02)ClickHouse架構設計介紹概述與ClickHouse資料分片設計
- ClickHouse(03)ClickHouse怎么安裝和部署
- ClickHouse(04)如何搭建ClickHouse集群
- ClickHouse(05)ClickHouse資料型別詳解
- ClickHouse(06)ClickHouse建表陳述句DDL詳細決議
- ClickHouse(07)ClickHouse資料庫引擎決議
- ClickHouse(08)ClickHouse表引擎概況
- ClickHouse(09)ClickHouse合并樹MergeTree家族表引擎之MergeTree詳細決議
- ClickHouse(10)ClickHouse合并樹MergeTree家族表引擎之ReplacingMergeTree詳細決議
- ClickHouse(11)ClickHouse合并樹MergeTree家族表引擎之SummingMergeTree詳細決議
本文來自博客園,作者:張飛的豬,轉載請注明原文鏈接:https://www.cnblogs.com/the-pig-of-zf/p/17166258.html
公眾號:張飛的豬大資料分享,不定期分享大資料學習的總結和相關資料,歡迎關注,
個人網站"張飛的豬編程作業室"鏈接: https://zhangfeidezhu.com
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/545383.html
標籤:其他
上一篇:oracle 口令檔案引數檔案
