首页 > 解决方案 > 如何避免 AWS/Glue 目录表更改列数据类型?

问题描述

我在我的 Glue 目录中以这种方式定义了表(通过 CF):

MyTable:
    Type: AWS::Glue::Table
    DependsOn : RealyseCatalogDB
    Properties:
      CatalogId: !Ref AWS::AccountId
      DatabaseName: !Ref CatalogDatabaseName
      TableInput:
        Name: 'customers'
        Description: Some test data
        TableType: EXTERNAL_TABLE
        Parameters: {
          "skip.header.line.count": "1",
          "compressionType": "none",
          "classification": "csv",
          "columnsOrdered": "true",
          "areColumnsQuoted": "true",
          "delimiter": ",",
          "typeOfData": "file"
        }
        StorageDescriptor:
          OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
          Columns:
            - Name: id
              Type: bigint
            - Name: startDate
              Type: date
            - Name: finalNumber
              Type: smallint
            - Name: price
              Type: int
            - Name: sumIndicator
              Type: tinyint
            - Name: officialName
              Type: string
          InputFormat: org.apache.hadoop.mapred.TextInputFormat
          Location: !Sub ${SomewhereS3BasePath}/MyFile.csv
          SerdeInfo:
            SerializationLibrary: org.apache.hadoop.hive.serde2.OpenCSVSerde

在我的 Glue/Spark 代码中,我使用以下方法从该表中读取数据:

val df = spark.glueContext.getCatalogSource(
  database = "test-db",
  tableName = "customers"
).getDynamicFrame().toDF()

但是类型date, tinyint,smallint被转换为字符串,而不是等效的 Spark 类型DateTypeByteTypeShortType。所以我被迫添加:

df
  .withColumn("startDate",col("startDate").cast(DateType))
  .withColumn("finalNumber",col("finalNumber").cast(ShortType))
  .withColumn("sumIndicator",col("sumIndicator").cast(ByteType))

这违背了在 CF 中定义表的目的。有什么办法可以避免这种情况吗?我尝试使用具有明确定义值的非常简单的测试数据来避免“resolveChoices”情况,但仍然是同样的问题。

标签: amazon-web-servicesaws-glueaws-glue-data-catalog

解决方案


这是由于 OpenCSVSerde 的限制,它将所有列数据类型视为字符串[1]。如果您想要列所需的数据类型,那么您可以通过利用 Glue applyMapping 转换来实现相同的目的,请参阅示例[2]


推荐阅读