「Clickhouse Array 的力量」1-3
数组与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─┐
│ 1 │ 2 │ a │
│ 1 │ 2 │ 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─┐
│ 1 │ 2 │ a │ i │
│ 1 │ 2 │ a │ ii │
│ 1 │ 2 │ b │ i │
│ 1 │ 2 │ b │ ii │
└───┴───┴────┴────┘
正如你所看到的,结果是数组值的笛卡尔乘积,这可能不是你想要的结果。在本文的其余部分,我们将重点讨论ARRAY JOIN,因为它允许我们处理具有相关值的数组。这种行为对于数组的更多高级应用是至关重要的。
结论
你刚才读的文章介绍了数组在ClickHouse中的基本用法。 我们展示了如何使用成对的数组来表示变量数据,如何使用数组函数来提取数据,以及如何使用 ARRAY JOIN
和 arrayJoin()
来连接数组与表的行。
我们所涉及的数组功能已经超越了许多SQL数据库的能力。 对于ClickHouse来说,这仅仅是一个开始。在下一篇文章中,我们将展示数组和SQL GROUP BY是如何紧密相连的。阵列和聚合之间的整合使用户能够识别事件的序列,以及建立漏斗,从而跟踪营销、销售和其他领域的预期目标的进展。这是一个重要的分析工具,可用于广泛的有趣的应用。
转载自:https://juejin.cn/post/7025158392926699550