国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

ClickHouse如何處理實時更新

這篇具有很好參考價值的文章主要介紹了ClickHouse如何處理實時更新。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

本文通過示例介紹如何處理ClickHouse實時更新。OLAP數據庫并不歡迎數據變更操作,ClickHouse也不例外,和其他OLAP產品一樣,剛開始ClickHouse甚至不支持更新,更新能力是后來才加上的,但是按照ClickHouse方式增加的。當前ClickHouse更新是異步的,使得在交互應用中難以使用。有很多場景中用戶需要修改已存在的數據并期望立即看到,ClickHouse如何滿足這樣需求呢。

ClickHouse更新歷史

早在2016年,當時ClickHouse不支持數據修改,ClickHouse團隊發(fā)布文章“ClickHouse如何更新數據” ,僅使用特殊的插入結構用于模擬更新,數據最終有分區(qū)刪除。

在GDPR(General Data Protection Regulation)的壓力下,ClickHouse團隊在2018年發(fā)布了更新和刪除。該文章ClickHouse中的更新和刪除,仍然是Altinity博客中閱讀量最大的文章之一。這些異步、非原子更新使用通過ALTER TABLE UPDATE 語句實現的,并可能打亂大量數據,對于批量操作和少量更新且不急于看到最終結果場景是有用的。標準的SQL更新仍沒有,盡管它們每年都出現在產品路線中。如果我們確實需要實時更新,則必須使用其他方法實現。下面基于實際應用場景對比ClickHouse不同實現方式。

使用場景

假設系統(tǒng)產生各類報警信息,用戶和機器學習算法不斷地查詢數據庫獲取新的報警信息并確認,確認操作需要修改報警記錄,一旦確認則報警記錄不會再次出現在用戶視圖中,這看起來像是ClickHouse所不熟悉的OLTP操作。

因為不能使用更新,需要使用插入新記錄代替。一旦數據庫中有兩個記錄,我們需要有效方式獲得最新的記錄。下面嘗試三種方式實現。

ReplacingMergeTree

首先創(chuàng)建表存儲報警信息:

CREATE TABLE alerts(
  tenant_id     UInt32,
  alert_id      String,
  timestamp     DateTime Codec(Delta, LZ4),
  alert_data    String,
  acked         UInt8 DEFAULT 0,
  ack_time      DateTime DEFAULT toDateTime(0),
  ack_user      LowCardinality(String) DEFAULT ''
)
ENGINE = ReplacingMergeTree(ack_time)
PARTITION BY tuple()
ORDER BY (tenant_id, timestamp, alert_id);

為了簡化,所有報警信息打包放在alert_data列中,實際可能包括幾十個或幾百個列信息。另外alert_id在示例中是隨機字符串。

注意ReplacingMergeTree引擎,是基于order by 子句指定的字段判斷重復,如果兩條記錄重復,則最新記錄保留,最新記錄有ack_time字段決定。去重操作在后端合并操作中執(zhí)行,不會立刻發(fā)生,不會保證什么時間發(fā)生。所以需要關心一致性查詢結果。ClickHouse有特殊語法實現,后面就要提及。

在運行查詢之前,需要填充表一些數據,我們生成1000個租戶的10M報警數據:

INSERT INTO alerts(tenant_id, alert_id, timestamp, alert_data)
SELECT
  toUInt32(rand(1)%1000+1) AS tenant_id,
  randomPrintableASCII(64) as alert_id,
  toDateTime('2020-01-01 00:00:00') + rand(2)%(3600*24*30) as timestamp,
  randomPrintableASCII(1024) as alert_data
FROM numbers(10000000);

接下來,讓我們確認99%的警報,為’ ack_user ‘、’ ack_user ‘和’ ack_time '列提供新值。不是更新,而是插入新行。

INSERT INTO alerts (tenant_id, alert_id, timestamp, alert_data, acked, ack_user, ack_time)
SELECT tenant_id, alert_id, timestamp, alert_data,  1 as acked, 
       concat('user', toString(rand()%1000)) as ack_user,  now() as ack_time
FROM alerts WHERE cityHash64(alert_id) % 99 != 0;

如果現在查詢表,可以看到:

SELECT count() FROM alerts
┌──count()─┐
│ 19898060 │
└──────────┘
1 rows in set. Elapsed: 0.008 sec. 

顯然已確認和未確認的行都在表中,替代還沒有發(fā)生。為了看到最后數據,可以使用final關鍵字。

SELECT count() FROM alerts FINAL
┌──count()─┐
│ 10000000 │
└──────────┘
1 rows in set. Elapsed: 3.693 sec. Processed 19.90 million rows, 1.71 GB (5.39 million rows/s., 463.39 MB/s.)

數量是正確的,但看查詢時間,使用final 關鍵字ClickHouse必須掃描所有行,并在查詢時按排序鍵進行合并。雖然獲得正確結果,但開銷很大?,F在看僅過濾尚未確認的行是否性能更好。

SELECT count() FROM alerts FINAL WHERE NOT acked
┌─count()─┐
│  101940 │
└─────────┘
1 rows in set. Elapsed: 3.570 sec. Processed 19.07 million rows, 1.64 GB (5.34 million rows/s., 459.38 MB/s.) 

查詢時間和處理的數據量沒有明顯差異,盡管計數要小得多。過濾無助于加快查詢速度。隨著表大小的增長,成本可能會更大。它無法擴展。

注意:為了可讀性,所有的查詢和查詢時間都像在“clickhouse-client”中運行一樣。事實上,我們多次嘗試查詢,以確保結果一致,并與“clickhouse-benchmark”實用程序進行確認。

查詢全部表意義不大,那么在我們的示例中還能使用ReplacingMergeTree引擎嗎?下面選擇隨機某個租戶,即該租戶下所有為確認的報警信息,想象該用戶正在看展示屏幕。因為alert_data是隨機數,這里僅計算下校驗和,就是為了看下結果:

SELECT 
  count(), 
  sum(cityHash64(*)) AS data
FROM alerts FINAL
WHERE (tenant_id = 451) AND (NOT acked)
┌─count()─┬─────────────────data─┐
│      9018441617166277032220 │
└─────────┴──────────────────────┘

1 rows in set. Elapsed: 0.278 sec. Processed 106.50 thousand rows, 119.52 MB (383.45 thousand rows/s., 430.33 MB/s.)

相當快,278毫秒查詢所有未確認數據。為什么這次快?過濾條件不同,tenant_id是主鍵的一部分,所以ClickHouse能在final之前過濾數據,這時ReplacingMergeTree有效的。

下面嘗試查詢某用戶已確認的數據。列的基數是相同的——我們有1000個用戶,可以試試user451。

SELECT count() FROM alerts FINAL
WHERE (ack_user = 'user451') AND acked
┌─count()─┐
│    9725 │
└─────────┘

1 rows in set. Elapsed: 4.778 sec. Processed 19.04 million rows, 1.69 GB (3.98 million rows/s., 353.21 MB/s.)

這個查詢很慢,因為沒有使用索引,ClickHouse掃描了19.04M行記錄。我們不能增加ack_user作為索引,這樣會破壞ReplacingMergeTree 語義。我們嘗試采用prewhere:

SELECT count() FROM alerts FINAL
PREWHERE (ack_user = 'user451') AND acked

┌─count()─┐
│    9725 │
└─────────┘

1 rows in set. Elapsed: 0.639 sec. Processed 19.04 million rows, 942.40 MB (29.80 million rows/s., 1.48 GB/s.)

PREWHERE是ClickHouse以不同方式應用過濾器的特殊方式。通常ClickHouse足夠聰明,可以自動將條件移動到PREWHERE,所以用戶不應該在意。但這個示例需要我們顯示指定。

Aggregate Functions

ClickHouse提供了大量的聚集函數,最新版本超過100多個,結合12個聚集合并器,極大地滿足了用戶需求。我們的示例僅需要三個函數:‘argMax’, ‘max’ and ‘any’.

下面使用argMax聚集函數查詢相同的租戶:

SELECT count(), sum(cityHash64(*)) data FROM (
  SELECT tenant_id, alert_id, timestamp, 
         argMax(alert_data, ack_time) alert_data, 
         argMax(acked, ack_time) acked,
         max(ack_time) ack_time_,
         argMax(ack_user, ack_time) ack_user
  FROM alerts 
  GROUP BY tenant_id, alert_id, timestamp
) 
WHERE tenant_id=451 AND NOT acked;

┌─count()─┬─────────────────data─┐
│      9018441617166277032220 │
└─────────┴──────────────────────┘

1 rows in set. Elapsed: 0.059 sec. Processed 73.73 thousand rows, 82.74 MB (1.25 million rows/s., 1.40 GB/s.)

結果相同,但性能提升了4倍。這是ClickHouse聚集能力。缺點是查詢變得復雜,但我們可以簡化。我們注意到,當確認報警信息時,僅需要更新三列:

  • acked: 0 => 1
  • ack_tiem: 0 => now()
  • ack_user: ‘’ => ‘user1’

三個值都在增加,所以可以使用max代替argMax。既然不改變alert_data, 就不需要任何實際聚集函數,ClickHouse提供any函數實現該功能,它返回任何一個值,減少額外開銷。

SELECT count(), sum(cityHash64(*)) data FROM (
  SELECT tenant_id, alert_id, timestamp, 
    any(alert_data) alert_data, 
    max(acked) acked, 
    max(ack_time) ack_time,
    max(ack_user) ack_user
  FROM alerts
  GROUP BY tenant_id, alert_id, timestamp
) 
WHERE tenant_id=451 AND NOT acked;

┌─count()─┬─────────────────data─┐
│      9018441617166277032220 │
└─────────┴──────────────────────┘

1 rows in set. Elapsed: 0.055 sec. Processed 73.73 thousand rows, 82.74 MB (1.34 million rows/s., 1.50 GB/s.)

查詢變得簡單了,速度也快了一點!原因是使用’ any ‘函數,ClickHouse不需要計算’ alert_data ‘列上的’ max ’ !

AggregatingMergeTree

AggregatingMergeTree 是ClickHouse最強特性之一。結合物化視圖能夠實現實時數據聚合。既然前面示例需要使用聚集函數,直接適應AggregatingMergeTree 會更好嗎?實際提升不明顯。因為每行僅更新一次,僅有兩行需要聚合為一組。對于這種場景,AggregatingMergeTree 不是最佳選項。

但可以結合需求變點戲法。需求中報警信息首先插入非確認信息,然后變成確認信息,一旦用戶確認了,三個字段需要修改。如果其他列不重復存儲會節(jié)約空間、提升性能。

首先創(chuàng)建AggregatingMergeTree 表引擎,使用max聚合函數。代替使用max,可以any,但需要列為非空,any會選擇非空值。

DROP TABLE alerts_amt_max;
CREATE TABLE alerts_amt_max (
  tenant_id     UInt32,
  alert_id      String,
  timestamp     DateTime Codec(Delta, LZ4),
  alert_data    SimpleAggregateFunction(any, String),
  acked         SimpleAggregateFunction(max, UInt8),
  ack_time      SimpleAggregateFunction(max, DateTime),
  ack_user      SimpleAggregateFunction(max, LowCardinality(String))
)
Engine = AggregatingMergeTree()
ORDER BY (tenant_id, timestamp, alert_id);

既然原始數據是隨機的,我們就使用已存在的表數據進行填充。像之前一樣進行兩次插入,分別為非確認報警信息和確認信息。

INSERT INTO alerts_amt_max SELECT * FROM alerts WHERE NOT acked;
INSERT INTO alerts_amt_max 
SELECT tenant_id, alert_id, timestamp,
  '' as alert_data, 
  acked, ack_time, ack_user 
FROM alerts WHERE acked;

注意,對于alert_data字段插入空字符串,因為不需要存儲兩次。聚合函數會獲取非空值,其他列保持缺省值不變。一旦有了數據,現在檢查下數據大?。?/p>

SELECT 
    table, 
    sum(rows) AS r, 
    sum(data_compressed_bytes) AS c, 
    sum(data_uncompressed_bytes) AS uc, 
    uc / c AS ratio
FROM system.parts
WHERE active AND (database = 'last_state')
GROUP BY table

┌─table──────────┬────────r─┬───────────c─┬──────────uc─┬──────────────ratio─┐
│ alerts         │ 1903943920926009562210493077101.0058921003373666 │
│ alerts_amt_max │ 1903943910723636061109020481781.0166372782501314 │
└────────────────┴──────────┴─────────────┴─────────────┴────────────────────┘

我們幾乎沒有壓縮,多虧了隨機字符串。但是aggregate要小兩倍,因為我們不需要存儲兩次’ alerts_data '?,F在讓我們嘗試對聚合表進行查詢:

SELECT count(), sum(cityHash64(*)) data FROM (
   SELECT tenant_id, alert_id, timestamp, 
          max(alert_data) alert_data, 
          max(acked) acked, 
          max(ack_time) ack_time,
          max(ack_user) ack_user
     FROM alerts_amt_max
   GROUP BY tenant_id, alert_id, timestamp
) 
WHERE tenant_id=451 AND NOT acked;

┌─count()─┬─────────────────data─┐
│      9018441617166277032220 │
└─────────┴──────────────────────┘

1 rows in set. Elapsed: 0.036 sec. Processed 73.73 thousand rows, 40.75 MB (2.04 million rows/s., 1.13 GB/s.)

多虧了AggregatingMergeTree,我們處理的數據更少了(40MB比之前的82MB),而且現在效率更高了。

實現更新

ClickHouse將盡其所能在后臺合并數據,刪除重復行并執(zhí)行聚合。但有時需要強制合并數據,為了釋放磁盤空間。如使用OPTIMIZE FINAL 語句,但該語句是阻塞的、且昂貴的操作。因此不能頻繁執(zhí)行,讓我們看看它是否對查詢性能有任何影響。

OPTIMIZE TABLE alerts FINAL

Ok.
0 rows in set. Elapsed: 105.675 sec.

OPTIMIZE TABLE alerts_amt_max FINAL

Ok.
0 rows in set. Elapsed: 70.121 sec.

執(zhí)行后兩者數量相同:

┌─table──────────┬────────r─┬───────────c─┬──────────uc─┬────────────ratio─┐
│ alerts         │ 1000000010616223201108594903001.02291465565429 │
│ alerts_amt_max │ 1000000010616223201108594903001.02291465565429 │
└────────────────┴──────────┴─────────────┴─────────────┴──────────────────┘

不同方法之間的性能差異變得不那么顯著。以下是匯總表:

** After inserts** After OPTIMIZE FINAL
ReplacingMergeTree FINAL 0.278 0.037
argMax 0.059 0.034
any/max 0.055 0.029
AggregatingMergeTree 0.036 0.026

總結

ClickHouse提供豐富的工具集處理實時更新,如:ReplacingMergeTree, CollapsingMergeTree (本文未提及), AggregatingMergeTree 和aggregate 函數。所有這些方法都有三個共性:

  • 數據通過插入新版本進行修改,插入在ClickHouse中很快
  • 有多種有效方法實現類似OLTP中的更新語義
  • 實際修改不會立刻發(fā)生

具體選擇哪種方法依賴具體應用場景。ReplacingMergeTree對用戶來說是最直接、方便,但一般用于數據量為中小量級或數據僅通過主鍵查詢場景。使用聚集函數更靈活,性能也不錯,但需要寫相對復雜的查詢。AggregatingMergeTree可以節(jié)約空間,僅保留修改列。這些都是ClickHouse DB設計師的好工具,可以在需要的時候使用。

參考文檔:https://dzone.com/articles/handling-real-time-updates-in-clickhouse文章來源地址http://www.zghlxwxcb.cn/news/detail-554243.html

到了這里,關于ClickHouse如何處理實時更新的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • CTF常用工具_實時更新

    CTF常用工具_實時更新

    近期在做一些ctf題,其中會涉及到許多工具,起初我會使用百度網盤在每一篇博客放置對應的工具,但因網盤上傳有上限,所以現在我將練習中所用到所有的工具放置在這篇文章中。 需要下載的小伙伴可隨時拿取,分享有效期為永久分享。 常用工具及常用網站為實時分享!

    2024年02月04日
    瀏覽(20)
  • 【clickhouse】ClickHouse與MySQL之間實時同步數據(MySQL引擎),將MySQL數據實時同步到clickhouse

    【clickhouse】ClickHouse與MySQL之間實時同步數據(MySQL引擎),將MySQL數據實時同步到clickhouse

    參考1:MySQL(通過該配置實現了實時同步) 參考2:experimental MaterializedMySQL 參考3:[experimental] MaterializedMySQL(包含設置 allow_experimental_database_materialized_mysql) MySQL引擎用于將遠程的MySQL服務器中的表映射到ClickHouse中,并允許您對表進行INSERT和SELECT查詢,以方便您在ClickHouse與MySQL之間進行

    2024年01月16日
    瀏覽(16)
  • 實時更新天氣微信小程序開發(fā)

    實時更新天氣微信小程序開發(fā)

    1.新建一個天氣 weather項目 2.在app.json中創(chuàng)建一個路由頁面 ?當我們點擊保存的時候,微信小程序會自動的幫我們創(chuàng)建好頁面 3.在weather頁面上書寫我們的骨架 ?4.此時我們的頁面很怪,因為沒有給它添加樣式和值。此時我們給它一個樣式。(樣式寫在wxss中) 5.給它值,使用插值

    2024年02月01日
    瀏覽(28)
  • Java面試基礎|數據結構 -實時更新

    Java面試基礎|數據結構 -實時更新

    1.HashMap和ConcurrentHashMap介紹 核心是一個Node數組, 數據結構與hashMap相似 使用CAS操作來實現無鎖的更新,提高了并發(fā)性。當更新節(jié)點時,它會使用CAS來替換節(jié)點的值或鏈接,如果CAS失敗,表明有其他線程也在進行修改,當前線程可以重試或鎖定節(jié)點 對于復雜的結構修改操作

    2024年01月17日
    瀏覽(22)
  • vue父子組件傳值不能實時更新

    vue父子組件傳值不能實時更新

    最近做項目,遇到個大坑,這會爬出來了,寫個總結,避免下次掉坑。 vue父子組件傳值不能實時更新問題,父組件將值傳給了子組件,但子組件顯示的值還是原來的初始值,并沒有實時更新,為什么會出現這種問題呢? 出現這個問題,可能有以下兩個原因: 一、 父組件沒有

    2024年02月16日
    瀏覽(25)
  • cocos tilemap的setTileGIDAt方法不實時更新

    cocos tilemap的setTileGIDAt方法不實時更新

    需要取消勾選?Enable Culling。同時代碼添加:markForUpdateRenderData函數。 floor.setTileGIDAt(1024+27,newP.x,newP.y,0); ? ?//中心 floor.markForUpdateRenderData(); 具體問題參考官網說明: Cocos Creator 3.2 手冊 - 項目設置

    2024年02月07日
    瀏覽(21)
  • 小程序彈幕自動滾動實時更新數據功能

    小程序彈幕自動滾動實時更新數據功能

    需求 最近遇到的需求,寫一個彈幕功能 大致就是實現這樣的效果 彈幕輪播,上下兩排,一共30個彈幕,30個輪播完畢之后獲取新的彈幕數據 實現方法 ?目前我想到的實現方法是用css的動畫來實現這個功能 布局層級 給barrageBox盒子一個相對定位 給barrageList絕對定位 先將list盒子

    2024年01月20日
    瀏覽(24)
  • Rust采集天氣預報信息并實時更新數據

    Rust采集天氣預報信息并實時更新數據

    最近天氣溫度時高時低,雖說這是大自然的力量人無法抗拒,不能改變那么我們就做預防工作。今天我將用Rust寫一個爬蟲程序實現電腦桌面實時更新天氣情況,這個是一個底層邏輯,需要多方面配合,不僅要有完善的代碼還有爬蟲IP試試更新才能保證數據最完整最新。 這是一

    2024年01月19日
    瀏覽(22)
  • vue中組件動態(tài)傳值,實現數據實時更新

    在一些項目需求中需要父組件向子組件動態(tài)傳值,比如父組件動態(tài)通過axios獲取數據,然后傳給子組件,子組件根據拿到的數據進行展示。 props傳值的時候,只會首次傳遞綁定的值,不會變化 方式1 利用watch監(jiān)聽props變化 方式2 利用ref獲取子組件,調用子組件的方法將值傳遞過

    2024年02月16日
    瀏覽(29)
  • 數據大屏--->前端實時更新數據的幾種方式

    數據大屏--->前端實時更新數據的幾種方式

    優(yōu)點:最大的優(yōu)點就是實現簡單 缺點:(1)無用的請求多,客戶端不知道服務端什么時候數據更新,只能不停的向服務端發(fā)送請求, (2)數據實時性差:客戶端還是需要一段時間(3s)才能拿到最新的數據 優(yōu)點:解決了短輪詢每隔幾秒向服務端頻繁發(fā)送請求的問題; 缺點:(1)服務端資源大量消

    2024年04月17日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包