Apache Druid Calcite SQL 测试数据源入门指南从 ingestion spec 到查询验证【免费下载链接】druidApache Druid: a high performance real-time analytics database.项目地址: https://gitcode.com/gh_mirrors/druid6/druid本指南围绕 sql/src/test/resources/calcite/tests/README.md 展开系统讲解 Apache Druid SQL 引擎基于 Apache Calcite单元测试所使用的测试数据体系calcite/tests目录下各数据源的 ingestion specfoo.json、foo2.json、foo4.json、numFoo.json、lookyloo.json与window/*.sqlTest查询验证用例。读完本文你将掌握这些测试数据集的字段结构、数据内容、维度/度量类型差异理解“spec 仅供参考、真相在CalciteTests”的权威性约定并能据此独立构造或校验一条 SQL 查询的预期结果。一、为什么需要一套“可读”的测试数据Druid 的 SQL 层以 CalciteTests.java 为中枢在内存中搭建起一个完整的查询框架SpecificSegmentsQuerySegmentWalker负责把 SQL 规划后的原生查询路由到虚拟 segment 上配合QueryRunnerFactoryConglomerate、JoinableFactoryWrapper、DruidOperatorTable等组件实现了不依赖真实集群的 SQL 单测环境见 CalciteTests.java 的createMockWalker系列方法与QueryStackTests构建的INJECTOR。问题在于这些 datasource 的实际数据是在 Java 测试代码里以编程方式构建的对阅读测试用例、调试 SQL 行为的人来说并不直观。因此sql/src/test/resources/calcite/tests/目录提供了一份可读的 ingestion spec 快照其作用正如 README 所言The purpose of these files is to make it easier to look at and manipulate the data under test so that you can easily validate if the results of the SQL query written are as expected.也就是说这套 spec 是为了让你能“对着数据手算 SQL 结果”从而快速验证自己编写的查询是否符合预期。例如在 simpleSum.sqlTest 中一条窗口函数查询的expectedResults就是逐行手写的 6 行结果必须与底层数据严格对应。二、权威性约定spec 与代码的同步关系README 给出了一条极其重要的边界NOTE: The provided specs are not guaranteed to be in sync with the datasources used by the test. The source of truth isorg.apache.druid.sql.calcite.util.CalciteTests.翻译过来就是两层含义spec 是辅助阅读材料tests/*.json中的数据结构字段、类型、行数大体反映测试数据但可能滞后或简化代码是唯一真相任何以测试结果为准的论断都必须回到 CalciteTests.java 与TestDataBuilder中的实际构建逻辑核对不能拿 json 里的数据与测试输出对不上时去“修 json”。从源码可以印证这一点datasource 名称常量定义在 CalciteTests.java包括fooDATASOURCE1、foo2DATASOURCE2、numfooDATASOURCE3、foo4DATASOURCE4、lotsocolumns、arrays、broadcast、wikipedia等。其中numfoo与资源文件名numFoo.json大小写不同也印证了“json 文件名/内容并不总是与代码常量完全一致”阅读时需以代码为准。三、五大测试数据源 ingestion spec 详解calcite/tests目录下共 5 份数据文件全部使用index_parallel任务类型 inline输入源无需外部文件即可重建数据。下面逐一拆解。3.1 foo.json —— 最基础的维度和度量数据集foo.json 定义了foo数据源覆盖 2000 与 2001 两个自然年共 6 行数据时间m1m2dim1dim2dim32000-01-011.01.0[a][a, b]2000-01-022.02.010.1[][b, c]2000-01-033.03.02[][d]2001-01-014.04.01[a][]2001-01-025.05.0def[abc][]2001-01-036.06.0abc——关键 schema 设计时间timestampSpec使用column: t、format: auto自动识别2000-01-01格式granularitySpec为uniformqueryGranularity: NONEsegmentGranularity: YEARrollup: false即每个自然年一个 segment、不做聚合、查询粒度保持原样维度dim1为普通字符串维度含数字字符串如10.1、2、1用于测试字符串/数字转换语义dim2、dim3是多值维度JSON 数组其中dim2覆盖空数组[]与空串[]dim3覆盖[]、[]等边界情况度量m1为floatSum、m2为doubleSum各 6 行取值 1.06.0方便心算 SUM/AVG。这个数据集几乎是所有 SQL 功能测试的“通用底料”GROUP BY、多值维度展开UNNEST、字符串比较、时间截断等场景都基于它。3.2 foo2.json —— 多语言多字节字符与 long 度量foo2.json 只有 3 行全部落在2000-01-01其核心价值在于非 ASCII 文本时间dim1dim2m12000-01-01דרואיד希伯来语he1.02000-01-01druiden1.02000-01-01друид西里尔字母ru1.0与 foo 不同它的度量m1是longSum维度只有dim1、dim2两个字符串维度segmentGranularity同样为YEAR。该数据集用于验证 Druid 在 SQL 层对 UTF-8 多语言字符串的过滤、排序、聚合是否正确例如WHERE dim1 דרואיד这类查询。3.3 foo4.json —— 带 rollup 与 HOUR 粒度的数据集foo4.json 是唯一开启rollup 聚合的 spec用于测试“预聚合后查询”的语义时间戳格式为iso2000-01-01T10:51:45.695Z仅 2 行输入queryGranularity: HOUR、rollup: true、segmentGranularity: YEAR维度只剩dim2、dim3注意没有 dim1度量m1floatSum、m2doubleSum。由于 rollup 开启原始两行若在 HOUR 桶内维度相同会被合并并累加度量值。阅读该 spec 时应意识到spec 中的输入行 ≠ 查询可见行真正可见的是 rollup 之后的聚合结果这再次呼应“以CalciteTests实际构建的数据为准”。3.4 numFoo.json —— 数值类型最全的数据集numFoo.json 定义了numFoo代码常量DATASOURCE3 numfoo数据源6 行数据覆盖 2000/2001 两年其最大特点是显式类型维度数值维度d1、d2double、f1、f2float、l1、l2long且第二行同时带出d2/f2/l2而其余行只有d1/f1/l1制造了大量NULL数值用于测试数值空值语义字符串维度dim1含10.1、2、def、abc等、dim2多值、dim3多值、dim4a/b、dim5aa/ab/ba/ad度量m1floatSum、m2doubleSum。在dimensionsSpec中数值维度以{type: double/float/long, name: ...}对象形式声明而字符串维度直接写名字字符串这是 Druid ingestion spec 中“类型化维度 vs 默认 string 维度”的典型写法也是测试 SQL 数值函数CAST、比较、四则运算的主力数据。3.5 lookyloo.json —— 不是数据源而是一行 lookup 数据lookyloo.json 与其余 4 份截然不同它只有 4 个键值对a/xa、abc/xabc、nosuchkey/mysteryvalue、6/x6不是 ingestion spec。对应代码中的LookylooModule见 CalciteTests.java 中INJECTOR注册的模块为测试提供一张小型 key-value 查找表用于验证 Druid SQL 中 LOOKUP 函数如LOOKUP(col, lookyloo)的映射行为包括缺失键、数字字符串键等边界。四、window/*.sqlTest查询验证用例的结构calcite/tests/window/下 25 个.sqlTest文件是 SQL 查询的“三件套”验证格式以 simpleSum.sqlTest 为例type: operatorValidation sql: | SELECT FLOOR(__time TO DAY) t, SUM(cnt) c, SUM(SUM(cnt)) OVER (ORDER BY FLOOR(__time TO DAY)) cc FROM foo GROUP BY FLOOR(__time TO DAY) expectedOperators: - { type: naivePartition, partitionColumns: [ ] } - type: window processor: type: framedAgg frame: type: groups upperOffset: 0 orderByColumns: [ d0 ] aggregations: - { type: longSum, name: w0, fieldName: a0 } expectedResults: - [ 946684800000, 1, 1 ] - [ 946771200000, 1, 2 ] - [ 946857600000, 1, 3 ] - [ 978307200000, 1, 4 ] - [ 978393600000, 1, 5 ] - [ 978480000000, 1, 6 ]三个字段的含义sql待验证的 SQL 语句本文件测试SUM(...) OVER (ORDER BY ...)累积求和窗口函数expectedOperatorsSQL 规划后应产生的原生算子链如naivePartition→window/framedAgg用于验证规划器选择了预期执行路径而非仅验证结果正确expectedResults逐行预期结果时间戳以毫秒表示946684800000即 2000-01-01 UTC验证输出严格有序。其他.sqlTest文件覆盖了窗口函数的丰富分支WindowOpReorder算子重排、aggregateConstant常量聚合、allBoundsCombinationROWS/RANGE 边界组合、defaultBoundCurrentRow、duplicateAggregation重复聚合去重、first_last_rewriteFIRST/LAST 重写、lead_lag、no_grouping无 GROUP BY 的窗口、offsetNotDiscarded、orderByDescNulls降序 NULL 排序、range_handling、rank_handling、virtualColumns、wikipediaAggregationsMultipleOrdering系列、wikipediaCumulativeOrdered、wikipediaFramedAggregations、wikipediaScanWindow、wikipediaSimplePartition、windowInsideSubquery、windowed_long_null等。从命名可见wikipedia*系列使用wikipedia数据源常量WIKIPEDIA见 CalciteTests.java用于验证带累计排序、多排序键、NULL 值等真实场景的窗口计算simpleSum等则回归到foo数据源做最小化验证。五、实战如何利用这套测试数据验证你的 SQL结合 README 的目的说明与目录结构推荐的验证流程如下读数据心算结果打开calcite/tests/foo.json等 spec理解字段类型与 6 行数据内容对多值维度、rollup 数据源foo4务必结合CalciteTests的构建逻辑确认最终可见行写查询估算子参照window/*.sqlTest的格式先手工推导expectedResults再推测规划器应产出的expectedOperators算子链与权威对齐将你的推导与 simpleSum.sqlTest 等既有用例的expectedResults对比——若对不上优先回到 CalciteTests.java 与TestDataBuilder核对真实数据而不是怀疑 spec运行测试确认在仓库根目录执行对应模块的测试类如sql模块下继承BaseCalciteQueryTest的用例观察算子链与结果是否与预期一致。六、小结sql/src/test/resources/calcite/tests/目录是 Druid Calcite SQL 测试的“数据速查手册”5 份数据文件覆盖了基础维度/度量foo、多语言文本与 long 度量foo2、rollup 与 HOUR 粒度foo4、类型化数值维度numFoo以及 lookup 映射表lookyloo五大测试场景25 个.sqlTest窗口用例示范了“SQL 算子 结果”三位一体的验证格式权威性铁律任何数据细节以 CalciteTests.java 及其TestDataBuilder为准spec 只是便于阅读和手工验证的辅助快照。掌握这套数据后你可以在不搭建集群的前提下仅凭“看数据 → 写 SQL → 手算结果 → 对照算子”的闭环快速定位 Druid SQL 行为窗口函数、多值维度、类型转换、LOOKUP、NULL 语义的正确与否这也是 Druid 自身 SQL 引擎每天执行上千次单测所依赖的方法论。【免费下载链接】druidApache Druid: a high performance real-time analytics database.项目地址: https://gitcode.com/gh_mirrors/druid6/druid创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考