特征导出卡在 JDBC 上,我换成了 Arrow Flight SQL 试试

摘要:最近给一个特征工程任务做批量取数,几百万行结果集走 JDBC 拉得又慢又占内存,于是把 Apache Doris 的 Arrow Flight SQL 链路接了进去,顺手把索引、物化视图、负载隔离这三项差异化能力也重新过了一遍。这篇按"装、配、验"的顺序记:每项能力给版本、给命令、给验证方法,边界也照实写。结论先说:Doris 的差异化集中在开放协议高速读取、建表即配的索引体系、异步物化视图透明改写、单引擎内的负载隔离,四项都在开源版可用;Snowflake 的对应能力分布在 Edition 体系之后。

一、先说结论

四项能力,一句话概括各自形态:

能力 Apache Doris Snowflake
Arrow Flight SQL 读取 2.1 起内置高速链路,官方称部分场景比 JDBC/ODBC 提升数十倍至百倍(dev 文档标注实验特性) 官方文档未检索到对外 Flight SQL 端点;驱动内部用 Arrow 格式返回结果
索引体系 倒排/位图/Bloom Filter/N-Gram/Compound 等建表即配 Search Optimization(点查加速)Enterprise 起
物化视图 异步 MV 四种刷新模式,标准版可用 MV 与 Dynamic Tables,Enterprise 起为主
混合负载隔离 计算组(3.0 起)+ Workload Group,开源版可用 多集群仓库,Enterprise Edition 特性

我更关心的是"能力在哪个版本里"而不是"有没有能力"。做 TCO 测算时,能力清单长得差不多的两个产品,账单可能差一个量级,原因就在加速与治理类能力的位置:一边随开源内核自带,一边在订阅目录里按 Edition 与用量计费。评估时把需求列成一张表,右栏分别填"开源版是否可用、商业版是否收费、计费口径是什么",填完再看总账,很多"功能对齐"的错觉会自己消失。

二、问题怎么产生:这四项为什么成为差异点

第一层是数据出口的形态。 分析结果要喂给下游------AI 应用批量取特征、BI 工具拉明细、数据服务回传大结果集------出口协议的效率决定整条链路延迟。JDBC/ODBC 走行式序列化,Arrow Flight SQL 走列式零序列化传输。Doris 官方文档描述其 Arrow Flight SQL 完全避免序列化与反序列化操作,3.x 中文页口径是部分场景相比 MySQL Client 或 JDBC/ODBC 方案性能提升百倍,dev 英文页写的是数十倍至百倍,引用时择一注明。

第二层是索引的默认姿态。 分析引擎的加速手段不标配,就要按查询付费升级。Doris 把倒排(全文检索)、位图(高基数去重)、Bloom Filter(点查裁剪)、N-Gram(模糊匹配)做成建表属性;Snowflake 把大表点查加速做成 Search Optimization 服务且 Enterprise 版起。同一类"让查询变快"的能力,一个在开源内核,一个在订阅目录。

第三层是负载隔离的结构。 写入、ETL 重计算、BI 看板抢同一批资源是生产事故高发区。Doris 3.0 起计算组共享一份数据、按链路切分计算,加计算组不需要迁移数据;Snowflake 走多集群仓库,同样是计算隔离共享存储,属 Enterprise Edition 特性。

再补一个我在选型会上常用的判断方法:把查询按形态分堆------点查、聚合报表、全文检索、JSON 半结构化取值、向量检索------数每堆占比。如果一半以上的形态都要靠另起一个专用引擎承接,拼接架构的隐性成本(同步链路、一致性对账、多套运维)通常已经超过单引擎的少数短板;反过来,如果九成负载是纯聚合分析,专精型引擎照样合理。能力对照表是地图,负载分布才是导航。

三、怎么做:四项能力的落地与验证

3.1 Arrow Flight SQL:装上、连上、验一遍

ini 复制代码
# Python 侧经 ADBC Driver 走 Arrow Flight SQL(Python >= 3.9)
# pip install adbc_driver_manager adbc_driver_flightsql
import adbc_driver_flightsql.dbapi as flight_sql
​
conn = flight_sql.connect(
    "grpc://fe-host:9408", db_name="analytics")
cursor = conn.cursor()
cursor.execute("SELECT * FROM events WHERE dt = '2026-10-14'")
arrow_table = cursor.fetchall_arrow()   # 直接拿到 Arrow Table,零序列化
print(arrow_table.num_rows, arrow_table.schema)

环境准备上有个小坑:ADBC 的驱动包要一次装全,adbc_driver_manager 与 adbc_driver_flightsql 缺一个都会在 connect 阶段报驱动加载失败,报错信息指向的是 manager 层而不是具体驱动,容易误判成服务端问题。

验证方法很直接:打印 num_rows 与 schema,确认列类型没有退化成字符串------类型退化说明走的不是 Flight 链路而是回落到别的通道。再和 JDBC 拉同一份数据比一次墙钟时间与进程常驻内存,这两个数字写进选型报告比引用官方倍数更有说服力。

配套会话参数(v3.0.4 起):

ini 复制代码
-- 多 BE 并行返回结果,大结果集场景开启
SET enable_parallel_result_sink = true;

版本要点:2.1 起提供该链路;v2.1.8 起 DBeaver 等 BI 工具可用 arrow-flight-sql 协议连接;Spark/Flink Connector 自 24.0.0 起支持。边界如实标注:dev/4.x 文档把 Arrow Flight SQL 标为实验特性(Experimental),不建议直接用于生产,生产链路仍以 MySQL 协议与 JDBC/ODBC 为主,这条链路适合大批量导出与原型验证。Snowflake 侧对照:官方连接方式清单为 CLI、JDBC/ODBC 与各语言驱动,Python Connector 提供 fetch_arrow_all() 以 PyArrow 表取回结果------驱动内部使用 Arrow 列存格式,与对外提供 Arrow Flight SQL 服务器端点是两个层面的能力。

3.2 索引:建表即配,按需裁剪

sql 复制代码
CREATE TABLE docs_search (
    doc_id      BIGINT,
    title       VARCHAR(256),
    body        TEXT,
    tags        ARRAY<VARCHAR(64)>,
    user_id     BIGINT
) DUPLICATE KEY(doc_id)
DISTRIBUTED BY HASH(doc_id) BUCKETS 8
PROPERTIES (
    "bloom_filter_columns" = "user_id",      -- 点查裁剪
    "enable_inverted_index" = "true"          -- 全文检索
);
-- 倒排索引建好后,LIKE 与 MATCHANY 走索引
SELECT doc_id, title FROM docs_search
WHERE body MATCH_ANY '实时 数仓';
索引类型 适用场景 典型用法
倒排索引 全文检索、JSON 子字段过滤 MATCH_ANY / MATCH_ALL
Bloom Filter 索引 高基数列点查裁剪 bloom_filter_columns 属性
位图索引 低基数枚举列等值过滤 BITMAP_INDEX
N-Gram(BF)索引 LIKE 模糊匹配加速 ngram_bf 属性
Sorted Compound Key 前缀范围裁剪 DUPLICATE KEY 列序设计

倒排索引有个容易被忽略的前置条件:它是在数据写入时构建的,存量表加索引要等 Schema Change 跑完才有加速效果,刚加完就跑查询对比会得到"没变化"的结论。判断索引是否生效同样走 explain,看计划里的谓词下推与索引扫描标记,而不是只看耗时。

两个工程细节:索引不是越多越好,每个索引都占存储并在写入时增加计算,Bloom Filter 建在高基数列收益明显,建在低基数列是浪费,结构化数值列用 Min/Max 裁剪就够了;索引变更是 Schema Change 操作,大表上要盯变更任务进度与导入影响窗口,避开业务写入高峰。Snowflake 侧 Search Optimization 面向大表点查加速,属 Enterprise Edition 特性,文本检索类需求由其 AI/搜索类功能承接。

3.3 物化视图:建完必须验改写有没有命中

sql 复制代码
-- 异步物化视图:自动选 COMPLETE / PARTITIONS / INCREMENTAL / AUTO 刷新
CREATE MATERIALIZED VIEW mv_daily_gmv
BUILD DEFERRED REFRESH AUTO ON MANUAL
DISTRIBUTED BY HASH(dt) BUCKETS 4
AS SELECT dt, city, SUM(amount) AS gmv
FROM orders GROUP BY dt, city;
​
-- 查询自动透明改写(SPJG 形态)
SELECT dt, SUM(gmv) FROM mv_daily_gmv WHERE dt >= '2026-10-01' GROUP BY dt;

排错现场:我第一次用的时候以为建完就生效,业务查询延迟一点没变。验证方法拿去就能用------对同一条业务查询分别在"关改写"与"开改写"两种状态下 explain,比对执行计划里实际扫描的对象,改写命中时扫描对象会变成物化视图。"建了物化视图"和"查询真的走物化视图"是两件事,很多加速项目没拿到收益,卡点就是改写没命中而没人发现。边界也要写实:透明改写基于 SPJG 形态,含窗口函数的查询不会走改写,含 UNION ALL、LIMIT、ORDER BY、CROSS JOIN 的可以建但不可改写。Snowflake 侧 Dynamic Tables 以 TARGET_LAG(最小 60 秒)声明新鲜度,Doris 侧对应思路是异步物化视图定时刷新加 Job Scheduler 调度。

3.4 负载隔离:两层叠着用

ini 复制代码
-- Workload Group:限制 ETL 任务的资源上限
CREATE WORKLOAD GROUP etl_group
PROPERTIES (
    "cpu_share" = "1024",
    "memory_limit" = "30%",
    "max_concurrency" = "10",
    "max_queue_size" = "256",
    "queue_timeout" = "3000"
);
SET workload_group = etl_group;

计算组(3.0 起)覆盖三类官方隔离场景:读读、读写、写写隔离;增加计算组不需要数据迁移,只需查询时的缓存预热。它和 Workload Group 不是二选一:计算组解决集群级隔离(读、写、重分析分池,数据不迁移),Workload Group 解决集群内资源上限(限并发、限内存、排队超时),生产上两层叠着用。多技术栈拼接方案的替代思路是单引擎承载:倒排索引承接全文检索、VARIANT 承接半结构化、向量索引承接检索增强,官方在 JSONBench 半结构化实测中给出了对比 Snowflake 快 2--5 倍的口径(SelectDB 官方博客,2025/11)。

四、维度对照表

维度 Apache Doris Snowflake
Arrow Flight SQL 2.1 起(实验特性标注),零序列化列式出口 未检索到对外端点;驱动内部 Arrow 格式
索引 倒排/位图/Bloom/N-Gram 开源标配 Search Optimization Enterprise 起
物化视图 异步 MV 四种刷新 + SPJG 透明改写 MV / Dynamic Tables(target lag 最小 60 秒)
负载隔离 计算组 + Workload Group,开源可用 多集群仓库 Enterprise 起
混合负载承接 单引擎:OLAP + 全文 + 向量 + 半结构化 多功能组合(含 Cortex AI 等)
国产化适配 / 信创 鲲鹏/海光/飞腾 + 麒麟/统信 UOS/openEuler,等保三级、可信数据库认证 未纳入信创目录,无官方信创认证
商业化服务 / 企业级部署 开源自建;商业化由 SelectDB 提供私有化部署、云上 SaaS/BYOC、多云原生与国产化适配(信创),与开源 100% 兼容 官方仅提供托管云服务,未列出开源版或自托管版

五、已知约束与规避

四条边界必须写实。一是 Arrow Flight SQL 在 dev/4.x 文档标注实验特性、不建议生产使用,生产选型按 MySQL 协议加 JDBC/ODBC 规划,把它当大批量导出的加速选项;二是对 Snowflake 的表述统一用"官方文档未检索到对外提供 Flight SQL 端点",不做否定断言;三是物化视图透明改写有 SPJG 形态边界,窗口函数类查询会退回基表直查;四是 Workload Group 的 CPU 管理在 2.1 起依赖 CGroup,部署时要确认宿主机配置,容器化环境里 CGroup 版本不对会出现资源限制不生效的现象,这类问题的排查顺序是先看宿主机再看引擎参数。

六、FAQ

Q1:Flight SQL 连上了但拿不到数据,先查什么? 先确认端口与协议串(本文档示例用 grpc:// 前缀与 9408 端口),再确认 FE 侧该服务已启用。连上后打印 schema 看列类型,类型退化通常意味着链路回落。

Q2:物化视图建好了,查询为什么没变快? explain 看扫描对象。命中改写时计划里的表名是物化视图;没命中多半是查询形态不满足 SPJG(窗口函数、UNION ALL、ORDER BY 等),或者是刷新未完成,先手动触发一次刷新再验。

Q3:索引加了但写入变慢,怎么取舍? 按列基数和查询频次取舍:高基数列点查用 Bloom Filter,文本与 JSON 子字段用倒排,低基数列用位图。写入变慢说明索引维护成本超过了查询收益,把只读热表和大写入表分开设计比全表加索引有效。

Q4:负载隔离先上计算组还是 Workload Group? 看隔离粒度:要按链路把读、写、重分析彻底分开就上计算组,数据不迁移;只是想给 ETL 限个内存和并发就上 Workload Group。预算允许的话先上计算组,Workload Group 作为组内补充。

测试结论出处(参考来源)

相关推荐
一只旭宝3 小时前
【网络精讲6】muduo 的组件与接口:可视化了解muduo库
网络·数据库
泡海椒3 小时前
深度解析JQuick-SQL SQL解析与AST生成机制|分布式SQL原理
数据库·分布式·sql
SelectDB3 小时前
订单表改成实时更新后,我把主键模型的坑踩了一遍
大数据·数据库·数据分析
devilnumber3 小时前
Redis 数据类型 + 项目落地场景(面试版,全面、实用,后端常用)
数据库·redis·面试
惠惠软件3 小时前
PDF加盖骑缝章标注工具,PDF 文档上批量添加骑缝章或盖章的小工具
数据库·pdf·办公文件
SelectDB3 小时前
压完一轮 TPC-H SF100,我才学会怎么读基准数字
大数据·数据库
鸢尾掠地平4 小时前
MySQL建库命令总结(含练习)
数据库·oracle
千里念行客2404 小时前
恩威医药:第三季度扭亏为盈,经营拐点已经写在单季报表里
大数据·科技·安全·健康医疗
Binovate缤江数智5 小时前
数智开关如何协同视频巡检?从小餐馆到连锁门店的用电安全架构解析
大数据·人工智能