简介:本文翻译自 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 中处理实时更新相关内容,本系列还包括其他内容:

原文链接

本文为阿里云原创内容,未经允许不得转载。

【ClickHouse 技术系列】- ClickHouse 中的嵌套数据结构的更多相关文章

  1. MongoDB 大数据技术之mongodb中在嵌套子文档的文档上面建立索引

    一.给collection objectid赋自定义的值 MongoDB Enterprise > db.testid.insert({_id:{imsi:"4567890123&qu ...

  2. ClickHouse学习系列之一【安装说明】

    背景 最近花了些时间看了下ClickHouse文档,发现它在OLAP方面表现很优异,而且相对也比较轻量和简单,所以准备入门了解下该数据库系统.按照习惯第一步先安装,本文对其用户权限管理方面进行梳理说明 ...

  3. ClickHouse学习系列之三【配置文件说明】

    背景 最近花了些时间看了下ClickHouse文档,发现它在OLAP方面表现很优异,而且相对也比较轻量和简单,所以准备入门了解下该数据库系统.在介绍了安装和用户权限管理之后,本文对其配置文件做下相关的 ...

  4. ClickHouse学习系列之五【系统库system说明】

    背景 之前介绍过ClickHouse相关的系列文章,现在ClickHouse已经能正常使用起来了,包括副本和分片.因为ClickHouse已经可以提供服务了,现在需要关心的就是服务期间该数据库的各项性 ...

  5. C++的标准模板库STL中实现的数据结构之顺序表vector的分析与使用

    摘要 本文主要借助对C++的标准模板库STL中实现的数据结构的学习和使用来加深对数据结构的理解.即联系数据结构的理论分析和详细的应用实现(STL),本文是系列总结的第一篇,主要针对线性表中的顺序表(动 ...

  6. openresty开发系列16--lua中的控制结构if-else/repeat/for/while

    openresty开发系列16--lua中的控制结构if-else/repeat/for/while 一)条件 - 控制结构 if-else if-else 是我们熟知的一种控制结构.Lua 跟其他语 ...

  7. react实战系列 —— React 中的表单和路由的原理

    其他章节请看: react实战 系列 React 中的表单和路由的原理 React 中的表单是否简单好用,受控组件和非受控是指什么? React 中的路由原理是什么,如何更好的理解 React 应用的 ...

  8. 【转】Entity Framework技术系列之7:LINQ to Entities

    前言 LINQ(Language Integrated Query,语言集成查询)是一组用于C#和VB.NET语言的扩展,它允许编写C#或者VB.NET代码,以与查询数据库相同的方式操作内存数据. L ...

  9. Azure Messaging-ServiceBus Messaging消息队列技术系列3-消息顺序保证

    上一篇:Window Azure ServiceBus Messaging消息队列技术系列2-编程SDK入门  http://www.cnblogs.com/tianqing/p/5944573.ht ...

  10. Azure Messaging-ServiceBus Messaging消息队列技术系列4-复杂对象消息是否需要支持序列化和消息持久化

    在上一篇中,我们介绍了消息的顺序收发保证: Azure Messaging-ServiceBus Messaging消息队列技术系列3-消息顺序保证 在本文中我们主要介绍下复杂对象消息是否需要支持序列 ...

随机推荐

  1. 【Unity干货教程】如何实现Unity和Android原生互相调用?

    Unity是一个跨平台开发工具,发布到移动平台也是大部分Unity开发者的必备技能.而由于Unity跨平台的特性,总会遇到在移动平台的技术细节支持不够,或者需要在调用其他原生插件的情况.这里我们说一下 ...

  2. flutter版本的玩Android客户端

    flutter学习案例 目录介绍 00.项目下载与查看 01.项目介绍 02.项目优势 03.部分功能介绍 04.部分截图展示 05.版本更新 06.flutter系列博客 07.感谢 08.如何辨别 ...

  3. PDF的分割与合并

    1.进行PDF切割 python代码如下: # 20220521 # 1.选择要分割的文件 # 2.选择要保存的位置,分割为多个文件时,可自动用页码命名 # 3.输入要分割的页码,可以是一个范围1-2 ...

  4. KingbaseES 名词解释之timeline

    timeline定义 每当归档文件恢复完成后,创建一个新的时间线用来区别新生成的WAL记录.WAL文件名由时间线和日志序号组成 引入timeline的意义 为了理解引入时间线的背景,我们来分析一下,如 ...

  5. exist和left join 性能对比

    今天遇到一个性能问题,再调优过程中发现耗时最久的计划是exist 部分涉及的三个表. 然后计划用left join 来替换exist,然后查询了很多资料,大部分都说exist和left join 性能 ...

  6. 内核模块的makefile规则详解

    内核中的Makefile 这里主要对内核源码各子集目录中的Kbulid(内核的编译系统)Makfile进行简单介绍 这部分式内核驱动或设备驱动开发这最长接触到的 Makefile 的语法包括几个方面 ...

  7. 【已解决】Android----java.lang.NullPointerException:---java.lang.NullPointerException:

    2021-03-06 13:26:12.274 8544-8544/com.example.helloworld E/AndroidRuntime: FATAL EXCEPTION: main Pro ...

  8. spring中的bean对象的有关了解

    @Configuration public class AppConfig { @Bean public MyBean getMyBean() { MyBean myBean = new MyBean ...

  9. Advanced .Net Debugging 6:程序集加载器

    一.简介 这是我的<Advanced .Net Debugging>这个系列的第六篇文章.这篇文章的内容是原书的第二部分的[调试实战]的第四章.这章主要讲的是程序集加载器,比如:CLR 加 ...

  10. #二分图,并查集#洛谷 6185 [NOI Online #1 提高组] 序列

    题目 分析 考虑2操作可以在保证总和不变的情况下任意修改, 如果将2操作所在的连通块用并查集缩点,那么再考虑1操作, 按照1操作建边,如果存在奇环,那么只要这个环的点权和为偶数一定能使 \(a,b\) ...