Apache Spark SQL Hive Row Format 语法详解:SERDE 与 DELIMITED 的完整使用指南
2026/9/20 1:45:25 网站建设 项目流程
  • 大数据
  • 数据分析
  • 批处理
  • 流处理
  • 机器学习
  • 图计算

【免费下载链接】spark

Apache Spark - A unified analytics engine for large-scale data processing

项目地址:https://gitcode.com/gh_mirrors/sp/spark
点击查看免费下载

本文档是 Apache Spark 官方 SQL 语法参考系列的一部分,对应仓库文档 docs/sql-ref-syntax-hive-format.md。Hive Row Format 用于在CREATE TABLETRANSFORM(含MAP/REDUCE)等子句中指定 SerDe 类或文本分隔符,是打通 Spark 与 Hive 生态数据读写格式的关键语法。读完本文,你将掌握ROW FORMAT SERDEROW FORMAT DELIMITED两种定义方式、全部子句参数(字段/集合/Map/行分隔符、NULL 表示、转义字符)的语义与默认行为,并理解 Spark 解析器与 Hive 底层 SerDe 属性之间的映射规则。

一、概述(Description)

Spark 在CREATE TABLETRANSFORM子句中支持Hive row format,用于指定 SerDe 类或文本分隔符。CREATE TABLETRANSFORMrow_format有两种定义方式:

  1. SERDE子句:指定一个自定义的 SerDe 类(fully-qualified class name);
  2. DELIMITED子句:为原生 SerDe(native SerDe)指定分隔符(delimiter)、转义字符(escape character)、空值字符(null character)等。

从语法解析的实现看,这两种方式最终都会被解析成同一份SerdeInfo数据结构(定义于 statements.scala),它统一承载storedAsformatClassesserde类名与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 等完整建表子句列表)rowFormatcreateFileFormatlocationSpecbucketSpec等并列出现在建表选项列表中(见 SqlBaseParser.g4);
  • INSERT OVERWRITE (LOCAL) DIRECTORY:向目录写出数据时可指定rowFormatcreateFileFormat(见 SqlBaseParser.g4);
  • TRANSFORM / MAP / REDUCE 子句SELECT TRANSFORM(...) ... USING script的输入行格式inRowFormat与输出行格式outRowFormat(见 SqlBaseParser.g4)。

2.2 解析器如何构建 SerdeInfo

在 AstBuilder.scala 中,visitRowFormat根据语法树节点类型分发:

  • RowFormatSerdeContextvisitRowFormatSerde:把SERDE serde_name解析为SerdeInfo(serde = Some(name), serdeProperties = ...)WITH SERDEPROPERTIES中的键值对直接进入serdeProperties映射;
  • RowFormatDelimitedContextvisitRowFormatDelimited:把 DELIMITED 形态中的每个分隔符映射为对应名称的 SerDe 属性(详见下文第四节)。

三、参数说明(Parameters)

参数语义说明
SERDE serde_class指定自定义 SerDe 的完整限定类名(fully-qualified class name)必须给出可被类加载器加载的完整类路径,例如 Hive 生态常见的org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDeJsonSerDe
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 TABLETRANSFORM语法中均被支持。

四、DELIMITED 子句与底层 SerDe 属性的映射(源码级)

DELIMITED 形态的每个子句并不会被存成独立字段,而是被转换成 Hive SerDe 的serdePropertiesvisitRowFormatDelimited(见 AstBuilder.scala)逐项完成映射:

SQL 子句生成的 serdeProperties 键说明
FIELDS TERMINATED BYfield.delimserialization.format同时写入两个键,供不同 SerDe 解析使用
ESCAPED BYescape.delim转义字符
COLLECTION ITEMS TERMINATED BYcolelction.delim注意拼写为colelction(少一个 'l'),源码注释明确说明这是继承自 Hive 的拼写错误,必须沿用
MAP KEYS TERMINATED BYmapkey.delimMap 键值分隔符
LINES TERMINATED BYline.delim行分隔符
NULL DEFINED AS——源码中entry("null", ...)尚未实现,注释标注TODO we need proper support for the NULL format,即当前 DELIMITED 形态对 NULL 自定义值的支持仍属 TODO 状态

两个值得关注的实现细节:

  1. LINES TERMINATED BY 只接受'\n':当LINES TERMINATED BY的值不是"\n"时,解析器直接抛出QueryParsingErrors.unsupportedRowFormatLinesTerminatedByError(见 AstBuilder.scala)。这意味着在 Spark 中行分隔符实际上是固定为换行符的,无法像 Hive 那样自由指定行分隔符。
  2. 映射即 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 TRANSFORMMAP/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;

七、注意事项与限制(结合源码)

  1. 行分隔符受限LINES TERMINATED BY仅接受'\n',设置其他字符会在解析阶段直接报错(源码见 AstBuilder.scala)。
  2. colelction.delim拼写是历史遗留COLLECTION ITEMS TERMINATED BY映射到的属性键为colelction.delim(Hive 拼写错误),使用SERDEPROPERTIES直接手写属性时必须保持该拼写才能生效。
  3. NULL 自定义支持未完成NULL DEFINED AS在 DELIMITED 形态下尚未映射到任何 SerDe 属性(源码中有对应 TODO 注释),实际效果需要结合所用 SerDe 的自身属性(如 LazySimpleSerDe 的serialization.null.format)来实现。
  4. SERDE 与自带 SerDe 的文件格式不兼容:PARQUET、ORC 等格式自带序列化方案,不能与ROW FORMAT SERDE混用,否则建表报错。
  5. 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

项目地址:https://gitcode.com/gh_mirrors/sp/spark
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询