1. 程式人生 > 其它 >【ClickHouse 技術系列】- ClickHouse 中的巢狀資料結構

【ClickHouse 技術系列】- ClickHouse 中的巢狀資料結構

簡介:本文翻譯自 Altinity 針對 ClickHouse 的系列技術文章。面向聯機分析處理(OLAP)的開源分析引擎 ClickHouse,因其優良的查詢效能,PB級的資料規模,簡單的架構,被國內外公司廣泛採用。本系列技術文章,將詳細展開介紹 ClickHouse。

前言

本文翻譯自 Altinity 針對 ClickHouse 的系列技術文章。面向聯機分析處理(OLAP)的開源分析引擎 ClickHouse,因其優良的查詢效能,PB 級的資料規模,簡單的架構,被國內外公司廣泛採用。

阿里雲 EMR-OLAP 團隊,基於開源 ClickHouse 進行了系列優化,提供了開源 OLAP 分析引擎 ClickHouse 的雲上託管服務。EMR ClickHouse 完全相容開源版本的產品特性,同時提供叢集快速部署、叢集管理、擴容、縮容和監控告警等雲上產品功能,並且在開源的基礎上優化了 ClickHouse 的讀寫效能,提升了 ClickHouse 與 EMR 其他元件快速整合的能力。訪問

ClickHouse - E-MapReduce - 阿里雲 瞭解詳情。

譯者:何源(荊杭),阿里雲端計算平臺事業部高階產品專家

ClickHouse 中的巢狀資料結構

在這篇部落格文章中,我們將瞭解 ClickHouse for MySQL 中的巢狀資料結構,以及如何將其與 PMM 結合使用來檢視查詢。

巢狀結構在關係資料庫管理系統中並不常見。通常情況下,它只是平面表。有時,將非結構化資訊儲存在結構化資料庫中會很方便。

我們正在努力將 ClickHouse 調整為用於 Percona 監控和管理 (PMM) 的長期儲存,尤其是儲存有關查詢的詳細資訊。我們試圖解決的問題之一是,對導致特定查詢失敗的不同錯誤進行計數。

例如,對於日期為 2017-08-17 的查詢:

"SELECT foo FROM bar WHERE id=?"

被執行了 1000 次。其中 25 次失敗的錯誤程式碼為“1212”,8 次失敗的錯誤程式碼為“1250”。當然,在關係資料中進行儲存的傳統方法是建立一個表 "Date, QueryID, ErrorCode, ErrorCnt",然後對這個表執行 JOIN。遺憾的是,列式資料庫在多個 Join 的情況下表現不佳,通常建議使用非規範化表。

我們可以為每個可能的 ErrorCode 建立一個列,但這並不是最優解。可能有成千上萬的列,而且大多數時候它們都是空的。

在這種情況下,ClickHouse 提出了巢狀資料結構。對於我們的情況,這些可以定義為:

CREATE TABLE queries
(
    Period Date,
    QueryID UInt32,
    Fingerprint String,
    Errors Nested
    (
        ErrorCode String,
        ErrorCnt UInt32
    )
)Engine=MergeTree(Period,QueryID,8192);

這個解決方案有明顯的問題:我們如何在這個表中插入資料?我們如何提取它?

我們先從 INSERT 開始。插入可能如下所示:

INSERT INTO queries VALUES ('2017-08-17',5,'SELECT foo FROM bar WHERE id=?',['1220','1230','1212'],[5,6,2])

這意味著 2017-08-17 期間插入的查詢出現了 5 次錯誤 1220,6 次錯誤 1230,2 次錯誤 1212。

那麼在不同的日期,它可能會產生不同的錯誤:

INSERT INTO queries VALUES ('2017-08-18',5,'SELECT foo FROM bar WHERE id=?',['1220','1240','1258'],[3,2,1])

讓我們看一下 SELECT 資料的方法。非常基礎的 SELECT:

SELECT *
FROM queries
|_____Period_|_QueryID_|_Fingerprint_|_Errors.ErrorCode_______|_Errors.ErrorCnt_|
| 2017-08-17 |       5 | SELECT foo  | ['1220','1230','1212'] | [5,6,2]         |
| 2017-08-18 |       5 | SELECT foo  | ['1220','1240','1260'] | [3,16,12]       |
|____________|_________|_____________|________________________|_________________|

如果我們想使用更熟悉的表格輸出,則可以使用 ARRAY JOIN 擴充套件:

SELECT *
FROM queries
ARRAY JOIN Errors
┌─────Period─┬─QueryID─┬─Fingerprint─┬─Errors.ErrorCode─┬─Errors.ErrorCnt─┐
│ 2017-08-17 │       5 │ SELECT foo  │ 1220             │            5    │
│ 2017-08-17 │       5 │ SELECT foo  │ 1230             │            6    │
│ 2017-08-17 │       5 │ SELECT foo  │ 1212             │            2    │
│ 2017-08-18 │       5 │ SELECT foo  │ 1220             │            3    │
│ 2017-08-18 │       5 │ SELECT foo  │ 1240             │           16    │
│ 2017-08-18 │       5 │ SELECT foo  │ 1260             │           12    │
└────────────┴─────────┴─────────────┴──────────────────┴─────────────────┘

但是,通常我們希望看到多個期間的聚合,這可以通過傳統的聚合函式來完成:

SELECT 
    QueryID,
    Errors.ErrorCode,
    SUM(Errors.ErrorCnt)
FROM queries
ARRAY JOIN Errors
GROUP BY 
    QueryID,
    Errors.ErrorCode
┌─QueryID─┬─Errors.ErrorCode─┬─SUM(Errors.ErrorCnt)─┐
│       5 │ 1212             │                 2    │
│       5 │ 1230             │                 6    │
│       5 │ 1260             │                12    │
│       5 │ 1240             │                16    │
│       5 │ 1220             │                 8    │
└─────────┴──────────────────┴──────────────────────┘

如果我們別出心裁,每個 QueryID 只返回一行,我們也可以這麼做:

SELECT 
    QueryID, 
    groupArray((ecode, cnt))
FROM 
(
    SELECT 
        QueryID, 
        ecode, 
        sum(ecnt) AS cnt
    FROM queries 
    ARRAY JOIN 
        Errors.ErrorCode AS ecode, 
        Errors.ErrorCnt AS ecnt
    GROUP BY 
        QueryID, 
        ecode
) 
GROUP BY QueryID
┌─QueryID─┬─groupArray(tuple(ecode, cnt))──────────────────────────────┐
│       5 │ [('1230',6),('1212',2),('1260',12),('1220',8),('1240',16)] │
└─────────┴────────────────────────────────────────────────────────────┘

結論

ClickHouse 提供了靈活的方式來儲存資料,儘管它是一個列式資料庫,但可以實現較低的結構化程度,並提供各種函式來提取和聚合資料。

後續

您已經瞭解了在 ClickHouse 中處理實時更新相關內容,本系列還包括其他內容:

原文連結
本文為阿里雲原創內容,未經允許不得轉載。