PySpark/Aws Glue 中的性能问题
Performance issue in PySpark/Aws Glue
我有一个数据框。我需要将每条记录转换为 JSON,然后使用 JSON 有效负载调用 API 以将数据插入 postgress。我在数据框中有 14000 条记录并调用 api 并得到响应,这需要 5 个小时。有什么办法可以提高性能。下面是我的代码片段。
df_insert = spark.read \
.format(SNOWFLAKE_SOURCE_NAME) \
.options(**sfOptions) \
.option("dbtable", "source_table_name") \
.load()
json_insert = df_insert.toJSON().collect()
for row in json_insert:
line = json.loads(row)
headers = {
'Authorization': authorization,
'content-type': "application/json",
'cache-control': "no-cache",
}
response = requests.request("POST", url_insert, data=payload, headers=headers)
print(response.text)
res = response.text
response_result = json.loads(res)
#print(response_result["httpStatus"])
if response_result["message"] == 'success':
print ("INFO : Record inserted successfully")
else:
print ("ERROR : Error in the record")
status_code = response_result["status"]
error_message = response_result["error"]
my_list = [(status_code,error_message,row)]
df = sc.createDataFrame(my_list, ['status', 'error', 'json data'])
df.write.format(SNOWFLAKE_SOURCE_NAME) \
.options(**sfOptions) \
.option("dbtable", "error_table") \
.option("header", "true") \
.option("truncate_table", "on") \
.mode("append") \
.save()
注意:我知道通过 "json_insert = df_insert.toJSON().collect()" 我正在失去数据帧的优势。有没有更好的方法来完成。
df_insert.toJSON()
returns 一个 RDD
你可以 flatMap
过去。
1
source_rdd = df_insert.toJSON()
对该 RDD 执行 flatMap
并取回仅包含错误的 RDD。
headers = {
'Authorization': authorization,
'content-type': "application/json",
'cache-control': "no-cache"
}
def post_service_error(row):
# requests package may not be available in the node
# see about adding files to the spark context
response = requests.request("POST", url_insert, data=row, headers=headers)
response_result = response.json()
if response_result['message'] == 'success':
print ("INFO : Record inserted successfully")
return []
print ("ERROR : Error in the record")
status_code = response_result["status"]
error_message = response_result["error"]
return [(status_code, error_message, row)]
errors_rdd = source_rdd.flatMap(post_service_error)
将错误 RDD 转换为 spark DataFrame 并将其保存到 table。
errors_df = sc.createDataFrame(errors_rdd, ['status', 'error', 'json data'])
(errors_df.write.format(SNOWFLAKE_SOURCE_NAME)
.options(**sfOptions)
.option("dbtable", "error_table")
.option("header", "true")
.option("truncate_table", "on")
.mode("append")
.save())
如果您拥有正在请求的 API,我建议探索一种接受一批 objects/arrays 的实现。
这样你就可以在将每个分区映射到批处理请求之前对 RDD 进行分区,然后处理错误。
我有一个数据框。我需要将每条记录转换为 JSON,然后使用 JSON 有效负载调用 API 以将数据插入 postgress。我在数据框中有 14000 条记录并调用 api 并得到响应,这需要 5 个小时。有什么办法可以提高性能。下面是我的代码片段。
df_insert = spark.read \
.format(SNOWFLAKE_SOURCE_NAME) \
.options(**sfOptions) \
.option("dbtable", "source_table_name") \
.load()
json_insert = df_insert.toJSON().collect()
for row in json_insert:
line = json.loads(row)
headers = {
'Authorization': authorization,
'content-type': "application/json",
'cache-control': "no-cache",
}
response = requests.request("POST", url_insert, data=payload, headers=headers)
print(response.text)
res = response.text
response_result = json.loads(res)
#print(response_result["httpStatus"])
if response_result["message"] == 'success':
print ("INFO : Record inserted successfully")
else:
print ("ERROR : Error in the record")
status_code = response_result["status"]
error_message = response_result["error"]
my_list = [(status_code,error_message,row)]
df = sc.createDataFrame(my_list, ['status', 'error', 'json data'])
df.write.format(SNOWFLAKE_SOURCE_NAME) \
.options(**sfOptions) \
.option("dbtable", "error_table") \
.option("header", "true") \
.option("truncate_table", "on") \
.mode("append") \
.save()
注意:我知道通过 "json_insert = df_insert.toJSON().collect()" 我正在失去数据帧的优势。有没有更好的方法来完成。
df_insert.toJSON()
returns 一个 RDD
你可以 flatMap
过去。
1
source_rdd = df_insert.toJSON()
对该 RDD 执行 flatMap
并取回仅包含错误的 RDD。
headers = {
'Authorization': authorization,
'content-type': "application/json",
'cache-control': "no-cache"
}
def post_service_error(row):
# requests package may not be available in the node
# see about adding files to the spark context
response = requests.request("POST", url_insert, data=row, headers=headers)
response_result = response.json()
if response_result['message'] == 'success':
print ("INFO : Record inserted successfully")
return []
print ("ERROR : Error in the record")
status_code = response_result["status"]
error_message = response_result["error"]
return [(status_code, error_message, row)]
errors_rdd = source_rdd.flatMap(post_service_error)
将错误 RDD 转换为 spark DataFrame 并将其保存到 table。
errors_df = sc.createDataFrame(errors_rdd, ['status', 'error', 'json data'])
(errors_df.write.format(SNOWFLAKE_SOURCE_NAME)
.options(**sfOptions)
.option("dbtable", "error_table")
.option("header", "true")
.option("truncate_table", "on")
.mode("append")
.save())
如果您拥有正在请求的 API,我建议探索一种接受一批 objects/arrays 的实现。 这样你就可以在将每个分区映射到批处理请求之前对 RDD 进行分区,然后处理错误。