系列

Snuba 有一个查询处理管道,首先将 Snuba 查询语言( legacySnQL)解析为 AST,然后在 Clickhouse 上执行 SQL 查询。在这两个阶段之间,在 AST 上执行几次传递以应用查询处理转换。

处理管道有两个主要目标:优化查询并防止对我们的基础设施构成危险的查询。

在数据模型上,查询处理流水线分为逻辑部分,进行产品相关处理,物理部分专注于优化查询。

逻辑部分包含查询验证等步骤,以确保它与数据模型匹配或应用自定义函数。 物理部分包括诸如提升标签(promoting tags)和选择预聚合视图(pre-aggregated view)来为查询提供服务等步骤。

查询处理阶段

本节介绍了上述各阶段的代码和示例,并提供了一些提示。

Legacy 和 SnQL 解析器

Snuba 支持两种语言,传统的基于 JSON 的语言和新的名为 SnQL 的语言。除了传统语言不支持的连接和复合查询之外,查询处理管道不会更改是否使用一种或另一种语言。

Snuba 支持两种语言,一种是基于 JSON 的旧语言,另一种是名为 SnQL 的新语言。 除了遗留语言不支持的连接和复合查询之外,无论使用哪种语言,查询处理管道都不会改变。

它们都生成一个逻辑查询AST,该查询由下面数据结构表示。

基于 JSON 的语言旧解析器源码:

SnQL 解析器:

查询验证(Query Validation)

此阶段确保可以运行查询(大多数情况下,我们还没有捕获所有可能的无效查询)。 这个阶段的职责是在无效查询的情况下返回一个 HTTP400,并向用户提供适当的有用消息。

这分为两个子阶段:一般验证(general validation)和实体特定验证(entity specific validation)。

一般验证由一组检查组成,这些检查在解析器生成查询之后立即应用于每个查询。这在 QueryEntity 函数中发生。这包括防止别名阴影(alias shadowing)和函数签名验证(function signature validation)等验证。

每个实体也可以以必需列的形式提供一些验证逻辑。这发生在 class Entity(Describable, ABC):。 这允许查询处理拒绝在 project_id 上没有条件或没有时间范围的查询。

逻辑查询处理器(Logical Query Processors)

查询处理器是无状态转换,接收查询对象(及其 AST)并就地转换。这是为逻辑处理器实现的接口。在逻辑阶段,每个实体提供按顺序应用的查询处理器。常见的用例是像 apdex 这样的自定义函数,或者像时间序列处理器(time series processor)那样的计时。

查询处理器不应该依赖于在之前或之后执行的其他处理器,并且应该彼此独立。

存储选择器(Storage Selector)

如 Snuba 数据模型中所述,每个实体可以定义多个存储。 多个存储代表多个表,并且出于性能原因可以定义物化视图(materialized views),因为某些视图可以更快地响应某些查询。

在逻辑处理阶段(完全基于实体)结束时,存储选择器可以检查查询并为查询选择合适的存储。 存储选择器在实体数据模型中定义并实现此接口。 一个例子是 Errors 实体,它有两个存储,一个用于一致查询(它们被路由到写入事件的相同节点),另一个只包括我们没有写入的副本来服务大多数查询。 这减少了我们写入的节点上的负载。

查询转换器(Query Translator)

不同的 storage 有不同的 schema(这些反映了 clickhouse 表或视图的 schema)。 它们通常都与实体模型不同,最显着的例子是用于标签 tags[abc] 的可下标表达式,它在 clickhouse 中不存在,其中访问标签看起来像 tags.values[indexOf(tags.key, 'abc')]

选择 storage 后,需要将查询转换为物理查询。Translator 是一个基于规则的系统,规则由实体(针对每个 storage)定义并按顺序应用。

与查询处理器相反,翻译规则在查询上没有完整的上下文,只能翻译单个表达式。 这使我们能够轻松地编写翻译规则并跨实体重用它们。

这些是 transactions 实体的转换规则。

物理查询处理器(Physical Query Processors)

与逻辑查询处理器相比,物理查询处理器的工作方式非常相似。它们的接口非常相似,语义相同。 不同之处在于它们对物理查询进行操作,因此,它们主要是为优化而设计的。 例如,该处理器在标签上找到相等条件,并将它们替换为标签哈希图(有布隆过滤器索引)上的等效条件,从而使过滤操作更快。

查询拆分器(Query Splitter)

通过将某些查询拆分为多个单独的 Clickhouse 查询并组合每个查询的结果,可以以优化的方式执行某些查询。

两个例子是时间拆分和列拆分。两者都在下面这个文件中。

时间拆分(Time splitting)将一个查询(不包含聚合且已正确排序)在一个可变的时间范围内拆分为多个查询,该时间范围的大小逐渐增大,并在得到足够的结果后按顺序停止执行。

列拆分(Column splitting)拆分筛选和列获取。它对最少数量的列执行查询的筛选部分,以便 Clickhouse 加载较少的列,然后通过第二个查询,仅为第一个查询筛选的行获取缺少的列。

查询格式化器(Query Formatter)

该组件只是将查询格式化为 Clickhouse 查询字符串。

复合查询处理

上面的讨论仅适用于简单查询、复合查询(连接和包含子查询的查询遵循稍微不同的路径)。

上面讨论的简单查询管道不适用于连接查询或包含子查询的查询。 为了使这项工作发挥作用,每个步骤都必须考虑连接的查询和子查询,这会增加过程的复杂性。

为了解决这个问题,我们将每个连接查询转换为多个简单子查询的连接。每个子查询都是一个简单的查询,可以通过上述管道进行处理。这也是运行 Clickhouse 连接(join)的首选方式,因为它允许我们在连接之前应用过滤器。

此类查询的查询处理管道由与上述内容相关的几个附加步骤组成。

子查询生成器(Subquery Generator)

该组件采用一个简单的 SnQL 连接查询,并为连接中的每个表创建一个子查询。

表达式下推(Expressions Push Down)

上一步生成的查询将是一个有效的连接,但效率极低。 这一步基本上是一个连接优化器(join optimizer),它将所有可以成为子查询一部分的表达式下推到子查询中。 这是一个独立于子查询处理的必要步骤,因为 Clickhouse join 引擎不执行任何表达式下推,所以它由 Snuba 来优化查询。

简单查询处理管道(Simple Query Processing Pipeline)

这与上面讨论的从逻辑查询验证到物理查询处理器的管道相同。

连接优化(Join Optimizations)

在处理结束时,我们可以对整个复合查询应用一些优化,例如将 join 转换为 Semi Join

Sentry 监控 - Snuba 数据中台架构(Query Processing 简介)的更多相关文章

  1. Sentry 监控 - Snuba 数据中台架构(SnQL 查询语言简介)

    本文描述了 Snuba 查询语言 (SnQL). 系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒 ...

  2. Sentry 监控 - Snuba 数据中台架构(Data Model 简介)

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

  3. Sentry 监控 - Snuba 数据中台架构(编写和测试 Snuba 查询)

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

  4. Sentry 监控 - Snuba 数据中台架构简介(Kafka+Clickhouse)

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

  5. Sentry 监控 - Snuba 数据中台本地开发环境配置实战

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

  6. Sentry 监控 - 私有 Docker Compose 部署与故障排除详解

    内容整理自官方开发文档 系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Map ...

  7. Sentry 监控 - Environments 区分不同部署环境的事件数据

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

  8. Sentry 监控 - Distributed Tracing 分布式跟踪

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

  9. 【转】阿里架构总监一次讲透中台架构,13页PPT精华详解

    转:https://blog.csdn.net/u011323949/article/details/99542576 本文整理了阿里几位技术专家,如架构总监 谢纯良,中间件技术专家 玄难等几位大牛, ...

随机推荐

  1. 线程间协作的两种方式:wait、notify、notifyAll和Condition

    转载自海子: 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者 ...

  2. Linkerd 2.10(Step by Step)—3. 自动轮换控制平面 TLS &Webhook TLS 凭证

    Linkerd 2.10 系列 快速上手 Linkerd v2 Service Mesh(服务网格) 腾讯云 K8S 集群实战 Service Mesh-Linkerd2 & Traefik2 ...

  3. JAVA《多线程多人上线通知案例》

    package com.wangbiao.palyermanager; import com.wangbiao.player.Player; /** * TODO * * @author wangbi ...

  4. springgateway

    SpringGateAway: 先进行鉴权,然后进行路由,日志什么等等

  5. 使用spring向service里面注入dao不成功。

    因为原来的程序没有使用spring.后来加spring的时候action有个地方的new没有改!!! new了个新的实现层 不是spring管理的对象.

  6. GoLang设计模式3 - 抽象工厂模式

    之前我们介绍了工厂设计模式,现在我们再看一下抽象工厂设计模式.抽象工程模式顾名思义就是对工厂模式的一层抽象,也是创建型模式的一种,通常用来创建一组存在相关性的对象. UML类图大致如下: 类图比较复杂 ...

  7. JVM详解(一)——概述

    Test https://www.cnblogs.com/yrxing/p/14651346.html#gc的基础知识 https://www.cnblogs.com/yinzhengjie/p/92 ...

  8. 使用dubbo-go搭建dubbo接口测试平台

    背景 http接口测试只需要一个curl命令,但dubbo协议没有这样的现成接口测试工具.通常公司内的dubbo控制台或其他平台会集成一个dubbo接口测试工具. 调用一个dubbo接口,需要知道服务 ...

  9. 硕盟SM-T54|type-c转接头HDMI+VGA+USB3.0+PD3.0四合一多功能扩展坞接口功能说明

    硕盟SM-T54是一款 TYPE C转HDMI+VGA+USB3.0+PD3.0四合一多功能扩展坞,支持四口同时使用,您可以将含有USB 3.1协议的电脑主机,通过此产品连接到具有HDMI或VGA的显 ...

  10. python库--pandas--MultiIndex

    *表示后面会重复用到此参数 创建层次化索引 pd.MultiIndex 构造器 MI levels 每个级别不重复的标签 labels 每个级别的整数指定每个位置 *sortorder=None   ...