Apache spark Spark 2.3.1 AWS EMR未返回某些列的数据,但在Athena/Presto和Spectrum中仍有效

Apache spark Spark 2.3.1 AWS EMR未返回某些列的数据,但在Athena/Presto和Spectrum中仍有效,apache-spark,amazon-emr,Apache Spark,Amazon Emr,我正在AWS EMR(Python 2.7.14)上的Spark 2.3.1上使用PySpark 此操作不返回数据,未找到0行。 上表中每行的每个值都返回Null。 数据存储在拼花地板中。 当我在AWS Athena/Presto或AWS Redshift Spectrum上运行相同的SQL查询时,我得到了正确返回的所有列数据(大多数列值不为null) 这是返回正确数据的Athena SQL和红移SQL查询: select "message.country" from datalake.lead

我正在AWS EMR(Python 2.7.14)上的Spark 2.3.1上使用PySpark

此操作不返回数据,未找到0行。 上表中每行的每个值都返回Null。 数据存储在拼花地板中。

当我在AWS Athena/Presto或AWS Redshift Spectrum上运行相同的SQL查询时,我得到了正确返回的所有列数据(大多数列值不为null)

这是返回正确数据的Athena SQL和红移SQL查询:

select "message.country" from datalake.leads_notification where "message.country" is not null limit 10;
我在所有情况下都使用AWS胶水目录。 上面的列未分区,但表在其他列上分区。我试着用修理台,但没用。 i、 e.MSCK维修表datalake.leads\u通知

我尝试了Schema Merge=True,如下所示:

spark = SparkSession \
    .builder \
    .appName("Python Spark SQL data source example") \
    .config("hive.metastore.client.factory.class", "com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory") \
    .config("hive.exec.dynamic.partition", "true") \
    .config("spark.sql.parquet.mergeSchema", "true") \
    .config("hive.exec.dynamic.partition.mode", "nonstrict") \
    .config("spark.debug.maxToStringFields", 200) \
    .enableHiveSupport() \
    .getOrCreate()
没有区别,一列的每一个值都是空的,即使有些值不是空的

此列是作为表的最后一列添加的,因此大多数数据确实为null,但某些行不是null。该列最后列在目录中的列列表上,位于分区列的正上方

尽管如此,Athena/Presto仍检索所有非空值,红移光谱也是如此,但alas EMR Spark 2.3.1 PySpark将此列的所有值显示为“空”。正确检索Spark中的所有其他列

有人能帮我调试这个问题吗

由于输出格式的原因,在此处很难剪切和粘贴配置单元架构

***CREATE TABLE datalake.leads_notification(
  message.environment.siteorigin string, 
  dcpheader.dcploaddateutc string, 
  message.id int, 
  message.country string, 
  message.financepackage.id string, 
  message.financepackage.version string)
PARTITIONED BY ( 
  partition_year_utc string, 
  partition_month_utc string, 
  partition_day_utc string, 
  job_run_guid string)
ROW FORMAT SERDE 
  'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION
  's3://blahblah/leads_notification/leads_notification/'
TBLPROPERTIES (
  'CrawlerSchemaDeserializerVersion'='1.0', 
  'CrawlerSchemaSerializerVersion'='1.0', 
  'UPDATED_BY_CRAWLER'='weekly_datalake_crawler', 
  'averageRecordSize'='3136', 
  'classification'='parquet', 
  'compressionType'='none', 
  'objectCount'='2', 
  'recordCount'='897025', 
  'sizeKey'='1573529662', 
  'spark.sql.create.version'='2.2 or prior', 
  'spark.sql.sources.schema.numPartCols'='4', 
  'spark.sql.sources.schema.numParts'='3', 
  'spark.sql.sources.schema.partCol.0'='partition_year_utc', 
  'spark.sql.sources.schema.partCol.1'='partition_month_utc', 
  'spark.sql.sources.schema.partCol.2'='partition_day_utc', 
  'spark.sql.sources.schema.partCol.3'='job_run_guid', 
  'typeOfData'='file')***
最后3列在Spark中都有相同的问题:

message.country string, 
message.financepackage.id string, 
message.financepackage.version string
在雅典娜/普雷斯托和红移光谱中使用相同的目录返回OK

我为我的编辑道歉


谢谢

执行步骤5架构检查:

我敢打赌,拼花地板定义中的这些新列名要么是大写(而其他列名是小写),要么是拼花地板定义中的新列名是小写(而其他列名是大写)

这就是解决方案:注意

 .config("spark.sql.hive.convertMetastoreParquet", "false") 
模式列都是小写的,模式是由AWS Glue创建的,不是由我的自定义代码创建的,所以我不知道是什么导致了问题,所以当模式创建不在您的直接控制之下时,使用上面的设置可能是安全的默认设置。这是一个很大的陷阱,所以我希望这会在将来帮助其他人。 感谢Tooptop4指出了这篇文章:


请将表格的模式添加到问题中。可以使用配置单元cli使用此命令:show create table datalake.leads\u通知;编辑过,得剪栏目,这是一个非常大的表格架构,100+栏目谢谢!这似乎已经解决了问题,我将发布最后的会话配置供所有人在下面查看。@如果有效,请接受答案,谢谢!完成了,非常感谢,这对生产部署来说是一个重大的解脱!!
spark = SparkSession \
        .builder \
        .appName("Python Spark SQL data source example") \
        .config("hive.metastore.client.factory.class", "com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory") \
        .config("hive.exec.dynamic.partition", "true") \
        .config("spark.sql.parquet.mergeSchema", "true") \
        .config("spark.sql.hive.convertMetastoreParquet", "false") \
        .config("hive.exec.dynamic.partition.mode", "nonstrict") \
        .config("spark.debug.maxToStringFields", 200) \
        .enableHiveSupport() \
        .getOrCreate()
 .config("spark.sql.hive.convertMetastoreParquet", "false")