Elasticsearch:ES|QL Joins 来了!是的,Joins!- 8.18

作者:来自 Elastic Tyler Perkins

Elasticsearch 8.18 包含了 ES|QL 的 LOOKUP JOIN 命令,这是我们第一个 SQL 风格的 JOIN。

Elasticsearch 8.18 包含了我们第一个 SQL 风格的 JOIN:ES|QL 的 LOOKUP JOIN 命令,目前已在 Tech Preview 中提供,支持通过可轻松更新的 lookup 数据集进行数据关联与增强。需要把主机和资产信息添加到你的事件中?没问题。想检查哪些 IP 地址或 URL 出现在威胁情报列表中?当然可以!更新 lookup 数据集后立即使用?没问题!

Lookup Join 是一种 SQL 风格的 LEFT OUTER JOIN,右侧依赖一种称为 lookup 的新索引模式。lookup 索引可以是资产、已知恶意 IP 等威胁情报数据、订单信息、员工或客户信息 —— 可能性无限。

过去,Elasticsearch 一直缺乏 join 能力,尽管期间曾尝试过一些方向,比如 nested、_parent 和 join 字段类型,以及 enrich。我们通常建议通过将参考数据与事件数据放在同一个索引中,或者在客户端进行 join 来实现数据去规范化。这些方案在面对大规模数据时限制了可扩展性,在数据和用例高度多样化的场景下也存在局限。Elasticsearch 现在终于可以支持 joins 了。而这正是 ES|QL 的实现:它不仅是一种语言,还构建在一个全新的计算引擎之上。这个 ES|QL 引擎让执行像 join 这样高级的功能成为可能。

为了实现 Lookup Joins,我们创建了一种新的索引模式:lookup。lookup 索引基本上类似于常规索引(默认模式是 mode:standard),也就是说它是可直接更新的。主要的区别在于,lookup 索引只有一个分片。因此,它限制为最多 20 亿个文档,这是 Lucene 对单个分片的限制。这对于很多 lookup join 的用例来说,已经足够容纳右侧的数据了。这个限制帮助我们避免了完全分布式 join 所带来的一些问题,通过减少 join 右侧的源基数来提升性能。它也告诉我们哪些数据集被你用作 lookup 引用,这样我们可以在未来为这些数据集进行优化。

除了 lookup 索引模式外,进行 join 并不对源数据有限制,也无需进行任何数据预处理。这意味着添加 lookup 数据集非常简单,而且也很容易保持其最新状态。

部分能力其实早已通过 ES|QL 中的 ENRICH 命令实现。ENRICH 针对 ingest pipeline 中的查找操作进行了优化,适用于不常变化的小型数据集,虽然方便,但并不理想。而 Lookup Join 更容易设置和管理,优于 enrich 的几个方面包括:

  • 无需创建 enrich 策略

  • 无需执行策略

  • lookup 索引是可写的

  • 更少的数据副本

  • 更好的多匹配处理:enrich 会在多匹配时创建多值字段,而 lookup join 会创建多行记录。这使得进一步的分析如分组和聚合(例如每个用户传输的字节数或订单总额)更简单

  • 支持动态指定匹配字段

以下是一些可能使用 LOOKUP JOIN 的场景:

  • 将安全事件与威胁情报 join,以增强事件信息

  • 将当前主机列表与最新的威胁情报或内部元数据进行匹配

  • 将 IOT 数据与静态或动态元数据(如制造商、体积单位)进行关联

  • 将安全事件与主机信息 join,获取更多上下文以便筛选

  • 添加资产关键性等信息(例如该用户是高管)

  • 将 CrowdStrike AID 添加到包含主机名的数据中

  • 检查某些 IP 地址是否出现在威胁情报 feed 中

  • 为事件添加员工信息
    ……

可能性无穷无尽。

使用示例

让我们通过一些实际例子来看看这个功能到底有多简单又强大。

作为一名 SRE,你可能需要:

  • 根据 IP 地址或主机名为日志添加 environment 信息

  • 将员工信息 join 到日志中

  • 找出是哪一个团队拥有某台服务器

在 LOOKUP JOIN 出现之前,你得:

  • 把参考数据(比如 environments)放到一个索引里

  • 基于这个索引定义一个 enrich 策略,指定策略类型、匹配字段和 enrich 字段

  • 执行 enrich 策略一次,以构建 enrich 索引

  • 对每一个参考数据集(例如 employees、teams)都要重复上述步骤

  • 每当数据发生变化时就要重新执行 enrich 策略

而现在只需使用 LOOKUP JOIN,把参考数据放进一个 LOOKUP 索引,就可以直接用了!

想象一下,你收到一个告警,说有用户在电商网站上遇到了错误。你查找了 web 日志,发现响应码不是 200(表示成功)。你希望按 environment 维度拆分这些日志,看看是不是 Production 环境的客户受到了影响,但日志中并没有 environment 字段。没关系 —— 只需通过 environment 做一个 lookup join,比如使用类似这样的文件(这是一个环境信息 lookup 的示例 CSV 文件):

clientip,environment
192.168.1.9,QA
192.168.14.2,Dev
192.168.12.3,Prod

现在在 environments 的 lookup 索引上添加 LOOKUP JOIN(我的索引名叫 envs_lkp

FROM kibana_sample_data_logs | WHERE response.keyword != "200" 
| LOOKUP JOIN envs_lkp ON clientip 
| STATS COUNT(*) by response, environment

生产环境和质量保证(QA)环境中存在错误。我们可以通过 join 一个包含每台 web 服务器所属团队的列表,来查看应该联系谁。

以下是 teams lookup 的示例 CSV 文件:

host,team
www.elastic.co,Web team
artifacts.elastic.co,Delivery team
cdn.elastic-elastic-elastic.org,Cloud team
elastic-elastic-elastic.org,Web team
FROM kibana_sample_data_logs | WHERE response.keyword != "200"
| LOOKUP JOIN teams_lkp ON host
| STATS num = COUNT(*) by host, response.keyword, team
| SORT num DESC

安全分析师喜欢使用他们的 joins!也许他们想要:

  • 确定请求已知恶意 URL 的客户端 IP

  • 与资产信息进行关联,按事件分组并分配优先级或风险

你可以从 URLhaus(Abuse.ch)下载恶意 URL 列表,并将其上传到一个 lookup 索引中。

FROM logs 
| LOOKUP JOIN urlhaus_lkp ON url 
| WHERE threat IS NOT NULL 
| KEEP @timestamp, url.keyword, clientip, threat

如何创建 lookups:

你需要至少一个 lookup 索引才能使用 lookup join。我们正在设计方法,便于在 Kibana 中创建和更新 lookups。目前,你可以通过几种方式开始创建 lookup 索引 —— 关键细节是索引模式必须是 “lookup”。

使用索引管理创建 lookup 索引:

在 Kibana 的左侧导航窗格中,点击 Stack Management,然后点击 Index Management。接着,在右侧点击 Create index。

提供一个索引名称,并从索引模式下拉菜单中选择 “Lookup”:

点击 Create 来创建一个空的 lookup 索引。

通过 API 创建 lookup 索引:

使用 create index API 创建一个 lookup 索引 —— 只需确保包含索引模式:

PUT mylookupindex
{
 "settings": {
   "index.mode": "lookup"
 }
}

使用 ML 文件上传器创建 lookup 索引:

在 Kibana 的左侧导航窗格中,点击 Machine learning,然后点击 File data visualizer(或者在 Kibana 的搜索栏中输入 “upload”)。

选择或拖动并放置你的文件 —— CSV 格式效果最好。

点击 Import 后,提供索引名称,点击 Advanced 以显示索引设置。在这里,你需要添加 index.mode:lookup

完成文件上传,点击 Import。一个索引和一个数据视图将被创建。

在所有情况下,你现在可以在 ES|QL 查询中引用这个 lookup 索引。

常见问题解答

问:什么时候我不应该使用 joins?

Lookup Join 非常强大,但有了强大的能力……你知道的。Joins 可能是一个开销较大的操作,每次 join 都会增加查询的延迟。某些情况下,使用 join 可能是过度的或不是最佳选择。例如,如果有一个字段你在很多查询中频繁使用 join,可以考虑将其去规范化到左侧索引中。在 ingest 时通过 enrich ingest processor、file shipper 配置、Logstash 过滤器等方式将其添加。这种一次性的 ingest 处理是存储使用量轻微增加与查询速度提升之间的权衡。这个方法最适用于那些不常变化(如用户 ID 的用户名)或永远不变化(如主机的制造商) 的参考值。

问:我可以直接查询 lookup 吗?

可以!lookup 索引基本上是 “只是一个索引”,所以你可以使用 ES|QL 查询它。

FROM <lookup_index> | …

或者通过创建一个数据视图。

问:我可以从 Logstash 或代理发送数据到 lookup 索引吗?

可以!不过请记住,lookup 索引不是数据流,它只有一个分片,所以每个 lookup 索引最多只能发送 20 亿个文档。

接下来是什么?

我们正在努力移除一些已知的限制,以便 lookup join 能够正式发布。同时,我们正在设计一个一流的编辑体验,让你能够直接在 Kibana Discover 中创建和编辑 lookup 数据集,或者将 CSV 文件拖到 Discover 中以填充索引。以下是这种功能可能的界面原型:

而 lookup joins 只是开始。我们还希望提供其他有用类型的 joins,如 INNER joins 或子查询,并且允许对任何索引进行 join(不仅仅是 lookup 索引)。

结论

这就是 lookup join,作为技术预览版在 Elasticsearch 8.18/9.0 中可用。

准备好开始了吗?Elastic 8.18 和 9.0 现在可以在 Elastic Cloud 上使用 —— 这是托管的 Elasticsearch 服务,包含了最新发布的所有新功能。代表 ES|QL 团队,我们期待你的反馈 —— 你可以在 Discover 中的 ES|QL 编辑器使用提交反馈按钮。嘿,我们在写完这篇关于 joins 的博客时居然没有做任何 joins 的双关语...感谢你的加入!

Elasticsearch 拥有丰富的新功能,帮助你为你的用例构建最佳的搜索解决方案。深入了解我们的示例笔记本,了解更多内容,开始免费的云试用,或者现在就尝试在本地机器上使用 Elastic。

原文:ES|QL Joins Are Here! Yes, Joins! - Elasticsearch Labs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值