mysql - AWS Glue 未将 id(int) 列复制到 Redshift - 它是空白的

标签 mysql amazon-web-services pyspark amazon-redshift aws-glue

Glue 有一个非常奇怪的问题。使用它对我从 MySQL RDS 迁移到 Redshift 的数据运行一些 ETL。使用我在另一个表上使用的相同代码,它运行良好并按应有的方式复制了所有数据。

但是在第二个表上,由于某种原因,它不会从 MySQL 复制 id 列中的数据。 Redshift 上的 id 列完全空白。

query_df = spark.read.format("jdbc").option("url", 
args['RDSURL']).option("driver", 
args['RDSDRIVER']).option("dbtable", 
args['RDSQUERY']).option("user", args['RDSUSER']).option("password", 
args['RDSPASS']).load()

datasource0 = DynamicFrame.fromDF(query_df, glueContext, 
"datasource0")

logging.info(datasource0.show())

applymapping1 = ApplyMapping.apply(frame = datasource0, mappings = 
[("id", "int", "id", "int"), ... , transformation_ctx = 
"applymapping1")

logging.info(applymapping1.show())

从上面打印的日志中,我可以看到即使在 ApplyMapping 之后动态框架也包含 id 字段。
datasink2 = glueContext.write_dynamic_frame.from_jdbc_conf(frame = 
applymapping1, catalog_connection = args['RSCLUSTER'], 
connection_options = {"dbtable": args['RSTABLE'], "database": 
args['RSDB']}, redshift_tmp_dir = args["TempDir"], 
transformation_ctx = "datasink2")

我认为问题似乎发生在这里?在此作业完成后,在检查 Redshift 时,id 列完全为空。

对这种行为感到非常困惑。确切的代码在另一个表上运行良好,这两个表中的 id 之间的唯一区别是该表的 id 为 int (11) unsigned 而代码工作的表的 id 为 int (10) 签名。

最佳答案

我使用 Glue 从 MySQL RDS 中提取正是这种行为。对于寻求此答案的任何人 - 原因如下:AWSGlue 具有“类型选择”的概念,其中爬网列的确切类型可以在整个 ETL 作业中保留为多种可能性,因为爬网程序只爬网列数据的子集,以确定可能的类型,但不能明确决定。这就是为什么转换为使用显式架构而不是爬虫会解决问题的原因,因为它不涉及任何类型选择。
当作业运行时(或者您查看预览),Spark 将尝试处理整个列数据集。此时,列类型可能被解析为与数据集不兼容的类型 - 即解释器无法决定正确的类型选择,这会导致相关列的数据为空。我在转换 MySQL 数据库中的许多表时遇到过这种情况,并且没有明显的模式说明为什么有些失败,有些没有,尽管我能够确定它 必须与源数据库列中的数据相关。
解决方案是将选项的显式解析添加到您的脚本中,方法是将失败的列转换为所需的目标类型,如下所示:

df.resolveChoice(specs = [('id', 'cast:int')])
其中 df 是数据框。这将强制将该列解释为预期类型,并应在该列中产生预期的数据输出。这一直对我有用。
请注意,对于使用 Glue Studio 可视化编辑器的用户,现在可以添加“自定义转换”步骤,其中包含为您执行此操作的代码。在这种情况下,转换代码应如下所示:
def MyTransform (glueContext, dfc) -> DynamicFrameCollection:
df = dfc.select(list(dfc.keys())[0])
df_resolved = df.resolveChoice(specs = [('id', 'cast:int')])
return (DynamicFrameCollection({"CustomTransform0": df_resolved}, glueContext))
还要注意,在这种情况下,有必要使用“从集合中选择”转换来跟随此自定义转换节点,因为自定义转换返回的是一个集合而不是单个帧。

关于mysql - AWS Glue 未将 id(int) 列复制到 Redshift - 它是空白的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54468084/

相关文章:

php - 在 PHP 中,当我使用 PDO 调用 MySQL 存储过程,然后进行另一个查询时,出现错误 :

php - 如何创建一个具有自动增量但不从 1 开始而是从所需数字开始的交易编号

mysql - 为什么我无法远程访问 Amazon RDS 上的 MySQL?

linux - 如何修复 aws ec2 的启动脚本,以显示 hello world,来自 169.254.169.254 的其他元数据

javascript - 如何使用 JavaScript 更新 s3 中现有对象的元数据?

apache-spark - __HIVE_DEFAULT_PARTITION__ 作为胶水 ETL 作业中的分区值

apache-spark - Spark-Hudi : Save as table to Glue/Hive catalog

PHP 和 MySQL 形式,我做错了什么?

php - 使用 MySQL 和 PHP 查找 Row 是否有两个给定值

python - PySpark:TypeError:StructType 无法接受类型 <type 'numpy.float64' > 中的对象 0.10000000000000001