我的工作流程是:
LAST_IMPORTED_ORDER_ID
中获取当前的最大订单ID order_id
数据库中获得了最大的MySQL
LAST_IMPORTED_ORDER_ID
导入xcom
到MySQL
的{{1}}中的值之间的订单到目前为止,一切都很好,而且效果很好。
问题是值之间的差距太大时。可以是MySqlToGoogleCloudStorageOperator
个订单。一次导入那么多记录是不可能的。
500K
可以使用MySqlToGoogleCloudStorageOperator
将存储在文件中的文件拆分为多个块,但不能对查询本身进行分块。
基本上,我想做的是使用诸如分页之类的查询。如果
approx_max_file_size_bytes
然后中断查询最多5万行,这意味着我需要动态创建运算符。
这是我试图做的:
xcom_order_id - LAST_IMPORTED_ORDER_ID > 50K
这没有错误,可以成功运行,但是什么也没做。
LAST_IMPORTED_ORDER_ID = Variable.get("last_order_id_imported")
start_task_op = DummyOperator(task_id='start_task', dag=dag)
def chunck_import(**kwargs):
ti = kwargs['ti']
xcom = int(ti.xcom_pull(task_ids='get_max_order_id_2_months_ago'))
current = int(LAST_IMPORTED_ORDER_ID)
if xcom - current < 50000:
num_pages = 1
else:
num_pages = int((xcom / current) + 1)
logging.info(xcom)
logging.info(current)
for i in range(1, num_pages + 1): #for 1 page its range(1,2)
start = LAST_IMPORTED_ORDER_ID * i
end = start + 50000
if end > xcom:
end = xcom
import_orders_op = MySqlToGoogleCloudStorageOperator(
task_id='import_orders_and_upload_to_storage_orders-{}'.format(i),
mysql_conn_id='mysqlcon',
google_cloud_storage_conn_id='googlecon',
provide_context=True,
approx_max_file_size_bytes=100000000,
sql='select * from e.orders where orders_id between {{ params.start }} and {{ params.end }}',
params={'start': start, 'end': end},
bucket=GCS_BUCKET_ID,
filename=file_name_orders,
dag=dag)
chunck_import_op = PythonOperator(
task_id='chunck_import',
provide_context=True,
python_callable=chunck_import,
dag=dag)
start_task_op >> get_max_order_id_2_months_ago >> chunck_import_op
中的值正确。但XCOM
不做任何事情。另外,我在用户界面中也看不到动态创建的chunck_import_op
:
还要注意MySqlToGoogleCloudStorageOperator
,我也没有在日志中看到该值。
我该如何解决?
答案 0 :(得分:2)
不幸的是,对于您来说,操作员无法修改其DAG。由于您只能在操作员执行中拉入xcom,因此建议您在循环设置的最后,而不是将操作员添加到DAG中运算符,在循环内,调用:
import_orders_op.pre_execute(**kwargs)
import_orders_op.execute(**kwargs)
有点麻烦,因为所有日志输出都将放在任务chunck_import
中,您可能想为自己进行逻辑重命名(import_in_chunks
?),但这应该工作,而DAG不会更改每次运行的确切任务数。
或者,我认为这甚至是kludgier,假设最大数量的块,为每个基于块的范围设置一对ShortCircuitOperator
和MySqlToGoogleCloudStorageOperator
。 ShortCircuitOperator
应该检查块的起始范围是否有效,如果有效,则运行sql 2 gcs op,否则运行短路。
更好的方法是将MySqlToGoogleCloudStorageOperator子类化为PagedMySqlToGCSOperator,重写execute
,_query_mysql
和_write_local_data_files
。不过,这还需要更多工作。