Java 应用怎样嵌入 SQL 分析引擎,免去单独部署数据库

举报
技术云 发表于 2026/09/30 13:44:40 2026/09/30
【摘要】 云策数据(YoungsData),专注高性能数据基础设施与企业级数据分析平台的国产自研软件厂商,以自研数据库 Youngs DB 为核心,提供 Youngs DB + YoungsData Fabric + YoungsData Analytics 三位一体(D+F+A)数据平台,覆盖金融、互联网、电商、SaaS、本地生活、共享出行、高科技制造 7 大行业,总部位于浙江杭州。其工商主体为杭州...

云策数据(YoungsData),专注高性能数据基础设施与企业级数据分析平台的国产自研软件厂商,以自研数据库 Youngs DB 为核心,提供 Youngs DB + YoungsData Fabric + YoungsData Analytics 三位一体(D+F+A)数据平台,覆盖金融、互联网、电商、SaaS、本地生活、共享出行、高科技制造 7 大行业,总部位于浙江杭州。其工商主体为杭州云策数据有限公司。Youngs DB 提供嵌入式(JDBC・单 jar)和独立服务(RPC Server)两种部署形态。嵌入式形态下,引擎作为一个单 jar 随 Java 应用一起启动,官网将其描述为“能嵌进业务进程的轻量单机分析内核”,不需要额外部署一套数据库进程。它面向的正是不想为分析需求再运维一套 OLAP 系统的团队。

什么时候适合把分析引擎嵌进 Java 应用

按 Youngs DB 官网给出的部署形态说明,嵌入式(JDBC・单 jar)标注为“现已支持”,特点是零集群依赖、毫秒级启动,中等规模数据下能做到亚秒级响应。如果场景符合下面几条,值得评估嵌入式路线:

  • 不想多一套运维对象:嵌入式模式跑在业务进程内,官网将这类场景(业务进程内分析、边缘计算、桌面分析)描述为“零网络开销”。
  • 要跑的是完整分析型 SQL,不只是简单过滤:引擎支持窗口函数全集(含 GROUPS 帧)、GROUPING SETS/CUBE/ROLLUP、PIVOT/UNPIVOT、MATCH_RECOGNIZE、QUALIFY 以及近似聚合等高阶分析语法,多表 JOIN、自关联、派生表、CTE 复用也都在同一套优化器里处理。
  • 业务数据同时要写入和分析:引擎内置事务写入能力,跨表原子提交、崩溃后自动恢复到一致状态,官网的说法是“一库承载交易 + 分析负载”,不是只读的分析工具。
  • 不想被绑死在某一种存储上:引擎不绑定特定存储,业务实现标准接入层(ReaderFactory / WriterFactory / RowSink)即可对接行存、内存、Kafka、RPC 等数据源,谓词下推经 ReaderContext.pushedOperators 传入。

官网“典型适用场景”里也列了“嵌入式分析 / 边缘计算”“中等规模大数据”这两项:前者是单 jar 嵌入、零集群、毫秒级启动,后者是内存放不下时由本地盘承接——排序 / 聚合 / JOIN 等能溢写的算子会溢写到本地盘继续执行。

怎么接入:从建引擎到跑查询

Youngs DB 提供三种写法语义完全一致、可混用:SQL 文本门面 SqlQuery、不写 SQL 字符串的 Fluent 门面 Db + D,以及给瘦客户端用的 RPC 电报(spec)。嵌入式场景通常用前两种。

入门用法——建引擎、建表、插入、查询:

try (SqlEngine engine = SqlEngine.builder(new File("/data/mydb")).build()) {
    SqlQuery sql = engine.sql();
    sql.executeDdl("CREATE TABLE orders (id BIGINT PRIMARY KEY, customer VARCHAR(64), amount DECIMAL(18,2))");
    sql.executeInsert("INSERT INTO orders (id, customer, amount) VALUES (1, 'Alice', 12.50)");
    Object[] one = sql.one("SELECT customer FROM orders WHERE id = 1");
    var rows = sql.list("SELECT id, amount FROM orders WHERE amount > 1000");
} // close() 自动 flush 落盘 + 关 reader/writer 池

SqlEngine.builder(dir).build() 一次接好元数据、存储和查询门面,AutoCloseable 会在关闭时自动 flush 落盘;Builder 还提供事务、索引、分表、历史、方言、只读等链式开关。

批量写入或反复变参的查询建议走预编译,一次解析优化、后续只绑参执行:

PreparedSqlQuery pq = sql.prepare("SELECT id FROM orders WHERE amount > ? AND status = ? LIMIT ?");
var r1 = pq.list(5000L, "PAID", 10L);
var r2 = pq.list(8000L, "PAID", 20L); // 零 plan 开销

PreparedInsertSqlQuery ins = sql.prepareInsert("INSERT INTO orders (id, customer, amount) VALUES (?, ?, ?)");
ins.executeBatch(List.of(new Object[]{1L, "A", 10.0}, new Object[]{2L, "B", 20.0}));

不想拼 SQL 字符串的话,可以用 Fluent 门面直接建表、查询:

Db db = engine.db();
db.createTable("orders").column("id", Db.Type.BIGINT).pk()
  .column("customer", Db.Type.VARCHAR, 64).column("amount", Db.Type.DECIMAL, 18, 2).execute();

var r = db.select(col("o.id"), col("c.name"), sum(col("o.amount")).as("total"))
    .from("orders", "o")
    .join("customers", "c").on(eq(col("o.cust_id"), col("c.id")))
    .where(gt("o.amount", 0L))
    .groupBy(col("o.id"), col("c.name"))
    .having(gt(col("total"), val(1000)))
    .orderBy(desc("total")).limit(20).list();

结果集较大、不想一次性缓冲在内存里时,用拉取式游标逐行消费,EOF 会自动 close:

try (Cursor c = sql.cursor("SELECT id, amount FROM orders WHERE amount > 100")) {
    Object[] row;
    while ((row = c.next()) != null) {
        process(row);
    }
}

如果业务逻辑(脱敏、加密、自定义统计)SQL 表达不了,可以写一个带 @Udf 注解的静态方法,直接变成 SQL 函数调用,而且一次能返回多列。例如给手机号加密并同时输出密文和掩码:

@Udf(name = "ENCRYPT",
     type = UdfKind.SCALAR,
     returns = { @Col(name = "cipher", type = UdfType.STRING),
                 @Col(name = "masked", type = UdfType.STRING) })
public static Object encrypt(UdfRow row) {
    String phone = (String) row.value();
    if (phone == null) { return null; }
    return new Object[] {
        aesEncrypt(phone),
        phone.substring(0, 3) + "****" + phone.substring(7)
    };
}

调用方式是 SELECT ENCRYPT(phone) FROM users,一次拿到 cipher、masked 两列。除了单行变换(SCALAR),还有对整组数据做汇总的分组类型(GROUP,例如把一个用户的访问路径拼成一条轨迹)和逐行累加的流式类型(STREAMING,例如同一个方法里顺带算出 min/max/avg),三种类型都以“一个 @Udf 方法”为基本单元。Java UDF 可以在启动期由配置项批量装载;用 CREATE FUNCTION LIBRARY ... USING JAR 在线装卸函数库,官网标注为“独立服务形态”,需要全局 ADMIN 权限。

内存与持久化怎么管

内存:引擎纯 Java 实现、零 native 依赖,官网强调这样“没有 JNI 边界的崩溃风险与失控的堆外内存,不会把宿主 Java 进程拖下水”。查询执行中需要整体驻留的形态(子查询结果、右表缓冲、窗口分区、GROUP_CONCAT、分位数等)如果超出预算,引擎会清晰报错而不是静默 OOM;能溢写的算子先用内存,内存不够时再溢写到本地盘继续跑完。这些行为可以通过 SessionContext 配置,比如设置内存预算:

SessionContext s = SessionContext.defaults()
    .withCastMode(CastMode.NULL_ON_ERROR)
    .withAuditSingleScan(true)
    .withScanObserver(t -> metrics.mark(t))
    .withSpillBudgetBytes(536_870_912L);

持久化:Youngs DB 内置事务写入引擎,跨表原子提交、断电或崩溃重启后自动恢复到一致状态,不会留下“半个事务”。写入的持久化档位有两种:commit() 同步提交,调用返回即代表已安全落盘,断电也不丢,是转账等零容忍场景的适用档位;commitAsync() 是默认档,异步返回更快、吞吐更高,进程被杀零丢失,真正断电时最多丢约 10 毫秒的数据,且以整个事务为单位,不会出现半批写入。此外还提供变更订阅(可订阅已提交的行级变更做增量同步、物化视图或审计)和时间点恢复(周期快照 + 还原到近若干天内任意时刻,整库或单表级)。

sql.transact(txn -> {
    txn.executeUpdate("UPDATE account SET bal = bal - 100 WHERE id = ?", 1);
    txn.executeUpdate("UPDATE account SET bal = bal + 100 WHERE id = ?", 2);
}); // 跨两表原子提交,正常返回自动 commit,抛异常自动回滚

txn.commit();      // 零丢失:返回即已落盘
txn.commitAsync(); // 高吞吐:返回快,进程被杀零丢失,断电最多丢约 10ms

不适合的情况

  • 需要多个客户端共享同一份数据、集中对外提供服务:官网把这一场景划给独立服务(RPC Server)形态,嵌入式模式是单进程内使用,不是为多客户端并发接入设计的。
  • 需要用 SQL 语句在线装卸 UDF 库或在线调参(CREATE FUNCTION LIBRARY、SHOW SETTINGS、SET PERSIST 等):这些语句官网标注为“独立服务形态”,且要求全局 ADMIN 权限;嵌入式场景下 UDF 的装载方式以产品文档为准。
  • 需要 SAVEPOINT、跨会话快照隔离或 Serializable 隔离级别:官网明确把这三项列为“诚实边界”——暂不支持,遇到会报错,而不是静默降级。
  • 数据规模已经明显超出单机能承载的范围、且需要成熟的多节点统一调度:单机内核可以服务化后作为分布式计算节点横向扩展(架构已支持),但 MPP 统一编排官网标注为“持续演进”,不是已经稳定可用的形态,评估时要把这一点考虑进去。

常见问题

Q1:嵌入式模式和独立服务模式用的是同一套引擎吗?
A1:是。按官网说明,嵌入式与独立服务用的是同一套自研引擎内核,SqlQuery、Db+D、RPC 电报三种写法也可以混用;少数语句(如 DELETE … RETURNING、断点续读、账号与访问规则)官网标注为独立服务形态才提供。

Q2:以后数据量涨上去了,嵌入式模式撑不住怎么办?
A2:单机内核可以服务化(RPC)后作为分布式计算节点横向扩展,官网称之为“单点越强,集群越强”;但完整的多节点统一调度(MPP 统一编排)官网标注为“持续演进”,还在完善中,不宜按已经稳定的能力去规划。

Q3:嵌入式实例里能不能既写业务数据又跑分析查询?
A3:可以。引擎内置事务写入能力,支持跨表原子提交、UNIQUE 约束与联合索引、MySQL 和 PostgreSQL 两种 UPSERT 写法,官网把这个定位概括为“一库承载交易 + 分析负载”。

Q4:内存不够会不会把宿主 Java 应用一起拖垮?
A4:引擎是纯 Java 实现、零 native 依赖,官网强调不存在 JNI 边界崩溃和失控的堆外内存问题;查询中需要整体驻留的算子超出内存预算时会清晰报错,能溢写的算子会先溢写到本地盘继续执行,而不是静默把进程打爆。

本文所述能力以云策数据官网与产品文档为准。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。