版本发布记录¶
0.1.13¶
新功能
- 细节层次(LOD)聚合。 聚合现在可以在查询分组以外的粒度上计算。字段可以钉住
一个固定粒度,比如每个用户的
COUNT(DISTINCT event_date),它本身就成了一根可以 分组的轴,"活跃天数正好是 N 天的用户有多少"于是是一次查询。指标则相对查询自身的 分组钉住include、exclude或fixed:按渠道看人均消费,或者算一个分母不受 任何筛选影响的占比。参见 D-LOD。 - 两张事实表对齐到同一个细节层次。 当两张事实表各有自己的固定粒度字段——用户 会话了多少天、下单了多少天——它们之间的一致性配对 (D-CONFORM)会把两者变成同一根轴,任一侧的 指标都能按它分组。
- 细节层次可以取另一个数据集的值。 固定粒度字段的 base 现在可以聚合相关联的
数据集,比如数每个航班未关闭的告警,前提是键经声明过的多对一关系或一致性配对
对应上。另一边没有行时计数为 0,所以在
where里写> 0、= 0就是「有」 「没有」。参见跨数据集的 D-LOD。 - 细节层次可以带自己的时间窗。 固定粒度字段的 base 是带参数的筛选指标时,查询
的
params会绑定到它上面。于是「1 月活跃、2 月没登录的玩家」是一次查询:模型把 时间窗声明成参数,查询给出具体日期。参见 细节层次字段的 base。 - 明细查询能读细节层次。
dosi select可以投影、筛选和排序--from数据集 上的固定粒度字段,--param绑定这个字段的时间窗。明细查询还新增了--distinct和--context-filter,后者像时间范围一样约束汇总。参见 固定粒度字段。
增强
- DATUS 扩展版本升到 1.11。声明旧版本的模型照常加载。
string参数可以不列allowed,不设取值域,适用于按列的存储格式书写的日期、 模型无法穷举的编码。这样的参数编译时给出datus_param_unbounded警告,绑定时 仍然是带引号的字面量。参见参数化指标。- 固定粒度汇总算出的每个值都来自筛选指标时(比如带自己时间窗的字段),筛选条件
现在也会写进汇总的
WHERE,仓库可以按分区裁剪,不必扫整张表。结果不变。 - 按指标调用
list_dimensions时,指标自己的时间列现在只以metric_time出现一次, 不再和它并列。其他时间列照常列出,这一列也仍然可以写进group_by。
缺陷修复
- 上游 Ossie 校验器根本没跑起来时(例如它依赖的 Python 库缺失),
dosi validate --osi-basic会把模型报成不合规。凡是让校验器跑不起来的情况都 只是一条提示,不是结论;装了uv时,校验器现在会自己装好依赖。 - 字段或指标表达式里的
ROUND在 PostgreSQL、MySQL、TiDB 和 ClickHouse 上按 “四舍六入五成双”取整:ROUND(0.5)在这几个仓库上是 0,在其他仓库上是 1, 分箱维度里恰好落在 .5 的行会被分到另一个桶。现在所有仓库都是四舍五入。 - 模型表达式里手写的
DATE_TRUNC('MONTH', ...)在 MySQL 和 TiDB 上会报错,因为 它们没有这个函数。现在会像查询自身的时间粒度一样,改写成它们支持的形式。 - 在 ClickHouse 上,以文本存储的时间维度只要有一个值是 NULL,整个查询就会失败。 现在 NULL 值会归入 NULL 分组,与其他仓库一致。
- 按指标调用
list_dimensions时,D-CONFORM 配对的列被当成外键隐藏,一致性维度还按每种拼写各列一次。现在配对列和其他字段 一样判定,并且只列一次,用指标这一侧的拼写。 - 计数指标作为带窗口成员的组合的成员时,对它所在事实没有行的分组读出的是 0
而不是 NULL,于是
(… ) / store_count这样的加权得分变成了0 / 0—— 在 DuckDB 上是 NaN,在 PostgreSQL 上直接报错。只有被选中的计数本身才填 0 (S-FAN-6);现在在窗口阶段之下,表达式里的计数同样 保持 NULL。
行为变更
- 指标查询或明细查询里出现该类型没有定义的键时,现在会以
unknown_query_key拒绝,并列出合法的键。以前这个键会被悄悄忽略,所以拼错的context_filter, 或者把where_sql写成where,返回的都是没有筛选过的数字。
已知问题
- 分子或分母带运算的除法,比如
(a + b) / c或a / NULLIF(b, 0),仍按数仓自己的/计算:PostgreSQL、Trino、Redshift 对整数做截断除法,MySQL 和 TiDB 只保留 4 位 小数。只有SUM(a) / SUM(b)这种写法会自动转成浮点除法,其他写法请在分子上写CAST(... AS DOUBLE)。 - 0.1.13 仍然只能读取旧的文档格式,也就是
semantic_model:列表。见下方 0.1.11 的 说明。
0.1.12¶
新功能
- 排名计分卡。 窗口指标现在可以对比率或组合指标排名。用
frame.scope: "partition"可以数出整个分区有多少行,也就是排名旁边的那个 N。 窗口最多可以叠三层,比如先在品牌内给市场排名,再在市场内给得分加权。order.nulls固定 NULL 排在前面还是后面,不指定时各数仓的默认顺序不一样。参见 D-WINDOW。 - 按指标过滤。
where_sql现在可以写已选指标的条件(revenue > 1000),它 过滤的是结果行,相当于 SQL 的HAVING。新增的context_filter(CLI--context-filter、REST、MCP 和 Python)始终过滤输入行,要在一个子集内部排名时 用它。参见过滤条件。 - 指标怎么组成、查询必须按什么分组。 CLI、REST、MCP
describe_metric和 Python 返回的指标目录新增两个字段。derive_expr给出组合指标的公式。required_dimensions列出查询必须分组的字段,缺了它们,窗口算出来的就不是定义里 的那个口径。
增强
- 组合指标的成员在同一张表上用了不同的时间列,以前会报
MetricTimeConflict。 现在每个时间列各走一个分支,每个指标的结果都和单独查询时一样。参见 D-TIME。 - Oracle:缺少 Instant Client 或版本不兼容时,现在立即报
DPI-1047并附上安装 指南的链接,不再等 30 秒连接池超时。Oracle 连接器文档 按安装和排障重写了。 - DATUS 扩展版本升到 1.9。声明旧版本的模型照常加载。
缺陷修复
- 窗口的分区会随查询里的其他指标变化。比如加上一个累计指标后,另一个指标的每日 排名变成了跨所有日期排名。
- 维度表上的一个度量在同一个窗口查询里落到两张事实表上时,DuckDB 读到的是另一张 事实表的数,StarRocks 则直接报错。
dosi lineage view的图例现在和图里的边画法一致。
行为变更
- 在窗口查询里,
where_sql中只涉及分组字段的条件,现在过滤的是结果,而不是参与 排名的行。留下的行保留的是全量数据下的排名和分区计数。想得到 0.1.11 的结果,把 条件改写到context_filter里。 - 窗口的
partition.exclude列了一个查询没有分组的字段,现在会报window_exclude_not_grouped。以前每一行都在只有自己的分区里排第一。把这个字段加进group_by即可,required_dimensions会列出查询需要哪些字段。 - 维度计数和事实表度量放在一起时,比如"每家门店的维修数"里的
COUNT(DISTINCT stores.store_id),现在数的是全部门店,而不只是有维修记录的门店, 比率的值会变。如果只想数事实表里出现过的实体,改为数事实表上的键:COUNT(DISTINCT repairs.store_id)。参见 扇出保护。
已知问题
- 分子或分母带运算的除法,比如
(a + b) / c或a / NULLIF(b, 0),按数仓自己的/计算:PostgreSQL、Trino、Redshift 对整数做截断除法,MySQL 和 TiDB 只保留 4 位 小数。只有SUM(a) / SUM(b)这种写法会自动转成浮点除法。在这一点改变之前,请在 分子上写CAST(... AS DOUBLE)。 - 0.1.12 仍然只能读取旧的文档格式,也就是
semantic_model:列表。见下方 0.1.11 的 说明。
0.1.11¶
新功能
- 每个指标的推荐维度。
dosi list dimensions --metric只列出适合按该指标分组的 字段,推荐的排在前面。REST API、MCP 工具、PythonEngine.dimensions(metric=)和血缘图 返回的是同一份列表。Dosi 会排除键、join 列和被指标聚合的列;字段可以用is_dimension覆盖这一判断(D-DIM):false隐藏 ID 或自由文本列,true纳入数值列。这份列表只是推荐:--group-by仍然接受任何可达字段,生成的 SQL 也不变。dosi validate会提示缺少声明或与模型矛盾的字段;加--strict则把提示变成 错误。 - 跨两张事实表的比率。 两张事实表共享日期等列、但谁也不从属于谁(比如登录和付费),
现在可以用
cardinality: many_to_many配对(D-CONFORM)。 "付费人数 / 活跃人数"这样的指标随后可以按共享列分组和过滤,Dosi 不会把两张表直接 join。 dosi lineage。dosi lineage view在浏览器里打开指标血缘图,派生指标按构建 顺序从左到右排开;dosi lineage dump把图打印成 JSON。参见血缘。- Ontology(实验性)。
--ontology加载 Apache Ossie ontology,可以带核心模型,也可以 单独加载。可以按它的概念查询,用dosi describe和dosi paths浏览,也能在血缘图上 看到它们。参数和输出仍可能变化。
增强
- 归因现在必须指定
dimensions。不指定时,它在查询数仓之前停下,给出该指标推荐的维度, 可直接粘贴。参见维度怎么选。 - DATUS 扩展版本升到 1.8。声明旧版本的模型照常加载。
缺陷修复
- StarRocks 的 Arrow Flight 读取每次都失败。在 StarRocks 4.0.14 上还需要设置
arrow_flight_proxy_enabled = false。参见 Arrow 原生结果。
已知问题
- 本版本发布后,上游 Ossie 改了文档格式:一份文档只放一个模型,
name和datasets直接写在顶层,不再放在semantic_model:列表里。0.1.11 无法加载新格式,之后的版本会 两种都支持。使用--osi-basic时,请用dosi validate中给出的 提交版本的上游校验器;上游main会拒绝 0.1.11 接受的所有模型。
0.1.10¶
新功能
- 明细查询。
dosi select返回明细行,而不是聚合后的指标,比如 "Enterprise 客户最大的 100 笔订单"。你只管点名要哪些字段,连接由 Dosi 算 出来;会导致结果重复的连接,它宁可拒绝也不把重复的行交给你。参见 明细查询。 - 存成字符串或数字的时间列。 时间列不再必须是真正的
DATE。声明这一列 实际存的是什么(20240131、2024-01、2024年01月31日),Dosi 就能正确 分组和过滤,且不丢失分区裁剪。查询写法不变:始终写2024-01-31。参见 D-FORMAT。 - 组合指标可以基于另一个组合指标。 一个公式只写一次、可以复用,不必在每个 用到它的指标里重写一遍——而重写时抄歪了,以前是照样编译通过的。
增强
- 用了 OSI 标准
datatype属性的模型现在可以加载,Apache Ossie 的 TPC-DS 参考模型也在其中。 --order指定的是一个指标,或者你 group by 的某个字段,不必去对上引擎生成 的列名。
缺陷修复
- 参数取值是中文(或任何非 ASCII 文本)时,每个值生成的列名都一样;一次绑定 多个值还会让查询直接失败。
- 存成整数的时间列在 MySQL、TiDB、ClickHouse 上,上卷到月或年会失败。
0.1.9¶
Dosi 现在采用 Elastic License 2.0:可以自由使用和再分发,只是不能作为托管 服务转售。它取代了 0.1.5 引入的专有许可——那份许可在没有另行协议时不授予任何 权利。
新功能
- BigQuery 可以执行查询。 此前它只能编译:Dosi 生成 SQL,但拒绝执行。现在 可以执行,并在真实项目上跑通了完整测试语料。参见 BigQuery。
- 华为云 DWS 成为受支持的数仓。它的兼容模式(
ora、td、mysql)会影响 生成的 SQL,所以 Dosi 会从数据库读取模式,并拒绝执行为另一种模式编译的查询。 参见华为云 DWS。 - 指标血缘(仅 Python)——
Engine.lineage()返回指标背后的关系图:表 → 数据集 → 指标 → 派生指标。图要交给信任边界之外时,传redact_sql=True。 - 建模契约(仅 Python)——
render_datus_authoring_spec()返回本引擎实际 执行的建模规则并附摘要,生成模型的工具可以据此确认自己依据的是同一份规则。 - 从镜像安装。
install.sh新增DOSI_SOURCE=github|oss|cloudflare。中国 大陆请用DOSI_SOURCE=oss:从 GitHub 下载只有几十 KB/s,还经常卡死。两种 来源都会校验归档包的校验和。本版本没有填充 Cloudflare 镜像。
增强
install.sh可以装在 macOS 上,此前它对任何非 Linux 主机一律拒绝。- 校验会返回每个指标最终编译成了什么;Python 的连接配置可以直接在内存里传, 不再触发明文密钥告警——那条告警本来只对磁盘上的连接文件才有意义。
- 新增 BigQuery 和华为云 DWS
两页文档,以及一个 20 万行的示例数据库
https://dosi.datus.ai/orders-200k.duckdb。
缺陷修复
- 宽度为 1 个周期的滚动窗口,或
preceding边界为 0,会生成 Doris 和 StarRocks 直接拒绝的 SQL,于是--param n=1,3,6这样普通的查询在这两个引擎 上失败。
0.1.8¶
这一版没有发布 wheel,所以 dosi-engine 用户从 0.1.7 直接到 0.1.9,那一版
包含这里的全部内容。二进制只发布了 Linux x86_64、Linux aarch64 和 Apple
Silicon 三个目标——Intel Mac 请装 0.1.9。
新功能
- 归因:这个指标为什么变了。 给 Dosi 一个指标、要看的维度和两个时间窗口, 它自己把查询跑完,返回按贡献排序的分解结果,每个分段都附带下一步下钻可直接 用的过滤条件。用哪种方法由指标自身的代数结构决定;分解不了的指标会返回 结构化的"不支持"并说明原因,而不是给一个错的数。参见 解释指标变化。
- 参数化指标。 指标的窗口宽度、偏移、排名分桶、过滤取值,都可以是查询时
参数:一个
moving_avg(n)顶掉r7/r30/r90,一次查询还能同时要多个 取值,一个取值一列。参见参数化指标。
增强
dosi list metrics会说明一个指标能不能做归因、用哪种方法,不必真跑一次分析 就能先确认。- 一次查询可以带多个具名时间窗口,由一条语句一次返回。
行为变化
- 如果你在用 0.1.7 wheel 的
Engine.attribute():分母不为正的分段,占比字段 现在可能不存在,无条件读取这两个字段的代码需要处理这种情况。
0.1.7¶
这一版是拆开发的:二进制和 wheel 相隔三天、由不同提交构建,所以 wheel 的 内容更多。
新功能
- 多了一个更小的下载包 ——
dosi-<version>-<target>-lean.tar.gz只含两个 可执行文件。它照样能编译查询、连上所有数仓;本地 DuckDB 的执行交给 PATH 上 的duckdbCLI。 - 派生指标(D-DERIVE)M2 —— 窗口可以建在派生指标之上,组合也可以包含窗口 成员。
- SQLite 文件可以通过 DuckDB 读取。
- 错误码参考,含每种拒绝的含义清单。
- 归因分析首个版本(仅 wheel)——
Engine.attribute()。0.1.8 在此之上做了 扩展,升级前请先看上面那条行为变化。
增强
- DuckDB 每个进程的启动快了约 200 ms:一次性的
dosi query --execute从 249 ms CPU 降到 41 ms。查询本身的速度不变,省下的是启动开销。
缺陷修复
- Redshift 真的按 Redshift 渲染了。 此前它落到通用生成器上,产出的是 Postgres SQL。
- wheel 在 cargo 1.93 及更高版本下能构建。
0.1.6¶
仅 wheel —— dosi 和 dosi-server 用户从 0.1.5 直接到 0.1.7。
新功能
- 新增 Linux aarch64 的 wheel,Graviton 和 arm64 容器不必再从源码构建。
- SQLite 文件可以通过 DuckDB 读取,本地
.sqlite文件因此成了可用的连接, 适合测试和小模型。 - 导出
CONNECTION_TYPES,调用方可以直接列出某个 wheel 构建时带上了哪些数仓。
0.1.5¶
Dosi 的首个公开版本。 从这一版起,项目只以二进制和 wheel 的形式发布,不再
发布源码归档。安装:curl -fsSL https://dosi.datus.ai/install.sh | sh 拿到
dosi 和 dosi-server 可执行文件,pip install dosi-engine 拿到 Python
绑定。
它做什么:加载 OSI 语义模型、校验、把指标查询编译成你所用数仓的 SQL,然后执行。
十五个数仓 —— DuckDB · StarRocks · ClickHouse · Doris · TiDB · Trino ·
Postgres · MySQL · Snowflake · BigQuery · Databricks · Redshift · Hologres ·
GaussDB · Oracle。四种入口:dosi CLI、REST、MCP、Python wheel。两种模式:
--osi-datus 遵循 Datus 扩展,--osi-basic 是严格的标准 OSI。
0.1.5 之前的版本从未发布。