Apache Druid NULL 值处理实战指南:SQL 兼容模式下的字符串与数值列查询
数据库OLAP大数据后端【免费下载链接】druidApache Druid: a high performance real-time analytics database.项目地址https://gitcode.com/gh_mirrors/druid6/druid点击查看免费下载本文是一份面向 Druid 用户的 NULL 值处理实操教程。文章围绕 Apache Druid 默认的 ANSI SQL 兼容 NULL 语义通过一份同时包含空字符串、字符串 NULL、数值 NULL 的样例数据逐步演示字符串列过滤、数值列比较、聚合计数与摄入期ingestion time过滤中的 NULL 行为差异并深入仓库源码级实现说明 NULL 在段segment内如何存储、三个相关运行时配置如何控制三值逻辑以及从旧版默认值模式迁移到 SQL 兼容模式的三种改造路径。读完本文你将掌握在 Druid SQL 中正确编写 NULL 相关过滤、计数与算术表达式的能力避免NULL 不计入结果、NULL 不等于 0这类典型陷阱。前置条件开始本教程前请先按 Local quickstart 在本地下载并运行 Apache Druid。教程假设你已经熟悉使用 Query view 来摄取和查询数据并且没有修改任何与 NULL 处理相关的默认配置即保持druid.generic.useDefaultValueForNullfalse、druid.expressions.useStrictBooleanstrue、druid.generic.useThreeValueLogicForNativeFilterstrue的默认状态。加载包含 NULL 值的示例数据样例数据同时包含字符串列与数值列的 NULL 值{date: 1/1/2024 1:02:00,title: example_1,string_value: some_value,numeric_value: 1} {date: 1/1/2024 1:03:00,title: example_2,string_value: another_value,numeric_value: 2} {date: 1/1/2024 1:04:00,title: example_3,string_value: , numeric_value: null} {date: 1/1/2024 1:05:00,title: example_4,string_value: null, numeric_value: null}注意四行数据的差异example_3的string_value是空字符串numeric_value为nullexample_4的string_value与numeric_value均为null。在 Druid 控制台的Query视图中运行下面的 SQL通过 MSQ 任务引擎REPLACE INTO ... OVERWRITE ALL语法把数据写入null_example数据源REPLACE INTO null_example OVERWRITE ALL WITH ext AS ( SELECT * FROM TABLE( EXTERN( {type:inline,data:{\date\: \1/1/2024 1:02:00\,\title\: \example_1\,\string_value\: \some_value\,\numeric_value\: 1}\n{\date\: \1/1/2024 1:03:00\,\title\: \example_2\,\string_value\: \another_value\,\numeric_value\: 2}\n{\date\: \1/1/2024 1:04:00\,\title\: \example_3\,\string_value\: \\, \numeric_value\: null}\n{\date\: \1/1/2024 1:05:00\,\title\: \example_4\,\string_value\: null, \numeric_value\: null}}, {type:json} ) ) EXTEND (date VARCHAR, title VARCHAR, string_value VARCHAR, numeric_value BIGINT) ) SELECT TIME_PARSE(date, d/M/yyyy H:mm:ss) AS __time, title, string_value, numeric_value FROM ext PARTITIONED BY DAY这里用EXTERN定义内联 JSON 输入用EXTEND显式声明列类型numeric_value声明为BIGINT用TIME_PARSE(date, d/M/yyyy H:mm:ss)把原始日期字符串解析为__time时间戳并按天分区。数据加载完成后查询整张表SELECT * FROM null_exampleDruid 返回__timetitlestring_valuenumeric_value2024-01-01T01:02:00.000Zexample_1some_value12024-01-01T01:03:00.000Zexample_2another_value22024-01-01T01:04:00.000Zexample_3emptynull2024-01-01T01:05:00.000Zexample_4nullnull请特别留意example_3的空字符串值与example_4的 NULL 字符串值之间的区别在 SQL 兼容模式下Druid 会分别展示为empty与null两种不同的值。字符串列的 NULL 处理本节的查询演示字符串列上的 NULL 处理方式。下面这条查询过滤掉string_value不等于some_value的行SELECT COUNT(*) FROM null_example WHERE string_value ! some_valueDruid 返回2只统计了another_value和空字符串两行。NULL 值不计入结果——按照 ANSI SQL 的三值逻辑NULL ! some_value的结果是unknown既不成立也不成立因此被过滤掉。这正是 SQL 兼容模式与旧版默认值模式最显著的行为差异旧模式中 NULL 与空字符串等价会被计入。再来看聚合计数的差异。COUNT(*)统计全部行数而COUNT(string_value)只统计该列非 NULL 的行数SELECT string_value, COUNT(*) AS count_all_rows, COUNT(string_value) AS count_values FROM null_example GROUP BY 1Druid 返回string_valuecount_all_rowscount_valuesnull10empty11another_value11some_value11可以看到NULL 行虽然计入COUNT(*)但在COUNT(string_value)中计为 0。同时注意GROUP BY 会把null和空字符串作为两个不同的分组值各自独立成行——这与旧版模式中空串与 NULL 互换的行为完全不同。同时过滤空字符串与 NULL如果你的业务逻辑需要把空字符串和 NULL 等同看待可以在过滤条件中使用 OR 运算符。例如选出所有字符串列为 NULL 或空字符串的行SELECT * FROM null_example WHERE string_value IS NULL OR string_value Druid 返回__timetitlestring_valuenumeric_value2024-01-01T01:04:00.000Zexample_3emptynull2024-01-01T01:05:00.000Zexample_4nullnull再举一个例子如果不想统计空字符串可以用FILTER子句把空串排除掉SELECT COUNT(string_value) FILTER(WHERE string_value ) FROM null_exampleDruid 返回2。空字符串和 NULL 都被排除NULL 同样为unknown只剩some_value与another_value两行被计数。数值列的 NULL 处理Druid不会把 NULL 计入数值比较。例如SELECT COUNT(*) FROM null_example WHERE numeric_value 2Druid 返回1。虽然example_3的数值列在摄取时写入了 NULL但它既不满足 2也不满足 2因此example_3与example_4都被排除只有example_1数值 1命中。此外必须注意NULL 数值不会表现得像 0 一样参与算术运算。例如SELECT numeric_value 1 FROM null_example WHERE __time 2024-01-01 01:04:00.000Z该查询命中的是example_4行其numeric_value为 NULL因此 Druid 返回null而不是 1——按照 ANSI SQL 标准NULL 1的结果仍是 NULL。一种解决方式是使用COALESCE函数对 NULL 做兜底处理SELECT COALESCE(numeric_value, 0) 1 FROM null_example WHERE __time 2024-01-01 01:04:00.000Z这次 Druid 返回1因为COALESCE把 NULL 替换成了 0。COALESCE在 Druid SQL 标量函数中的定义是返回第一个既不是 NULL 也不是空字符串的值是处理数值 NULL 最常用的函数之一。摄入期ingestion time过滤NULL 处理规则同样适用于摄入阶段。SQL 兼容模式下MSQ 的REPLACE INTO ... SELECT中的WHERE子句在写段之前就会按相同语义过滤数据。下面这条查询用带WHERE的 SELECT 替换示例数据REPLACE INTO null_example OVERWRITE ALL WITH ext AS ( SELECT * FROM TABLE( EXTERN( {type:inline,data:{\date\: \1/1/2024 1:02:00\,\title\: \example_1\,\string_value\: \some_value\,\numeric_value\: 1}\n{\date\: \1/1/2024 1:03:00\,\title\: \example_2\,\string_value\: \another_value\,\numeric_value\: 2}\n{\date\: \1/1/2024 1:04:00\,\title\: \example_3\,\string_value\: \\, \numeric_value\: null}\n{\date\: \1/1/2024 1:05:00\,\title\: \example_4\,\string_value\: null, \numeric_value\: null}}, {type:json} ) ) EXTEND (date VARCHAR, title VARCHAR, string_value VARCHAR, numeric_value BIGINT) ) SELECT TIME_PARSE(date, d/M/yyyy H:mm:ss) AS __time, title, string_value, numeric_value FROM ext WHERE string_value ! some_value PARTITIONED BY DAY重跑SELECT * FROM null_example结果只剩两行__timetitlestring_valuenumeric_value2024-01-01T01:03:00.000Zexample_2another_value22024-01-01T01:04:00.000Zexample_3emptynullexample_1some_value被过滤掉example_4字符串为 NULL也因NULL ! some_value为 unknown 而被过滤——在摄入期过滤中NULL 同样不会被当作不等于某值而保留。这意味着如果你在摄入时依赖!过滤做数据清洗需要注意 NULL 行会被一并丢弃。底层原理Druid 如何存储与判断 NULL三值逻辑与三个运行时配置Druid 默认的 NULL 处理对标 ANSI SQL 的三值逻辑true / false / unknown任何与 NULL 的比较、!、等结果都是 unknown既不会命中也不会被!保留。这一行为由三个运行时属性共同控制见 docs/configuration/index.md 与 SQL 数据类型文档配置项作用默认值druid.generic.useDefaultValueForNull设为false时以 SQL 兼容模式存储和查询数据设为true进入已废弃的旧版模式NULL 在字符串列存为、在数值列存为0。该配置已废弃未来版本将固定为false行为falsedruid.expressions.useStrictBooleans控制表达式布尔逻辑模式为true时所有表达式布尔值统一用 1真/ 0假表示truedruid.generic.useThreeValueLogicForNativeFilters控制原生native过滤器是否使用 SQL 兼容的三值逻辑需在useDefaultValueForNullfalse且useStrictBooleanstrue时生效设为false时过滤器回退为两值逻辑。该配置已废弃未来将固定为true行为true这三个配置相互配合只要其中一个被改成非默认值非表达式型过滤器就会回退为两值逻辑表达式型过滤器则单独由useStrictBooleans控制。从 docs/release-info/migr-ansi-sql-null.md 可以看到Druid 28.0.0 起默认即启用以上三个值它们均已标记为 deprecated 并计划在未来版本中移除届时 Druid 将始终采用 SQL 兼容行为。NULL 在段内的存储结构从段存储层面看段设计与 NULL 处理 一节说明默认 SQL 兼容模式下字符串列的 NULL 在值字典dictionary中固定占用 id 0字典首位并配合位图bitmap值索引用于过滤 NULL数值列则维护一张NULL 行位图用于聚合时的 NULL 检查与过滤器对 NULL 值的匹配。这就是COUNT(string_value)能区分 NULL 行、GROUP BY能把null单独分组、数值比较能跳过 NULL 行的物理基础。而在旧版 legacy 模式下druid.generic.useDefaultValueForNulltrueDruid 28.0.0 之前的默认行为摄入时写入的段有以下特征字符串列无法区分与null两者被当作同一个值互换处理数值列无法表示 NULL 行统一存储为0。由于 legacy 模式的数值列没有 NULL 行位图段体积可能略小某些涉及数值列的查询也略微更快无需检查 NULL 位图但代价是丢失了标准 SQL 语义。从旧版模式迁移到 SQL 兼容模式的三种策略如果你的业务逻辑依赖旧版默认值模式的行为可以按以下三种方式之一改造完整示例见 SQL 兼容模式迁移指南策略一摄入时把 NULL 替换为默认值不保留 NULL如果不关心是否保留 NULL可以在摄入 SQL 的 SELECT 中用COALESCE/NVL把字符串 NULL 换成、数值 NULL 换成0使现有查询在 SQL 兼容模式下表现得与旧版一致SELECT TIME_PARSE(time) AS __time, COALESCE(string_example, ) AS string_example, NVL(number_example, 0) AS number_example FROM extNVL的定义是若 value1 非 NULL 则返回 value1否则返回 value2见 docs/querying/sql-scalar.md与COALESCE在二参数场景下等价。策略二摄入时把空字符串转成 NULL依赖 IS NULL 语义如果旧查询依赖col IS NULL命中空串legacy 模式两者等价可在摄入时用NULLIF(string_example, )把空串统一转为 NULL这样IS NULL过滤依然能命中原来的空串数据。策略三保留 NULL改写查询为 ANSI SQL 兼容如果需要保留数据中的 NULL则必须改写客户端查询典型手法包括不等值过滤显式带上 NULLx some_value改写为(x some_value OR x IS NULL)用空值安全比较IS DISTINCT FROM达到包含 NULL的不等判断string_value IS DISTINCT FROM some_value算术运算前用COALESCE/NVL兜底NVL(number_example, 0) 1。扩展阅读Null valuesSQL 数据类型文档Druid 对 NULL 值的完整行为描述包括布尔三值逻辑的三种控制配置。SQL 兼容模式迁移指南从 legacy 模式迁移的详细步骤与完整 SQL / JSON 摄取示例。Handling null values段设计文档NULL 在段内的存储结构字典 id 0、NULL 行位图与 legacy 模式的段特征。Druid SQL 标量函数COALESCE、NVL、NULLIF等 NULL 处理函数的完整定义。赞分享数据库OLAP大数据后端【免费下载链接】druidApache Druid: a high performance real-time analytics database.项目地址https://gitcode.com/gh_mirrors/druid6/druid点击查看免费下载相关推荐Apache Druid SQL 数据类型完全指南标准类型、数组、多值字符串与 NULL 处理Apache Druid SQL 数据类型完全指南标准类型、数组、多值字符串与 NULL 处理 Druid 为每一列关联一个特定的数据类型而 Druid S数据库OLAP大数据后端Apache Druid ANSI SQL 兼容模式迁移指南从遗留 null 处理到 SQL 三值逻辑Apache Druid ANSI SQL 兼容模式迁移指南从遗留 null 处理到 SQL 三值逻辑 Apache Druid 自 28.0.0 起默认的数据库OLAP大数据后端Apache Druid SQL 多值字符串函数MV_*完全指南从 MV_FILTER_ONLY 到 MV_TO_ARRAYApache Druid SQL 多值字符串函数MV_ 完全指南从 MV_FILTER_ONLY 到 MV_TO_ARRAY 本文以 Apache Dru数据库OLAP大数据后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

TSDX 2.0.0 发布解析:基于 Rust 工具链的零配置 TypeScript 包开发 CLI 重写

TSDX 2.0.0 发布解析:基于 Rust 工具链的零配置 TypeScript 包开发 CLI 重写

开发工具CLI构建工具 【免费下载链接】tsdx Zero-config CLI for TypeScript package development 项目地址: https://gitcode.com/gh_mirrors/ts/tsdx 点击查看 免费下载 TSDX 2.0.0 是一次从零开始(complete rewrite)的大版本发布&#xf…

2026/9/23 17:04:08 阅读更多 →
Deployer Rsync Recipe 实战指南:用 rsync 替代 git 完成代码推送与远端热备

Deployer Rsync Recipe 实战指南:用 rsync 替代 git 完成代码推送与远端热备

DevOpsCI/CDCLI开发工具运维 【免费下载链接】deployer The PHP deployment tool with support for popular frameworks out of the box 项目地址: https://gitcode.com/gh_mirrors/de/deployer 点击查看 免费下载 本指南围绕 Deployer 官方 contrib 配方 contrib/…

2026/9/23 17:04:08 阅读更多 →
搞定vc含量高的水果数据清洗与源码解析,别再被报错逼疯

搞定vc含量高的水果数据清洗与源码解析,别再被报错逼疯

搞定vc含量高的水果数据清洗与源码解析,别再被报错逼疯 刚跑完那个 vc含量高的水果 数据处理脚本,终端里直接炸出一坨红色的 KeyError 和 IndexError…

2026/9/23 17:03:07 阅读更多 →

最新新闻

Cesium卫星雷达三维可视化:波束锥体与动态扫描线实现详解

Cesium卫星雷达三维可视化:波束锥体与动态扫描线实现详解

简介:面向前端开发者与三维可视化爱好者,这份资源围绕 Cesium 库与卫星雷达数据的组合展示,适合想要快速上手三维地球场景、学习遥感数据可视化入门实践的读者。压缩包共十一个文件,包含两个可直接运行的 HTML 页面,分…

2026/9/23 17:39:59 阅读更多 →
论文摘要多少字新手避坑:从API变更看底层校验逻辑

论文摘要多少字新手避坑:从API变更看底层校验逻辑

论文摘要多少字新手避坑:从API变更看底层校验逻辑 版本升级后 API 全变了,你是不是也曾在深夜盯着报错日志怀疑人生?这种挫败感,比论文摘要多少字写不达标更让人头秃。很多转岗的开发者以为只是文档没更新,其实是底层校验机制发生了根本性重构。…

2026/9/23 17:39:59 阅读更多 →
qq下载2021最新版下载安装新手避坑与最佳实践指南

qq下载2021最新版下载安装新手避坑与最佳实践指南

qq下载2021最新版下载安装新手避坑与最佳实践指南 学会语法却不知怎么搭项目,这是很多初学者掉进坑里的第一个原因。很多博主只讲API,不讲工程化落地,导致你面对真实业务场景时手足无措。今天我们就以“qq下载2021最新版下载安装”这个高频…

2026/9/23 17:39:59 阅读更多 →
Escrcpy 常见问题排查实战指南:从设备识别到跨平台疑难杂症的全方位排障手册

Escrcpy 常见问题排查实战指南:从设备识别到跨平台疑难杂症的全方位排障手册

Escrcpy 常见问题排查实战指南:从设备识别到跨平台疑难杂症的全方位排障手册 【免费下载链接】escrcpy 优雅而强大的跨平台 Android 设备控制工具,基于 Scrcpy 的 Electron 应用,支持无线连接和多设备管理,让您的电脑成为 Android 的完美伴侣。 项目地…

2026/9/23 17:39:59 阅读更多 →
3个高频面试题拆解:abc3d版本升级后API全变的性能优化实战

3个高频面试题拆解:abc3d版本升级后API全变的性能优化实战

3个高频面试题拆解:abc3d版本升级后API全变的性能优化实战 刚把项目从 abc3d 2.0 升到 3.0,打开文档直接懵了。旧版熟悉的 render() 接口没了,取而代之的是异步回调链,连基础几何体加载都改成了 Promise…

2026/9/23 17:39:59 阅读更多 →
React 同构直出项目接入 VasSonic:基于 Next.js / Redux / Koa2 的 SSR 页面秒开实战指南

React 同构直出项目接入 VasSonic:基于 Next.js / Redux / Koa2 的 SSR 页面秒开实战指南

移动开发前端后端 【免费下载链接】VasSonic VasSonic is a lightweight and high-performance Hybrid framework developed by tencent VAS team, which is intended to speed up the first screen of websites working on Android and iOS platform. 项目地址: h…

2026/9/23 17:38:59 阅读更多 →

日新闻

3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A…

2026/9/23 0:00:23 阅读更多 →
2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我

2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我

2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我 刚把开发环境的显示器从1080P换到2K,跑老项目直接报错,版本升级后 API…

2026/9/23 0:01:25 阅读更多 →
3步搞定美眉图实战项目,告别官方文档抓不住重点

3步搞定美眉图实战项目,告别官方文档抓不住重点

3步搞定美眉图实战项目,告别官方文档抓不住重点 官方文档翻了三遍还是云里雾里?别急,美眉图在实战项目中常被用来做数据可视化,但它的原理比你想的简单。今天咱们直接上手,用一个完整的小项目把美眉图跑通,不再死磕那些冗长的理论说明。…

2026/9/23 0:01:25 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/23 4:55:02 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/23 4:49:06 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/23 9:53:41 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/23 9:53:40 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/23 9:53:40 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/23 9:53:40 阅读更多 →