SQL 数据类型
Apache Druid 支持两种查询语言:Druid SQL 和 原生查询。 本文档介绍 SQL 语言。
Druid将每一列与特定的数据类型相关联。本主题介绍Druid SQL中支持的数据类型。
标准类型
Druid 原生支持以下基本列类型:
- LONG: 64位有符号整数
- FLOAT: 32位浮点数
- DOUBLE: 64位浮点数
- STRING: UTF-8编码的字符串和字符串数组
- COMPLEX: 非标准数据类型,例如嵌套JSON、hyperUnique和approxHistogram,以及DataSketches
- ARRAY: 由任意这些类型组成的数组
Druid将时间戳(包括__time列)视为LONG类型,其值表示自UTC时间1970-01-01 00:00:00以来的毫秒数(不计算闰秒)。因此,Druid中的时间戳不携带任何时区信息,仅表示其所对应的精确时间点。有关时间戳处理的更多信息,请参阅Time functions。
下表描述了Druid在执行查询时如何将SQL类型映射到原生类型:
| SQL 类型 | Druid 运行时类型 | 默认值* | 备注 |
|---|---|---|---|
| CHAR | STRING | '' | |
| VARCHAR | STRING | '' | Druid STRING columns are reported as VARCHAR. Can include multi-value strings as well. |
| DECIMAL | DOUBLE | 0.0 | DECIMAL uses floating point, not fixed point math |
| FLOAT | FLOAT | 0.0 | Druid FLOAT columns are reported as FLOAT |
| REAL | DOUBLE | 0.0 | |
| DOUBLE | DOUBLE | 0.0 | Druid DOUBLE columns are reported as DOUBLE |
| BOOLEAN | LONG | false | |
| TINYINT | LONG | 0 | |
| SMALLINT | LONG | 0 | |
| INTEGER | LONG | 0 | |
| BIGINT | LONG | 0 | Druid LONG columns (except __time) are reported as BIGINT |
| TIMESTAMP | LONG | 0, meaning 1970-01-01 00:00:00 UTC | Druid's __time column is reported as TIMESTAMP. Casts between string and timestamp types assume standard SQL formatting, such as 2000-01-02 03:04:05, not ISO 8601 formatting. For handling other formats, use one of the time functions. |
| DATE | LONG | 0, meaning 1970-01-01 | Casting TIMESTAMP to DATE rounds down the timestamp to the nearest day. Casts between string and date types assume standard SQL formatting—for example, 2000-01-02. For handling other formats, use one of the time functions. |
| ARRAY | ARRAY | NULL | Druid native array types work as SQL arrays, and multi-value strings can be converted to arrays. See Arrays for more information. |
| OTHER | COMPLEX | none | 可能表示各种Druid列类型,例如hyperUnique、approxHistogram等。 |
*
所有类型的默认值均为NULL。
对于两种SQL类型之间的转换,其行为取决于运行时类型:
-
在具有相同Druid运行时类型的两种SQL类型之间进行转换时,除了表格中注明的例外情况外,不会产生任何效果。
-
在两种具有不同Druid运行时类型的SQL类型之间进行转换时,会在Druid中生成运行时转换。
如果值无法转换为目标类型,例如CAST('foo' AS BIGINT),Druid会替换为NULL。
数组
Druid支持ARRAY类型,其行为与标准SQL数组一致,结果会通过匹配整个数组进行分组。通过使用UNNEST操作符可以对单个数组元素执行操作,将每个元素转换为单独的行。
ARRAY类型的列可以通过基于JSON的摄取方式存储在段中,使用与模式自动发现共享的'auto'类型维度模式来检测并将数组作为ARRAY类型列摄取。对于基于SQL的摄取,必须将查询上下文参数arrayIngestMode指定为"array"以摄取ARRAY类型。在Druid 28中,为了向后兼容,此参数的默认模式是"mvd",它只能处理ARRAY类型,并将其存储在多值字符串列中。
您可以通过MV_TO_ARRAY显式地将多值维度转换为标准SQL数组,或使用数组函数隐式转换。您还可以使用数组函数从多列构建数组。
Druid默认将ARRAY结果序列化为数组的JSON字符串,这可以通过上下文参数sqlStringifyArrays进行控制。当设置为false并使用JSON结果格式时,数组将以常规JSON数组形式返回,而非字符串化形式。
多值字符串
Druid的原生类型系统允许字符串拥有多个值。这些多值字符串维度在SQL中报告为VARCHAR类型,可以像其他VARCHAR一样在语法上使用。引用多值字符串维度的常规字符串函数会单独应用于每行的所有值。
您可以使用特殊的多值字符串函数将多值字符串维度视为数组,这些函数执行强大的数组感知操作,同时保留其VARCHAR类型和行为。
按多值维度分组遵循Druid原生的多值聚合行为,类似于隐式的SQL UNNEST操作。详见Grouping获取更多信息。
由于SQL规划器将多值维度视为VARCHAR类型,因此在Druid SQL和原生查询中对它们的处理方式存在一些不一致。例如,涉及多值维度的表达式可能会被Druid SQL规划器错误优化。比如multi_val_dim = 'a' AND multi_val_dim = 'b'会被优化为false,但实际上单行数据完全可能同时包含'a'和'b'作为multi_val_dim的值。
多值维度在SQL中的行为可能会在未来的版本中发生变化,以更贴近其在原生查询中的表现,但多值字符串函数应能提供几乎所有可能的原生功能。
多值字符串行为
Druid 多值字符串维度的行为会根据其使用场景而变化。
当与期望每行单个输入值的标准VARCHAR函数(如CONCAT)一起使用时,Druid会将函数映射到行中的所有值。如果行为空或为空,则函数接收NULL作为其输入。
当与显式的多值字符串函数一起使用时,Druid会将行值当作ARRAY类型进行处理。任何产生空行和空值的操作会被区分为不同的值(与隐式映射行为不同)。这些多值字符串函数通常以MV_为前缀,在计算完成后仍保持VARCHAR类型。请注意Druid的多值列不会区分空行和空值。空行永远不会作为原生输入传递给多值函数,但任何操作数组形式值的多值函数都可能产生空数组,这在处理过程中会单独处理。
不要在同一表达式中混用多值函数和普通标量函数,因为规划器将无法根据其模糊用法确定如何处理该值。多值字符串在表达式中必须保持一致处理。
当转换为ARRAY或与数组函数一起使用时,多值字符串的行为类似于标准SQL数组,无法再使用非数组函数进行操作。
默认情况下,如果未对值进行分组操作,Druid会将多值VARCHAR结果序列化为数组的JSON字符串。
若值经过分组(由于隐式UNNEST行为),所有结果将始终以标准单值VARCHAR形式呈现。数组类型结果的序列化由上下文参数sqlStringifyArrays控制。当该参数设为false且使用JSON结果格式时,数组将以常规JSON数组形式返回,而非字符串化形式。
NULL值
默认情况下,Druid处理NULL值的方式与ANSI SQL标准类似。
关于空值处理的示例,请参阅空值处理教程。
布尔逻辑
Druid在过滤处理和布尔表达式评估中使用SQL三值逻辑。
嵌套列
Druid支持使用原生COMPLEX类型在数据段中存储嵌套数据结构。更多信息请参阅Nested columns。
您可以使用JSON函数与嵌套数据进行交互,这些函数可以提取嵌套值、从字符串解析、序列化为字符串,并创建新的COMPLEX结构。
COMPLEX类型在专门使用它们的函数之外功能有限,因此在以下情况下其行为未定义:
- 基于复杂值的分组。
- 直接对复杂值进行过滤。
- 用作聚合器的输入,无需针对特定复杂类型进行专门处理。
在许多情况下,提供了将COMPLEX值类型转换为STRING的函数,这是一种临时解决方案,直到COMPLEX类型功能得到改进。