【Doris系列】 SQL 多方言兼容

目前 Doris 引擎提供了两种方式实现对 sql 多方言的支持。即,提交指定方言的 sql,Doris 可以成功解析,并返回正确的计算结果。本文就简单来测试验证下这两种方式的效果。

一、Doris Sql Convertor

Doris 官方提供了一个 sql convertor 工具,这是一个单独的服务,与 Doris 服务本身是解耦的。我们可以参考官方文档:SQL 方言兼容,直接下载、启动服务即可。

1.1 功能验证

首先需要通过 set 来显示设置服务的地址,这样 FE 在执行 sql 的时候,就会将 sql 通过 HTTP 发送到转换工具,然后将转换之后的查询返回。设置语句如下:

set global sql_converter_service_url = "http://127.0.0.1:5001/api/v1/convert";

接着就可以指定方言来测试下这个工具的效果。

1.1.1 引用标识符改写测试

这里我们以 Trino 方言为例,来测试下引用标识符的改写效果(Doris 的引用标识符是反引号,Trino 的是双引号):

// 可以在 WebUI 看到查看 query profile
SET is_report_success=true;

// 获取正确的 sql 执行结果
set sql_dialect=doris;
select count(distinct user_id) from example_tbl;
select sex, count(distinct user_id) from example_tbl group by sex;

// 设置引用标识符为双引号,验证 sql convertor 改写效果
set sql_dialect=trino;
select count(distinct "user_id") from example_tbl;
select sex, count(distinct "user_id") from example_tbl group by sex;

执行结果如下所示:
1
2

可以看到,两种方言场景下,执行结果完全一致。这说明 sql convertor 工具成功改写了 sql,并且执行结果也是完全正确的。我们可以通过 WebUI 观察提交的 sql,如下所示:
3

可以看到,实际执行的 SQL 已经被改写成反引号,这符合我们的预期。

1.1.2 函数改写测试

接着我们测试下是否可以实现一些简单的函数改写,测试 case 如下所示:

set sql_dialect=trino;
// 测试函数替换,approx_distinct 是 Trino 中的近似去重函数,Doris 中没有此函数
select sex, approx_distinct("user_id") from example_tbl group by sex;

执行结果如下:
4

可以看到,approx_distinct被改写为APPROX_COUNT_DISTINCT,并且引用标识符也替换成了反引号,这说明改写生效,符合预期。

1.2 Doris 侧源码解析

由于 sql convertor 工具本身没有开源,因此我们主要看下 Doris 的 FE 中相关的代码流程。针对上述的 sql convertor 工具,Doris 在 FE 中加入了一个 HTTP 的 plugin 来实现与该工具的交互。在 FE 启动的时候,就会加载这个 plugin,主要的代码调用如下所示:

main(DorisFE.java):83
-start(DorisFE.java):168
--initialize(Env.java):1002
---init(PluginMgr.java):93
----initBuiltinPlugins(PluginMgr.java):122
-----ctor(HttpDialectConverterPlugin.java)

上述代码调用基于 Doris 2.1.2版本,不同的版本代码行数可能会有所不同。FE 启动之后,我们就可以通过 show plugins 命令来查看已经加载的 plugins:
5

上面的__builtin_SqlDialectConverter就是对应的这个 HTTP plugin。当我们通过 sql_converter_service_url 配置项设置了 sql convertor 工具的地址之后,下次 sql 执行就会通过 HTTP 请求将 sql 发到该服务进行方言转换,对应的代码调用如下所示:

handleQuery(MysqlConnectProcessor.java):176
-handleQuery(ConnectProcessor.java):184
--executeQuery(ConnectProcessor.java):195
---convertOriginStmt(ConnectProcessor.java):320
----convertSql(HttpDialectConverterPlugin.java):106
-----convertSql(HttpDialectUtils.java)

最终在convertSql方法中完成了与 sql convertor 工具的交互。

二、Plugin 方言转换插件

除了上面提到的 sql convertor 工具, Doris 还支持通过 plugin 的方式来实现方言转换。目前,Doris 内置了 Trino 和 Spark 两种方言 plugin,分别位于 /fe_plugins/trino-converter和 /fe_plugins/sparksql-converter 这两个路径下,需要自己编译和安装。

2.1 编译 Plugin

我们可以直接执行build_plugin.sh脚本来编译当前 Doris 自带的所有 plugin。需要注意的是,由于在编译 plugin 的时候,其依赖的 fe-core 和 fe-common jar 包是通过远端 maven 仓库下载的,因此可能与最新的 FE 代码不一致(仓库代码可能比较落后)。因此,建议直接编译 FE,然后将对应的 jar 部署到本地仓库:

mvn install:install-file -DgroupId=org.apache.doris -DartifactId=fe-core -Dversion=1.2-SNAPSHOT -Dpackaging=jar -Dfile=/root/doris/fe/fe-core/target/doris-fe.jar
mvn install:install-file -DgroupId=org.apache.doris -DartifactId=fe-common -Dversion=1.2-SNAPSHOT -Dpackaging=jar -Dfile=/root/doris/fe/fe-common/target/doris-fe-common.jar

接着再编译 FE plugin 模块,如果出现一些类或者方法名不存在的问题,需要根据 FE 的代码来调整 plugin 模块的相关代码。

2.2 加载 Plugin

编译完成之后,就可以通过install命令进行安装:

install plugin from "/xx/doris/fe_plugins/trino-converter/target/trino-converter.zip";

安装完成之后,我们就可以通过 show plugins 命令来查看已经安装的 plugin:
6

此时,在 FE 部署目录的/plugins下面也可以看到安装的这个 plugin。

2.3 Trino Plugin 测试

这里以 Trino 的 plugin 为例来测试下方言转换的效果:

// 为了验证效果,先屏蔽掉 sql convertor 工具
set global sql_converter_service_url = "";
2.3.1 引用标识符改写测试

同样,首先测试下引用标识符的改写效果:

// 获取正确的 sql 执行结果
set sql_dialect=doris;
select count(distinct user_id) from example_tbl;
select sex, count(distinct user_id) from example_tbl group by sex;
// 设置引用标识符为双引号,验证 trino plugin 的改写效果
set sql_dialect=trino;
select count(distinct "user_id") from example_tbl;
select sex, count(distinct "user_id") from example_tbl group by sex;

执行结果如下所示:

7
8

可以看到,设置 Trino 方言之后, 两条 sql 的执行效果与 Doris 方言的执行效果都不同,说明这里的改写是有问题的,sql 执行结果不正确。从 WebUI 看 sql 也没有被改写:
9

2.3.2 函数改写测试

执行如下 SQL 来检测函数改写的效果:

set sql_dialect=trino;
select sex, approx_distinct("user_id") from example_tbl group by sex;

执行结果如下所示:
10

可以看到,执行直接报错,找不到这个函数,说明 Trino 的 plugin 并没有改写函数。

2.3.3 源码解析

方言 Plugin 的代码流程与上面的 sql convertor 有所不同,这里简单看下相关的代码调用:

// FE 模块代码
-executeQuery(ConnectProcessor.java):205
--parseSQL(NereidsParser.java):71
---parseSQLWithDialect(NereidsParser.java):97
// FE Plugin 模块代码
parseSqlWithDialect(TrinoDialectConverterPlugin.java):43
-parse(TrinoParser.java):63
--parseSingle(TrinoParser.java):91
---parse(TrinoParser.java):79
----createStatement(io.trino.sql.parser.SqlParser)
--parseSingle(TrinoParser.java):92
---visit(TrinoLogicalPlanBuilder.java)

可以看到,方言 Plugin 是在 Doris 的新优化器 NereidsParser 中被调用的。首先用 Trino 的 SqlParser 将 sql string 转换成了 Trino 的 Statement,然后利用 TrinoLogicalPlanBuilder 将 Trino 的 AST 转换成了 Doris 自己的 StatementBase。由于这里是直接生成了 AST 结构,并没有像 sql convertor 那样生成一个新的 sql string,因此我们在 WebUI 看到的都是原始的 sql。我们可以通过 debug 调试来查看对应的执行计划是否被改写,如下所示:

11
12

可以看到,当方言是 Trino 的时候,sql 里面的 user_id 被解析成 UnboundSlot,而 Drois 方言下则解析成了 VarcharLiteral(这是一个常量),这说明 Trino 的 plugin 转换是生效了,只是在 WebUI 上没有提现。

三、总结

3.1 代码流程对比

我们在前面章节分别简单介绍了两种方言转换工具的代码调用,这里我们将整个流程串联到一起,如下所示:
13

可以看到,sql在整个 Doris 的 FE 中的相关流程如下:

  1. 首先通过 sql convertor 工具对 sql 进行改写,返回值仍然是一个 sql string 的形式;
  2. 然后这个 sql string 会通过 NereidsParser 进行 sql 解析,在这里面会用到方言的 Plugin 进行转换,此时的返回值就是一个 AST 了;
  3. 最终生成的 sql plan 会由 BE 实际执行。

因此,我们可以得知,这两个方言转换的工具是会同时执行的。也就是说,我们既可以部署 sql convertor,也可以安装方言 plugin。两种转换工具都存在的前提下,sql convertor 会优先执行,因此可能会覆盖方言 plugin 的转换。

3.2 两种工具优缺点对比

这里我们对两种方言转换工具的特点做一个简单的对比:

方言工具兼容性功能性开放性总结
Sql Convertor工具兼容 Presto、Trino、ClickHouse、Hive 等近十种主流 SQL 方言函数改写和引用标识符改写等case 验证通过不开放源代码,实现可以参考 SqlGlot功能性比较完备,但是依赖官方更新,完全黑盒|
方言 Plugin工具只提供了 Trino 和 Spark不支持函数改写,引用标识符改写也有问题,总体看问题比较多代码完全开源问题较多,生产环境没办法直接用,兼容性较差,需要自己开发完善

3.3 写在最后

本文简单测试了下当前 Doris 提供的两种方言转换工具,并介绍了相关的代码调用流程。我们可以发现,sql convertor 工具相对比较成熟,可用性比较好。方言 Plugin 插件问题较多,甚至改写后的查询结果也是有问题的,后续有时间再详细看下这块的问题,这里不再展开。本文的相关内容都是笔者个人基于代码分析和实际测试,如有错误,欢迎指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/583781.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ES全文检索支持拼音和繁简检索

ES全文检索支持拼音和繁简检索 1. 实现目标2. 引入pinyin插件2.1 编译 elasticsearch-analysis-pinyin 插件2.2 安装拼音插件 3. 引入ik分词器插件3.1 已有作者编译后的包文件3.2 只有源代码的版本3.3 安装ik分词插件 4. 建立es索引5.测试检索6. 繁简转换 1. 实现目标 ES检索时…

力扣33. 搜索旋转排序数组

Problem: 33. 搜索旋转排序数组 文章目录 题目描述思路复杂度Code 题目描述 思路 1.初始化左右指针:首先,定义两个指针left和right,分别指向数组的开始和结束位置。 2.计算中间值:在left和right之间找到中间位置mid。 3.比较中间值…

使用Python爬取淘宝商品并做数据分析

使用Python爬取淘宝商品并做数据分析,可以按照以下步骤进行操作: 确定需求:确定要爬取的淘宝商品的种类、数量、关键词等信息。 编写爬虫程序:使用Python编写爬虫程序,通过模拟浏览器请求,获取淘宝商品的页…

ffmpeg音视频裁剪

音视频裁剪,通常会依据时间轴为基准,从某个起始点到终止点的音视频截取出来,当然音视频文件中存在多路流,所对每一组流进行裁剪 基础概念: 编码帧的分类: I帧(Intra coded frames): 关键帧,…

SpringCloud学习笔记(一)微服务介绍、服务拆分和RestTemplate远程调用、Eureka注册中心

文章目录 1 认识微服务1.1 单体架构1.2 分布式架构1.3 微服务1.4 SpringCloud1.5 总结 2 服务拆分与远程调用2.1 服务拆分原则2.2 服务拆分示例2.2.1 搭建项目2.2.2 创建数据库和表2.2.3 实现远程调用2.2.3.1 需求描述2.2.3.2 注册RestTemplate2.2.3.3 实现远程调用 2.2.4 提供…

【网络】HTTP协议

文章目录 一. 认识 URL1. URL 初识2. URL 的组成① 协议名称② 域名③ 端口号④ 文件路径⑤ 查询参数 3. URL中的字符3.1 合法字符3.2 保留字符3.3 其他字符3.4 URL中的字符总结 二. HTTP 协议1. HTTP 介绍2. 请求报文2.1 请求报文的格式2.2 请求方法介绍2.3 请求报文中常见的 …

【LeetCode:1103. 分糖果 II + 模拟】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

CUDA架构介绍与设计模式解析

文章目录 **CUDA**架构介绍与设计模式解析**1** CUDA 介绍CUDA发展历程CUDA主要特性CUDA系统架构CUDA应用场景编程语言支持CUDA计算过程线程层次存储层次 **2** CUDA 系统架构分层架构并行计算模式生产-消费者模式工作池模式异步编程模式 **3** CUDA 中的设计模式工厂模式策略模…

电脑技巧:推荐一款非常好用的媒体播放器PotPlayer

目录 一、 软件简介 二、功能介绍 2.1 格式兼容性强 2.2 高清播放与硬件加速 2.3 自定义皮肤与界面布局 2.4 多音轨切换与音效增强 2.5 字幕支持与编辑 2.6 视频截图与录像 2.7 网络流媒体播放 三、软件特色 四、使用技巧 五、总结 一、 软件简介 PotPlayer播放器 …

【MATLAB源码-第201期】基于matlab的黏菌群优化算法(SMA)无人机三维路径规划,输出做短路径图和适应度曲线

操作环境: MATLAB 2022a 1、算法描述 黏菌优化算法(Slime Mould Algorithm, SMA)是一种新颖的启发式优化方法,其灵感来源于自然界中的真菌——黏菌。这种算法模拟了黏菌在寻找食物时的行为和网络形成策略。在本文中&#xff0c…

【Linux】yum、vim

🌈个人主页:秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343🔥 系列专栏:https://blog.csdn.net/qinjh_/category_12625432.html 目录 Linux 软件包管理器 yum 什么是软件包 查看软件包 如何安装软件 如何卸载软…

网络安全的重要性及人才需求

安全现在是大趋势,说是铁饭碗也不为过,就业前景好,方向多比传统计算机行业就业舒服点。但是大厂依然是985,211的天下,是双非能进大厂的,只是凤毛麟角。前提是你的能力可以让公司忽略你的学历。 以2023年为…

【华为】VRRP的实验配置

【华为】VRRP的实验配置 实验需求拓扑LSW 3LSW 1基础配置VRRPDHCPOSPF默认路由 LSW 2基本配置VRRPDHCPOSPF默认路由 R1ISPPC1PC2 测试上网VRRP实验需求监视端口 配置文档 实验需求 ① 该公司有市场部和技术部,分别划在VLAN 10 和 VLAN 20里面 ② 此时为了网络的稳…

万兆以太网MAC设计(12)万兆UDP协议栈上板与主机网卡通信

文章目录 一、设置IP以及MAC二、上板效果2.1、板卡与主机数据回环测试2.2、板卡满带宽发送数据 一、设置IP以及MAC 顶层模块设置源MAC地址 module XC7Z100_Top#(parameter P_SRC_MAC 48h01_02_03_04_05_06,parameter P_DST_MAC 48hff_ff_ff_ff_ff_ff )(input …

双目深度估计原理立体视觉

双目深度估计原理&立体视觉 0. 写在前面1. 双目估计的大致步骤2. 理想双目系统的深度估计公式推导3. 双目标定公式推导4. 极线校正理论推导 0. 写在前面 双目深度估计是通过两个相机的对同一个点的视差来得到给该点的深度。 标准系统的双目深度估计的公式推导需要满足:1)两…

ASR语音转录Prompt优化

ASR语音转录Prompt优化 一、前言 在ASR转录的时候,我们能很明显的感受到有时候语音识别不是很准确,这过程中常见的文本错误主要可以归纳为以下几类: 同音错误(Homophone Errors) 同音错误发生在不同词语发音相似或相…

Modelsim自动仿真平台的搭建

Modelsim自动仿真平台的搭建 如果要搭建自动仿真平台脚本那就需要更改下面3个文件。run_simulation.bat、complie.do和wave.do文件。注:前提是安装了modulsim并且配置好了环境变量,这里不过多介绍。 一、下面是run_simulation.bat文件的内容 : 注释的…

MySQL-查询数据-练习

练习 1.创建一个查询,显示收入超过 12,000 的雇员的名字和薪水。 select LAST_NAME,SALARY from employees where SALARY > 12000;2.创建一个查询,显示雇员号为 176 的雇员的名字和部门号。 select LAST_NAME,DEPARTMENT_ID from employees where …

前端vue如何生成二维码

有时候有需要链接直接生成二维码在手机上看的需求,比如下载,比如信息,比如excel 下面先引入包 import QRCode from qrcode; 然后上代码 // 将res转换成二维码const qrCodeData JSON.stringify(res); // 将res转换为字符串作为二维码数据// …

WebSocket 全面解析

🌟 引言 WebSocket,一个让实时通信变得轻而易举的神器,它打破了传统HTTP协议的限制,实现了浏览器与服务器间的全双工通信。想象一下,即时消息、在线游戏、实时股票报价…这一切都离不开WebSocket的魔力💫。…