使用MySqlToGoogleCloudStorageOperator对记录进行分页

时间:2018-10-11 06:37:55

标签: airflow

我的工作流程是:

  1. 我正在从变量LAST_IMPORTED_ORDER_ID中获取当前的最大订单ID
  2. 我在order_id数据库中获得了最大的MySQL
  3. 使用LAST_IMPORTED_ORDER_ID导入xcomMySQL的{​​{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

enter image description here

还要注意MySqlToGoogleCloudStorageOperator,我也没有在日志中看到该值。

我该如何解决?

1 个答案:

答案 0 :(得分:2)

不幸的是,对于您来说,操作员无法修改其DAG。由于您只能在操作员执行中拉入xcom,因此建议您在循环设置的最后,而不是将操作员添加到DAG中运算符,在循环内,调用:

import_orders_op.pre_execute(**kwargs)
import_orders_op.execute(**kwargs)

有点麻烦,因为所有日志输出都将放在任务chunck_import中,您可能想为自己进行逻辑重命名(import_in_chunks?),但这应该工作,而DAG不会更改每次运行的确切任务数。

或者,我认为这甚至是kludgier,假设最大数量的块,为每个基于块的范围设置一对ShortCircuitOperatorMySqlToGoogleCloudStorageOperatorShortCircuitOperator应该检查块的起始范围是否有效,如果有效,则运行sql 2 gcs op,否则运行短路。

更好的方法是将MySqlToGoogleCloudStorageOperator子类化为PagedMySqlToGCSOperator,重写execute_query_mysql_write_local_data_files。不过,这还需要更多工作。