DEBUG.WIKI
PanstarCloud:部署应用,接入 AI,云服务器与 AI 网关
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
搬瓦工;先看线路,再选 VPS;CN2 GIA · 对应线路套餐;查看线路 →

jOOQ 生成的 DuckDB 索引带 WHERE,执行时报不支持部分索引

jOOQ 3.21.9 会渲染索引条件,DuckDB 1.5.0 却明确拒绝部分索引。核对目标方言与实际 DDL,不把普通索引或全表唯一性当作同语义替换,也不以关闭问题推断修复已发布。

用 jOOQ 为 DuckDB 生成索引,DDL 中带了 WHERE 条件,执行时却被数据库拒绝。先核对目标数据库是否支持部分索引,不能因为 DSL 允许调用 .where(...),就认为当前方言会提供同样的能力。

部分索引只覆盖符合条件的行。jOOQ 3.21.9 的索引构造会在存在条件时直接渲染 WHERE;正式 DuckDB 1.5.0 的解析器遇到该条件会抛出:

Creating partial indexes is not supported currently

其他 DuckDB 版本应核对实际能力与错误,不能仅凭主版本号不同就推断已经支持。这与数据库文件被其他进程占用、索引名冲突或缺少建表权限是不同问题。

看最终 DDL,不只看 Java 方法能否编译

下面展示一个部分索引的形状,假定已有 events 表、event_id 列和布尔列 active:

CREATE INDEX idx_active_events ON events (event_id) WHERE active;

这是用于识别生成结果的示例,不应直接在业务数据库执行。还要核对 jOOQ 配置的 SQLDialect 与真正连接的数据库,避免生成时按 PostgreSQL、运行时却交给 DuckDB。

在多数据库迁移里,应按目标能力分别组织 DDL。一个数据库接受这条语句,不能代替另一个数据库的能力检查;给语句加 IF NOT EXISTS 也不会让不支持的 WHERE 变成合法语法。

普通索引与部分索引不是等价替换

如果原索引只用于查询加速,可以根据实际查询负载评估 DuckDB 支持的普通索引或其他查询组织方式。移除 WHERE 会使索引覆盖的行增加,存储、构建及写入成本随之改变;性能是否改善需要由项目自己的验证判断,不能给出固定收益。

若原来是 CREATE UNIQUE INDEX ... WHERE ...,更不能机械删除 WHERE。部分唯一性只约束条件内的行,全表唯一性会改变业务规则,已有条件外的重复值也可能使建索引失败。

此时要重新设计符合目标数据库能力的约束方案,并验证并发写入下是否仍能保证业务要求。只在应用插入前 SELECT 一次,并不能自动获得与数据库唯一约束相同的并发保证。

也不要忽略执行错误,仍把迁移标记为完成。索引没有建立与建立了普通索引是两种不同状态,部署记录必须与实际 schema 一致。

jOOQ 的方言修正不会扩展数据库能力

相关处理已安排到 jOOQ 的后续版本与维护分支,但 3.21.9 的正式代码仍会渲染所给条件。采用其他版本时,应检查正式发行工件及实际渲染结果,不能仅根据已关闭的问题或维护版计划认定当前安装包已变化。

即使生成器以后能更早拒绝或识别这种组合,也不会让数据库突然支持部分索引。迁移需要的是符合目标能力、语义明确的 DDL,而不是只把报错发生的位置前移。

修改前保存原迁移和目标 schema,在数据库副本上核对生成语句、执行结果及实际索引定义。涉及唯一性时,还应覆盖条件内外的重复数据和更新条件字段的情况;回退 DDL 或应用版本并不自动撤销已经提交的业务写入。