- 大数据
- 数据分析
- 批处理
- 流处理
- 机器学习
- 图计算
【免费下载链接】spark
Apache Spark - A unified analytics engine for large-scale data processing
本文档是 Apache Spark 官方 SQL 语法参考系列的一部分,对应仓库文档 docs/sql-ref-syntax-hive-format.md。Hive Row Format 用于在
CREATE TABLE与TRANSFORM(含MAP/REDUCE)等子句中指定 SerDe 类或文本分隔符,是打通 Spark 与 Hive 生态数据读写格式的关键语法。读完本文,你将掌握ROW FORMAT SERDE与ROW FORMAT DELIMITED两种定义方式、全部子句参数(字段/集合/Map/行分隔符、NULL 表示、转义字符)的语义与默认行为,并理解 Spark 解析器与 Hive 底层 SerDe 属性之间的映射规则。
一、概述(Description)
Spark 在CREATE TABLE和TRANSFORM子句中支持Hive row format,用于指定 SerDe 类或文本分隔符。CREATE TABLE与TRANSFORM的row_format有两种定义方式:
SERDE子句:指定一个自定义的 SerDe 类(fully-qualified class name);DELIMITED子句:为原生 SerDe(native SerDe)指定分隔符(delimiter)、转义字符(escape character)、空值字符(null character)等。
从语法解析的实现看,这两种方式最终都会被解析成同一份SerdeInfo数据结构(定义于 statements.scala),它统一承载storedAs、formatClasses、serde类名与serdeProperties键值对。ANTLR 文法 SqlBaseParser.g4 中的rowFormat规则完整对应了本文档的两种语法形态。
二、语法(Syntax)
row_format: SERDE serde_class [ WITH SERDEPROPERTIES (k1=v1, k2=v2, ... ) ] | DELIMITED [ FIELDS TERMINATED BY fields_terminated_char [ ESCAPED BY escaped_char ] ] [ COLLECTION ITEMS TERMINATED BY collection_items_terminated_char ] [ MAP KEYS TERMINATED BY map_key_terminated_char ] [ LINES TERMINATED BY row_terminated_char ] [ NULL DEFINED AS null_char ]两种形态互斥,只能二选一。DELIMITED形态下,除了FIELDS TERMINATED BY是可选项,其余各子句均为可选,可按需自由组合。
2.1 row_format 可出现的语法位置
row_format不仅仅出现在建表语句中。从 ANTLR 文法可以看出,Spark 在以下语法位置都允许嵌入row_format:
- CREATE TABLE / CREATE TABLE LIKE:建表时可指定行格式,例如
CREATE TABLE ... LIKE source (rowFormat | createFileFormat | locationSpec | TBLPROPERTIES ...)*(见 SqlBaseParser.g4); - CREATE TABLE ... (含分区、分桶、SKEWED 等完整建表子句列表):
rowFormat与createFileFormat、locationSpec、bucketSpec等并列出现在建表选项列表中(见 SqlBaseParser.g4); - INSERT OVERWRITE (LOCAL) DIRECTORY:向目录写出数据时可指定
rowFormat与createFileFormat(见 SqlBaseParser.g4); - TRANSFORM / MAP / REDUCE 子句:
SELECT TRANSFORM(...) ... USING script的输入行格式inRowFormat与输出行格式outRowFormat(见 SqlBaseParser.g4)。
2.2 解析器如何构建 SerdeInfo
在 AstBuilder.scala 中,visitRowFormat根据语法树节点类型分发:
RowFormatSerdeContext→visitRowFormatSerde:把SERDE serde_name解析为SerdeInfo(serde = Some(name), serdeProperties = ...),WITH SERDEPROPERTIES中的键值对直接进入serdeProperties映射;RowFormatDelimitedContext→visitRowFormatDelimited:把 DELIMITED 形态中的每个分隔符映射为对应名称的 SerDe 属性(详见下文第四节)。
三、参数说明(Parameters)
| 参数 | 语义 | 说明 |
|---|---|---|
| SERDE serde_class | 指定自定义 SerDe 的完整限定类名(fully-qualified class name) | 必须给出可被类加载器加载的完整类路径,例如 Hive 生态常见的org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe、JsonSerDe等 |
| SERDEPROPERTIES | 一组用于标记 SerDe 定义的键值对(key-value pairs) | 透传给 SerDe 的初始化属性,例如('field.delim'='\t', 'serialization.format'='\t') |
| FIELDS TERMINATED BY | 定义列分隔符(column separator) | 指定字段之间的分隔字符 |
| COLLECTION ITEMS TERMINATED BY | 定义集合元素分隔符(collection item separator) | 用于 Array、Struct 等集合类型内部元素的切分 |
| MAP KEYS TERMINATED BY | 定义 Map 键分隔符(map key separator) | 用于 Map 类型中键与值之间的切分 |
| LINES TERMINATED BY | 定义行分隔符(row separator) | Spark 仅接受'\n',其他字符会被拒绝(见下文) |
| NULL DEFINED AS | 定义 NULL 的特定表示值 | 指定文本文件中表示空值的字符序列 |
| ESCAPED BY | 转义机制(escape mechanism) | 指定转义字符,用于转义分隔符或特殊字符 |
注意:
SERDEPROPERTIES的键值对写法是k=v1,但在实际 SQL 中通常写作带引号的字符串键值对,例如WITH SERDEPROPERTIES ('field.delim' = '\t'),这在CREATE TABLE与TRANSFORM语法中均被支持。
四、DELIMITED 子句与底层 SerDe 属性的映射(源码级)
DELIMITED 形态的每个子句并不会被存成独立字段,而是被转换成 Hive SerDe 的serdeProperties。visitRowFormatDelimited(见 AstBuilder.scala)逐项完成映射:
| SQL 子句 | 生成的 serdeProperties 键 | 说明 |
|---|---|---|
FIELDS TERMINATED BY | field.delim与serialization.format | 同时写入两个键,供不同 SerDe 解析使用 |
ESCAPED BY | escape.delim | 转义字符 |
COLLECTION ITEMS TERMINATED BY | colelction.delim | 注意拼写为colelction(少一个 'l'),源码注释明确说明这是继承自 Hive 的拼写错误,必须沿用 |
MAP KEYS TERMINATED BY | mapkey.delim | Map 键值分隔符 |
LINES TERMINATED BY | line.delim | 行分隔符 |
NULL DEFINED AS | —— | 源码中entry("null", ...)尚未实现,注释标注TODO we need proper support for the NULL format,即当前 DELIMITED 形态对 NULL 自定义值的支持仍属 TODO 状态 |
两个值得关注的实现细节:
- LINES TERMINATED BY 只接受
'\n':当LINES TERMINATED BY的值不是"\n"时,解析器直接抛出QueryParsingErrors.unsupportedRowFormatLinesTerminatedByError(见 AstBuilder.scala)。这意味着在 Spark 中行分隔符实际上是固定为换行符的,无法像 Hive 那样自由指定行分隔符。 - 映射即 SerDe 属性:DELIMITED 形态最终生成的也是一个
SerdeInfo(serdeProperties = entries.toMap),只是不指定serde类,交由原生(默认)SerDe 读取这些属性。
五、ROW FORMAT 与 STORED AS 的兼容性规则
ROW FORMAT不能与任意文件格式随意组合。解析器在validateRowFormatFileFormat(见 AstBuilder.scala)中强制校验以下组合,除此之外都会抛出 ParseException:
ROW FORMAT SERDE ... STORED AS [SEQUENCEFILE | RCFILE | TEXTFILE]—— 允许;ROW FORMAT DELIMITED ... STORED AS TEXTFILE—— 允许;ROW FORMAT ... STORED AS INPUTFORMAT ... OUTPUTFORMAT ...—— 允许(显式指定 InputFormat/OutputFormat);- 其他组合(例如
ROW FORMAT SERDE搭配PARQUET/ORC/AVRO等自带 SerDe 的格式,或ROW FORMAT DELIMITED搭配非 TEXTFILE 格式)—— 不允许。
对应测试用例位于 DDLParserSuite.scala,例如:
ROW FORMAT SERDE 'customSerde' WITH SERDEPROPERTIES ('prop'='value')搭配STORED AS otherFormat会报错"ROW FORMAT SERDE is incompatible with format 'otherformat', which also specifies a serde";ROW FORMAT DELIMITED FIELDS TERMINATED BY ','搭配非 TEXTFILE 格式会报错"ROW FORMAT DELIMITED is only compatible with 'textfile', not 'otherformat'"。
六、实战示例
6.1 CREATE TABLE 中使用 ROW FORMAT SERDE
指定自定义 SerDe 类,并透传 SerDe 属性:
CREATE TABLE hive_serde_table ( name STRING, age INT ) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe' WITH SERDEPROPERTIES ( 'field.delim' = '\t', 'serialization.format' = '\t' );6.2 CREATE TABLE 中使用 ROW FORMAT DELIMITED
使用原生 SerDe 并指定完整的分隔符组合:
CREATE TABLE hive_delimited_table ( id INT, name STRING, tags ARRAY<STRING>, attributes MAP<STRING, STRING> ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' ESCAPED BY '\\' COLLECTION ITEMS TERMINATED BY '#' MAP KEYS TERMINATED BY ':' LINES TERMINATED BY '\n' NULL DEFINED AS '\\N';上例中:字段用逗号切分;数组元素用#切分;Map 键值对用:切分;转义字符为反斜杠;NULL 在文本中以\N表示。注意LINES TERMINATED BY在 Spark 中只能取'\n'。
6.3 CREATE TABLE LIKE 中继承行格式
CREATE TABLE LIKE子句允许在复制表结构的同时显式覆盖行格式:
CREATE TABLE new_table LIKE source_table ROW FORMAT SERDE 'customSerde' WITH SERDEPROPERTIES ('prop' = 'value');6.4 TRANSFORM 子句中使用 ROW FORMAT
SELECT TRANSFORM(MAP/REDUCE为其别名)可以分别为脚本的输入与输出指定行格式:
SELECT TRANSFORM (id, name) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' USING '/usr/bin/awk -F, \'{print $1, toupper($2)}\'' AS (id INT, name STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';6.5 INSERT OVERWRITE DIRECTORY 中使用 ROW FORMAT
向目录导出文本时指定分隔符:
INSERT OVERWRITE LOCAL DIRECTORY '/tmp/export' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' SELECT name, age FROM people;七、注意事项与限制(结合源码)
- 行分隔符受限:
LINES TERMINATED BY仅接受'\n',设置其他字符会在解析阶段直接报错(源码见 AstBuilder.scala)。 colelction.delim拼写是历史遗留:COLLECTION ITEMS TERMINATED BY映射到的属性键为colelction.delim(Hive 拼写错误),使用SERDEPROPERTIES直接手写属性时必须保持该拼写才能生效。- NULL 自定义支持未完成:
NULL DEFINED AS在 DELIMITED 形态下尚未映射到任何 SerDe 属性(源码中有对应 TODO 注释),实际效果需要结合所用 SerDe 的自身属性(如 LazySimpleSerDe 的serialization.null.format)来实现。 - SERDE 与自带 SerDe 的文件格式不兼容:PARQUET、ORC 等格式自带序列化方案,不能与
ROW FORMAT SERDE混用,否则建表报错。 - SERDEPROPERTIES 是透传机制:Spark 本身不解释属性值的业务含义,只负责将其原样绑定到表/目录的 SerDe 上,具体解析由对应 SerDe 类完成。
八、相关资源
- 本文档原文:docs/sql-ref-syntax-hive-format.md
- 语法文法定义:SqlBaseParser.g4
- 解析实现:AstBuilder.scala
- SerdeInfo 数据结构:statements.scala
- 兼容性与错误提示测试:DDLParserSuite.scala
- 大数据
- 数据分析
- 批处理
- 流处理
- 机器学习
- 图计算
【免费下载链接】spark
Apache Spark - A unified analytics engine for large-scale data processing
相关推荐
Apache Spark SQL 的 LOAD DATA 语句:向 Hive Serde 表装载数据文件的完整指南
Apache Spark SQL 的 LOAD DATA 语句:向 Hive Serde 表装载数据文件的完整指南 LOAD DATA 是 Apache Spa
大数据数据分析批处理流处理机器学习图计算Apache Spark SQL 语法精解:SHOW TABLES 命令的完整使用指南
Apache Spark SQL 语法精解:SHOW TABLES 命令的完整使用指南 导读 SHOW TABLES 是 Apache Spark SQL 中最
大数据数据分析批处理流处理机器学习图计算Apache Spark SQL 集成 Hive UDF / UDAF / UDTF 完整指南
Apache Spark SQL 集成 Hive UDF / UDAF / UDTF 完整指南 导读 本文以 Apache Spark 官方 SQL 参考文档
大数据数据分析批处理流处理机器学习图计算
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考