likes
comments
collection
share

「Clickhouse Array 的力量」1-3

作者站长头像
站长
· 阅读数 43

数组与table JOIN

直接使用数组函数来定位和处理标签值可能会很麻烦,特别是在跨数组的几列工作时。 幸运的是,ClickHouse有一个非常方便的 **ARRAY JOIN**,可以很容易地将数组值 "解卷" 到一个名称值对表中。 下面是一个使用 **ARRAY JOIN** 的例子:

SELECT date, vm_id, vm_type, name, value
FROM vm_data
ARRAY JOIN tags_name AS name, tags_value AS value
ORDER BY date, vm_id, name

ARRAY JOIN的工作方式如下:

左侧表 vm_data 的列(date, vm_id, vm_type)与 ARRAY JOIN(tags_name, tags_value)后列出的数组中的值 "连接"。 ClickHouse为每个列出的数组创建一个列,并以相同的顺序从每个数组中填充值。 结果看起来像下面这样。

┌───────date─┬─vm_id─┬─vm_type─────┬─name──┬─value───────┐
 2020-09-03   6220  m5.large     group  rtb         
 2020-09-03   6220  m5.large     name   sfg-prod-01 
 2020-09-03   6221  m5ad.xlarge  group  marketing   
 2020-09-03   6221  m5ad.xlarge  name   mt-prod-65  
 2020-09-03   6221  m5ad.xlarge  owner  casey       
└────────────┴───────┴─────────────┴───────┴─────────────┘

ClickHouse的文档中有一篇关于 ARRAY JOIN的文章,说明了它的灵活性。

这里有一个例子:下面的查询添加了一个序列号,并使用方便的 **arrayEnumerate()** 按照数组序列顺序对行进行排序,该函数以升序返回数组索引值。

SELECT date, vm_id, vm_type, name, value, seq
FROM vm_data
ARRAY JOIN
  tags_name AS name,
  tags_value AS value,
  arrayEnumerate(tags_name) AS seq
ORDER BY date, vm_id, seq

/* sql answer*/
┌───────date─┬─vm_id─┬─vm_type─────┬─name──┬─value───────┬─seq─┐
2020-09-03 │  6220 │ m5.large    │ name  │ sfg-prod-01 │   1
2020-09-03 │  6220 │ m5.large    │ group │ rtb         │   2
2020-09-03 │  6221 │ m5ad.xlarge │ name  │ mt-prod-65  │   1
2020-09-03 │  6221 │ m5ad.xlarge │ group │ marketing   │   2
2020-09-03 │  6221 │ m5ad.xlarge │ owner │ casey       │   3
└────────────┴───────┴─────────────┴───────┴─────────────┴─────┘

ARRAY JOIN 对于呈现输出很有帮助,因为包含数组的查询结果对人类来说很难阅读,而且可能需要在客户端应用程序中进行专门的反序列化逻辑。它对降低查询的复杂性也很有帮助。

使用ARRAY JOIN,我们可以最小化甚至消除数组函数表达式。下面的例子是对前面的例子的重写,以寻找 "group rtb" 使用的虚拟机类型:

SELECT distinct vm_type FROM (
  SELECT date, vm_id, vm_type, name, value
  FROM vm_data
  ARRAY JOIN tags_name AS name, tags_value AS value
  WHERE name = 'group' AND value = 'rtb'
)

如果不提及 arrayJoin(),就无法结束我们对使用数组的数据建模的介绍。这个函数可以被添加到SELECT 列表中,以产生未滚动的结果,如下例所示:

SELECT 1, 2, arrayJoin(['a', 'b']) AS a1

/* sql answer*/
┌─1─┬─2─┬─a1─┐
12 │ a  │
12 │ b  │
└───┴───┴────┘

这完全等同于以下带有ARRAY JOIN的查询:

SELECT 1, 2 FROM system.one ARRAY JOIN ['a', 'b'] AS a1

然而,有一个关键的区别。

正如我们在上面看到的,ARRAY JOIN允许多个数组,并在所有数组上并行展开数值。 arrayJoin() 行为则不同。如果有多个 arrayJoin() 调用,它们会产生如下的结果:

SELECT  1,  2, 
  arrayJoin(['a', 'b']) AS a1, arrayJoin(['i', 'ii']) AS a2

/* sql answer*/
┌─1─┬─2─┬─a1─┬─a2─┐
12 │ a  │ i  │
12 │ a  │ ii │
12 │ b  │ i  │
12 │ b  │ ii │
└───┴───┴────┴────┘

正如你所看到的,结果是数组值的笛卡尔乘积,这可能不是你想要的结果。在本文的其余部分,我们将重点讨论ARRAY JOIN,因为它允许我们处理具有相关值的数组。这种行为对于数组的更多高级应用是至关重要的。

结论

你刚才读的文章介绍了数组在ClickHouse中的基本用法。 我们展示了如何使用成对的数组来表示变量数据,如何使用数组函数来提取数据,以及如何使用 ARRAY JOINarrayJoin() 来连接数组与表的行。

我们所涉及的数组功能已经超越了许多SQL数据库的能力。 对于ClickHouse来说,这仅仅是一个开始。在下一篇文章中,我们将展示数组和SQL GROUP BY是如何紧密相连的。阵列和聚合之间的整合使用户能够识别事件的序列,以及建立漏斗,从而跟踪营销、销售和其他领域的预期目标的进展。这是一个重要的分析工具,可用于广泛的有趣的应用。

转载自:https://juejin.cn/post/7025158392926699550
评论
请登录