如何防止Spark查询CSV格式Glue Catalog数据源时包含表头行
问题原因
Spark默认不会读取Glue Catalog中CSV表Serde参数里的skip.header.line.count配置,该配置仅对Athena(Presto引擎)生效,所以直接通过spark.sql()查询CSV表时会把表头行当作普通数据返回。
可行的解决方案
方案1:修改Glue Catalog表配置(一次修改永久生效)
在现有Glue表的**表属性(TBLPROPERTIES)**中新增两个配置,无需修改作业代码:
spark.sql.sources.options.header=truespark.sql.sources.options.skipHeader=1
配置完成后Spark再读取该表时会自动跳过第一行表头,和Athena的查询行为一致。
方案2:作业代码中显式指定表头配置(无需修改元数据)
如果不方便修改Glue Catalog的表配置,可以调整作业代码,先显式读取源CSV数据并指定跳过表头,再注册临时视图执行你的查询逻辑,示例调整后的代码如下:
from pyspark.context import SparkContext from pyspark.sql.session import SparkSession glue_source_database_name = 'source_database' glue_destination_database_name = 'destination_database' table_name = 'diamonds10_csv' partition_count = 5 s3_output_path = "你的S3输出路径" merge_query = 'SELECT SEQ.`sn`,SEQ.`carat`,SEQ.`cut`,SEQ.`color`,SEQ.`clarity`,SEQ.`depth`,SEQ.`table`,SEQ.`price`,SEQ.`x`,SEQ.`y`,SEQ.`z` FROM ( SELECT SUB.`sn`,SUB.`carat`,SUB.`cut`,SUB.`color`,SUB.`clarity`,SUB.`depth`,SUB.`table`,SUB.`price`,SUB.`x`,SUB.`y`,SUB.`z`, ROW_NUMBER() OVER ( PARTITION BY SUB.`sn` ORDER BY SUB.`price` DESC ) AS test_diamond FROM temp_diamonds_view AS SUB) AS SEQ WHERE SEQ.test_diamond = 1' spark_context = SparkContext.getOrCreate() spark = SparkSession( spark_context ) # 新增部分:获取源表存储路径,显式读取CSV并跳过表头 source_table = spark.sql(f"DESCRIBE FORMATTED {glue_source_database_name}.{table_name}") source_location = source_table.filter("col_name == 'Location'").select("data_type").collect()[0][0] df = spark.read.option("header", "true").option("skipHeader", "1").csv(source_location) # 注册临时视图供SQL查询使用 df.createOrReplaceTempView("temp_diamonds_view") targettable = spark.sql(merge_query) targettable.repartition(partition_count).write.option("path",f'{s3_output_path}/{table_name}').mode("overwrite").format("parquet").saveAsTable(f'`{glue_destination_database_name}`.`{table_name}`')
方案3:SQL查询中直接过滤表头行(临时应急方案)
如果你确定表头行的sn字段值就是字符串sn,可以直接在你的查询语句的子查询中新增过滤条件WHERE SUB.sn != 'sn'即可排除表头行,无需修改其他配置。
内容的提问来源于stack exchange,提问作者Brandon
相关产品推荐
相关产品推荐

