本文翻译自官网:https://ci.apache.org/projects/flink/flink-docs-release-1.9/dev/table/types.html

由于历史原因,在 Flink 1.9之前,Flink 的 Table和SQL API 数据类型与 Flink TypeInformation 紧密相关。TypeInformation 在 DataStream 和 DataSet API 中使用,并且足以描述在分布式设置中序列化和反序列化基于 JVM的 对象所需的所有信息。

但是,TypeInformation并非旨在表示独立于实际JVM类的逻辑类型。过去,很难将SQL标准类型映射到此抽象。此外,某些类型不符合SQL,因此在引入时并没有大的意义。

从Flink 1.9开始,Table&SQL API将获得一种新类型系统,该系统可作为API稳定性和标准合规性的长期解决方案。

修改类型系统是一项涉及几乎所有面向用户界面的重大工作。因此,它的引入涵盖了多个发行版,并且社区目标是 Flink 1.10 完成此工作。

由于同时为 Table 程序添加了一个新的 planner(请参阅FLINK-11439),因此不支持 planner 和数据类型的每种组合。此外,planner 可能不支持具有所需精度或参数的每种数据类型。

注意: 在使用数据类型之前,请参阅 planner 兼容性列表和限制部分。

数据类型

  • Table API中的数据类型

规划器兼容性

  • Old planner

  • 新的 Blink planner

局限性

数据类型列表

  • 字符串

  • 二进制字符串

  • 精确数值

  • 近似数值

  • 日期和时间

  • 构造数据类型

  • 其他数据类型

数据类型

数据类型描述在表中的生态系统值的逻辑类型。它可用于声明操作的输入或输出类型。

Flink的数据类型与SQL标准的数据类型术语相似,但也包含有关有效处理标量表达式值的可为空性的信息。

数据类型的示例是:

INT

INT NOT NULL

INTERVAL DAY TO SECOND(3)

ROW<myField ARRAY<BOOLEAN>, myOtherField TIMESTAMP(3)>

可以在下面找到所有预定义数据类型的列表。

Table API中的数据类型

基于JVM API的用户可以在Table API 中使用org.apache.flink.table.types.DataType的实例,或者在定义连接器,catalog 或用户定义的函数时使用。

一个 DataType 实例有两个作用:

逻辑类型的声明,并不表示要进行传输或存储的具体物理表示形式,而是定义了基于JVM的语言和表生态系统之间的界限。

可选: 向 pallner 提供有关数据物理表示的提示,这对于其他 API 的边缘很有用。

对于基于 JVM 的语言,所有预定义的数据类型都在 org.apache.flink.table.api.DataTypes 中提供。

建议使用星号导入到表程序中以顺利使用全部的API:

import org.apache.flink.table.api.DataTypes._

val t: DataType = INTERVAL(DAY(), SECOND(3));

物理Hites

在基于SQL的类型系统结尾和需要特定编程数据类型的表生态系统的边缘,需要物理 hint。hint 指示实现所需的数据格式。

例如,数据源可以表示它使用java.sql.Timestamp类而不是默认的java.time.LocalDateTime为逻辑TIMESTAMP生成值。有了这些信息,runtime 就可以将产生的类转换为其内部数据格式。作为回报,数据接收器可以声明其从 runtime 使用的数据格式。

以下是一些如何声明桥接转换类的示例:

// tell the runtime to not produce or consume java.time.LocalDateTime instances
// but java.sql.Timestamp
val t: DataType = DataTypes.TIMESTAMP(3).bridgedTo(classOf[java.sql.Timestamp]);

// tell the runtime to not produce or consume boxed integer arrays
// but primitive int arrays
val t: DataType = DataTypes.ARRAY(DataTypes.INT().notNull()).bridgedTo(classOf[Array[Int]]);

注意: 请注意,通常只有在扩展API时才需要物理提示。预定义 source/sink/functions 的用户无需定义此类提示。Table 程序(例如field.cast(TIMESTAMP(3).bridgedTo(Timestamp.class)))中的提示将被忽略。

Planner 兼容性

如引言中所述,对类型系统进行重做将跨越多个版本,每种数据类型的支持取决于所使用的 planner 。本节旨在总结最重要的差异。

Old planner

Flink 1.9之前引入的Flink old planner 主要支持 type information。它仅对 data type 提供有限的支持。声明可以转换为 Type information 的 data type,以便 old planner 可以理解它们。

下表总结了 data type 和 type information 之间的区别。大多数简单类型以及行类型均保持不变。时间类型,数组类型和 decimal 类型需要特别注意。不允许使用其他提示。

对于“ Type Information ” 列,该表格省略了前缀 org.apache.flink.table.api.Types。

对于“ Data Type Representation ”列,该表格省略了前缀org.apache.flink.table.api.DataTypes。

注意:如果新型系统有问题。用户可以随时回退到 org.apache.flink.table.api.Types 定义的 Type information。

新的Blink planner

新的Blink planner 支持所有 old planner 的程序类型。尤其包括列出的Java表达式字符串和类型信息。

支持以下数据类型:

局限性

Java表达式字符串:Table API中的Java表达式字符串,例如table.select("field.cast(STRING)") 尚未更新为新类型的系统。使用在Old planner 部分中声明的字符串表示形式。

连接器描述符和SQL客户端:描述符字符串表示形式尚未更新为新类型的系统。使用在“ 连接到外部系统”部分中声明的字符串表示形式

用户定义的函数:用户定义的函数尚不能声明 data type。

数据类型列表

本节列出了所有预定义的数据类型。对于基于JVM的Table API,这些类型在 org.apache.flink.table.api.DataTypes 中也可用。

字符串

CHAR

定长字符串的数据类型。

SQL 定义

CHAR
CHAR(n)

Java、Scala 定义

DataTypes.CHAR(n)

可以使用CHAR(n) n是字符串的长度声明类型。n的值必须介于1 和之间2,147,483,647(包括两者之间)。如果未指定长度 ,则n等于1。 桥接到JVM类型

VARCHAR / STRING

可变长度字符串的数据类型。

SQL 定义

VARCHAR
VARCHAR(n)

STRING

Java、Scala 定义

DataTypes.VARCHAR(n)

DataTypes.STRING()

可以使用VARCHAR(n) n是字符串的最大长度来声明类型。n的值必须介于1和之间2,147,483,647(包括两者之间)。如果未指定长度,则n等于1。 STRING 是 VARCHAR(2147483647) 的同义词。

桥接到JVM类型

二进制字符串

BINARY 固定长度的二进制字符串(=字节序列)的数据类型。

SQL 定义

BINARY
BINARY(n)

Java、Scala 定义

DataTypes.BINARY(n)

可以使用BINARY(n) n是字节数来声明类型。n的值必须介于1和之间2,147,483,647(包括两者之间)。如果未指定长度,则 n 等于1。 桥接到JVM类型

VARBINARY / BYTES 可变长度二进制字符串(=字节序列)的数据类型。

SQL 定义

VARBINARY
VARBINARY(n)

BYTES Java、Scala 定义

DataTypes.VARBINARY(n)

DataTypes.BYTES()

可以使用VARBINARY(n) n是字节的最大长度来声明类型。n的值必须介于1和之间2,147,483,647(包括两者之间)。如果未指定长度,则 n等于1。 BYTES是 VARBINARY(2147483647) 的同义词。

桥接到JVM类型

精确数值

DECIMAL 具有固定精度和小数位数的十进制数字的数据类型。

SQL 定义

DECIMAL
DECIMAL(p)
DECIMAL(p, s)

DEC
DEC(p)
DEC(p, s)

NUMERIC
NUMERIC(p)
NUMERIC(p, s)

Java、Scala

DataTypes.DECIMAL(p, s)

可以使用 DECIMAL(p, s) 来声明类型,其中 p 是数字中整数部分的位数(precision),s是数字中小数点右边的位数(scale)。p的值必须介于1和之间38(包括两者之间)。s 的值必须介于0和之间p(包括两者之间)。其中 p 的缺省值是10,s 的缺省值是 0。 NUMERIC(p, s) 和 DEC(p, s) 是这种类型的同义词。

桥接到JVM类型

TINYINT

1字节有符号整数的数据类型,其值从-128 到 127。

SQL 定义

TINYINT

Java、Scala 定义

DataTypes.TINYINT()

桥接到JVM类型

SMALLINT

2字节有符号整数的数据类型,其值从-32,768到32,767。

SQL 定义

SMALLINT

Java、Scala 定义

DataTypes.SMALLINT()

桥接到JVM类型 INT

4字节有符号整数的数据类型,其值从-2,147,483,648to到2,147,483,647。

SQL 定义

INT

INTEGER

Java、Scala 定义

DataTypes.INT()

INTEGER 是此类型的同义词。 桥接到JVM类型

BIGINT

8字节有符号整数的数据类型,其值从-9,223,372,036,854,775,808to到 9,223,372,036,854,775,807。

SQL 定义

BIGINT

Java、Scala 定义

DataTypes.BIGINT()

桥接到JVM类型

近似数值

FLOAT

4字节单精度浮点数的数据类型。

与SQL标准相比,该类型不带参数。

SQL 定义

FLOAT

Java、Scala 定义

DataTypes.FLOAT()

桥接到JVM类型 DOUBLE 8字节双精度浮点数的数据类型。

SQL 定义

DOUBLE
DOUBLE PRECISION

Java、Scala 定义

DataTypes.DOUBLE()

DOUBLE PRECISION 是此类型的同义词。 桥接到JVM类型

日期和时间

DATE 日期的数据类型,包含 year-month-day 范围从0000-01-01 到的值9999-12-31。

与SQL标准相比,year 范围从 0000 开始。

SQL 定义

DATE

Java、Scala 定义

DataTypes.DATE()

桥接到JVM类型 TIME 没有时区的时间数据类型,其hour:minute:second[.fractional]精度高达纳秒,范围从00:00:00.000000000到23:59:59.999999999。

与SQL标准相比,不支持leap秒(23:59:60和23:59:61),因为语义更接近java.time.LocalTime。没有提供带时区的时间。

SQL 定义

TIME
TIME(p)

Java、Scala 定义

DataTypes.TIME(p)

可以使用TIME(p) p是小数部分 秒的位数(precision)来声明类型。p的值必须介于0和之间9(包括两者之间)。如果未指定精度,则 p等于0。 桥接到JVM类型

TIMESTAMP 不带时区的时间戳数据类型,其year-month-day hour:minute:second[.fractional] 精度高达纳秒,范围从0000-01-01 00:00:00.000000000到 9999-12-31 23:59:59.999999999。

与SQL标准相比,不支持leap秒(23:59:60和23:59:61),因为语义更接近java.time.LocalDateTime。

不支持从BIGINT(与JVM long类型)之间的转换,因为这意味着时区。但是,此类型没有时区。对于更类似 java.time.Instant 的语义,请使用 TIMESTAMP WITH LOCAL TIME ZONE。

SQL 定义

TIMESTAMP
TIMESTAMP(p)

TIMESTAMP WITHOUT TIME ZONE
TIMESTAMP(p) WITHOUT TIME ZONE

Java、Scala 定义

DataTypes.TIMESTAMP(p)

可以使用TIMESTAMP(p) p是小数部分 秒的位数(precision)来声明类型。p的值必须介于0和之间9(包括两者之间)。如果未指定精度,则 p等于6。 TIMESTAMP(p) WITHOUT TIME ZONE 是此类型的同义词。

桥接到JVM类型 TIMESTAMP WITH TIME ZONE timestamp with time zone 数据类型由 year-month-day hour:minute:second[.fractional] 与 zone 组成, 精度达纳秒,值范围为0000-01-01 00:00:00.000000000 +14:59至 9999-12-31 23:59:59.999999999 -14:59。

与SQL标准相比,不支持leap秒(23:59:60和23:59:61),因为语义更接近java.time.OffsetDateTime。

与 TIMESTAMP WITH LOCAL TIME ZONE 相比,时区偏移量信息物理存储在每个数据中。它单独用于每个计算,可视化或与外部系统的通信。

SQL 定义

TIMESTAMP WITH TIME ZONE
TIMESTAMP(p) WITH TIME ZONE

Java、Scala 定义

DataTypes.TIMESTAMP_WITH_TIME_ZONE(p)

可以使用TIMESTAMP(p) WITH TIME p是小数部分秒的位数(precision)来声明类型。p的值必须介于0和之间9(包括两者之间)。如果未指定精度,p则等于6。 桥接到JVM类型

TIMESTAMP WITH LOCAL TIME ZONE timestamp with local time zone 数据类型,由 year-month-day hour:minute:second[.fractional] zone 组成, 精度高达纳秒,范围从0000-01-01 00:00:00.000000000 +14:59到 9999-12-31 23:59:59.999999999 -14:59。

不支持Leap 秒(23:59:60和23:59:61),因为语义更接近java.time.OffsetDateTime。

与TIMESTAMP WITH TIME ZONE相比,时区偏移量信息并非物理存储在每个数据中。相反,该类型在表生态系统的边缘采用UTC时区中的java.time.Instant语义。每个数据都在当前会话中配置的本地时区中进行解释,以进行计算和可视化。

通过允许根据已配置的会话时区解释UTC时间戳,此类型填补了时区空闲和时区强制性时间戳类型之间的空白。

SQL 定义

TIMESTAMP WITH LOCAL TIME ZONE
TIMESTAMP(p) WITH LOCAL TIME ZONE

Java、Scala 定义

DataTypes.TIMESTAMP_WITH_LOCAL_TIME_ZONE(p)

可以使用TIMESTAMP(p) WITH LOCAL TIME ZONE p是小数部分秒的位数(precision)来声明类型。p的值必须介于0和之间9 (包括两者之间)。如果未指定精度,p则等于6。 桥接到JVM类型

INTERVAL YEAR TO MONTH 一组年月间隔类型的数据类型。

必须将类型参数化为以下类型之一:

年间隔

几年到几个月的间隔

间隔几个月。

年-月的间隔由+years-months 到组成,范围从-9999-11到 +9999-11。

所有类型的分辨率的值表示均相同。例如,始终以“年月间隔”格式(默认年份精度)表示50个月的间隔:+04-02(4年2个月)。

SQL 定义


INTERVAL YEAR
INTERVAL YEAR(p)
INTERVAL YEAR(p) TO MONTH
INTERVAL MONTH

Java、Scala 定义

DataTypes.INTERVAL(DataTypes.YEAR())
DataTypes.INTERVAL(DataTypes.YEAR(p))
DataTypes.INTERVAL(DataTypes.YEAR(p), DataTypes.MONTH())
DataTypes.INTERVAL(DataTypes.MONTH())

可以使用以上组合来声明类型,其中p是年(年精度)的位数。p的值必须介于1和之间4(包括两者之间)。如果未指定年精度,p则等于2。 桥接到JVM类型

INTERVAL DAY TO MONTH

一组天时间间隔类型的数据类型。

必须将类型参数设置为以下类型之一,精度最高为纳秒:

天间隔

几天到几小时的间隔

天到分钟的间隔

天到秒的间隔

小时间隔

小时到几分钟的间隔,

小时到几秒的间隔,

分钟间隔

分钟到秒的间隔,

或秒间隔。

一天中的时间间隔包含,+days hours:months:seconds.fractional范围从 -999999 23:59:59.999999999到+999999 23:59:59.999999999。所有类型的分辨率的值表示均相同。例如,秒间隔 70 始终以天间隔格式(具有默认精度)表示:+00 00:01:10.000000。

SQL 定义

INTERVAL DAY
INTERVAL DAY(p1)
INTERVAL DAY(p1) TO HOUR
INTERVAL DAY(p1) TO MINUTE
INTERVAL DAY(p1) TO SECOND(p2)
INTERVAL HOUR
INTERVAL HOUR TO MINUTE
INTERVAL HOUR TO SECOND(p2)
INTERVAL MINUTE
INTERVAL MINUTE TO SECOND(p2)
INTERVAL SECOND
INTERVAL SECOND(p2)

Java、Scala 定义

DataTypes.INTERVAL(DataTypes.DAY())
DataTypes.INTERVAL(DataTypes.DAY(p1))
DataTypes.INTERVAL(DataTypes.DAY(p1), DataTypes.HOUR())
DataTypes.INTERVAL(DataTypes.DAY(p1), DataTypes.MINUTE())
DataTypes.INTERVAL(DataTypes.DAY(p1), DataTypes.SECOND(p2))
DataTypes.INTERVAL(DataTypes.HOUR())
DataTypes.INTERVAL(DataTypes.HOUR(), DataTypes.MINUTE())
DataTypes.INTERVAL(DataTypes.HOUR(), DataTypes.SECOND(p2))
DataTypes.INTERVAL(DataTypes.MINUTE())
DataTypes.INTERVAL(DataTypes.MINUTE(), DataTypes.SECOND(p2))
DataTypes.INTERVAL(DataTypes.SECOND())
DataTypes.INTERVAL(DataTypes.SECOND(p2))

可以使用上述组合声明类型,其中p1是天的位数(日精度)和p2是秒的位数(分数精度)。 p1的值必须介于1和之间6(包括两者之间)。p2的值必须介于0 和之间9(包括两者之间)。如果未p1指定,默认情况下等于 2。如果未p2指定,默认情况下等于6。 桥接到JVM类型

构造数据类型

ARRAY 具有相同子类型的元素数组的数据类型。

与SQL标准相比,无法指定数组的最大基数,但固定为2,147,483,647。另外,任何有效类型都支持作为子类型。

SQL 定义

ARRAY<t>
t ARRAY

Java、Scala 定义

DataTypes.ARRAY(t)

可以使用 ARRAY<t> t是所包含元素的数据类型来声明类型。 t ARRAY是接近SQL标准的同义词。例如,INT ARRAY等效于ARRAY<INT>。

桥接到JVM类型

MULTISET

多重集的数据类型(= bag )。与集合不同,它允许每个元素具有公共子类型的多个实例。每个唯一值(包括NULL)都映射到某种多重性。

元素类型没有限制;确保唯一性是用户的责任。

SQL 定义


MULTISET<t>
t MULTISET

Java、Scala 定义

DataTypes.MULTISET(t)

可以使用 MULTISET<t> t是所包含元素的数据类型来声明类型。 t MULTISET是接近SQL标准的同义词。例如,INT MULTISET等效于MULTISET<INT>。

桥接到JVM类型

ROW 字段序列的数据类型。

字段由字段名称,字段类型和可选描述组成。表的行 最特定类型是行类型。在这种情况下,该行的每一列对应于具有与该列相同序号位置的行类型的字段。

与SQL标准相比,可选的字段描述简化了复杂结构的处理。

Row 类型类似于其他非标准兼容框架中已知的STRUCT类型。

SQL 定义


ROW<n0 t0, n1 t1, ...>
ROW<n0 t0 'd0', n1 t1 'd1', ...>

ROW(n0 t0, n1 t1, ...>
ROW(n0 t0 'd0', n1 t1 'd1', ...)
Java、Scala 定义
DataTypes.ROW(DataTypes.FIELD(n0, t0), DataTypes.FIELD(n1, t1), ...)
DataTypes.ROW(DataTypes.FIELD(n0, t0, d0), DataTypes.FIELD(n1, t1, d1), ...)

可以使用ROW<n0 t0 'd0', n1 t1 'd1', ...>where 来声明类型,其中where n是字段的唯一名称,是字段t的逻辑类型,是字段d的描述。 ROW(...)是接近SQL标准的同义词。例如,ROW(myField INT, myOtherField BOOLEAN)等效于ROW<myField INT, myOtherField BOOLEAN>。

桥接到JVM类型

其他数据类型

BOOLEAN (可能)具有三值逻辑 TRUE,FALSE 和 UNKNOWN 的布尔数据类型。

SQL 定义


BOOLEAN

Java、Scala 定义

DataTypes.BOOLEAN()

桥接到JVM类型

NULL

表示空类型 NULL值的数据类型。

NULL 类型是SQL标准的扩展。除了 NULL 类型之外没有其他 NULL 值,因此可以将其强制转换为类似于JVM语义的任何可空类型。

此类型有助于表示使用NULL文字的API调用中的未知类型,以及桥接到定义该类型的JSON或Avro等格式。

这种类型在实践中不是很有用,为完整起见在此仅提及。

SQL 定义


NULL

Java、Scala 定义

DataTypes.NULL()

桥接到JVM类型

ANY

任意序列化类型的数据类型。此类型是表生态系统内的黑匣子,仅在边缘反序列化。

any类型是SQL标准的扩展。

SQL 定义

ANY('class', 'snapshot')

Java、Scala 定义

DataTypes.ANY(class, serializer)


DataTypes.ANY(typeInfo)

可以使用ANY('class', 'snapshot') class是原始类来声明类型,并 以Base64编码TypeSerializerSnapshot 进行 snapshot 序列化。通常,类型字符串不是直接声明的,而是在保留类型时生成的。 在API中,可以通过直接提供Class + TypeSerializer或通过传递TypeInformation并让框架从那里提取Class + TypeSerializer来声明ANY类型。

桥接到JVM类型