Synapse Analytics中复制活动比脚本活动执行同SQL查询慢的原因及优化
差异原因分析
- Copy活动与Script活动的执行逻辑本质不同:Copy活动需要依赖集成运行时(IR)完成资源调度,包括建立源数据库与存储的双向连接、初始化数据读写的框架组件,这些前置流程存在固定的启动开销,哪怕数据量极小也无法避免;而Script活动仅直接调用Azure SQL DB的引擎执行查询,无额外调度环节。
- 集成运行时的冷启动开销:若使用无服务器IR或按需启动的自托管IR,首次执行Copy活动时需要启动计算节点,这部分时间会被计入等待队列;Script活动不依赖IR的计算资源,无需等待节点启动。
- Copy活动默认配置的冗余:默认启用的数据一致性校验、分块读取等设置,对于小数据集来说属于不必要的额外开销,进一步拉长了等待时间。
Copy活动优化方案
- 保持集成运行时预热状态:针对无服务器IR,开启保持预热配置,让IR节点持续活跃,避免冷启动等待;若使用自托管IR,确保IR服务持续运行。
- 精简Copy活动配置:在源设置中关闭数据一致性校验,设置匹配结果行数的批量大小(比如设为100),减少不必要的初始化步骤。
- 切换为专用集成运行时:专用IR是持续运行的固定计算资源,不存在冷启动问题,适合频繁执行的小数据量任务。
替代Copy活动生成Parquet的方法
1. SQL存储过程+外部表(PolyBase)
预先在Azure SQL DB中创建指向Storage Gen2的Parquet格式外部表,然后通过存储过程执行查询并写入外部表,最后用Script活动调用该存储过程:
-- 创建外部数据源(指向Storage Gen2) CREATE EXTERNAL DATA SOURCE StorageGen2Source WITH ( LOCATION = 'abfss://container@yourstorage.dfs.core.windows.net', CREDENTIAL = StorageGen2Credential, TYPE = HADOOP ); -- 创建外部文件格式(Parquet) CREATE EXTERNAL FILE FORMAT ParquetFormat WITH ( FORMAT_TYPE = PARQUET, DATA_COMPRESSION = 'org.apache.hadoop.io.compress.SnappyCodec' ); -- 创建外部表 CREATE EXTERNAL TABLE ExternalParquetOutput ( -- 与查询结果匹配的字段定义 pk INT, -- 其他字段... ) WITH ( LOCATION = 'path/to/output/', DATA_SOURCE = StorageGen2Source, FILE_FORMAT = ParquetFormat ); -- 创建存储过程 CREATE PROCEDURE ExportChangesToParquet AS BEGIN TRUNCATE EXTERNAL TABLE ExternalParquetOutput; INSERT INTO ExternalParquetOutput SELECT * FROM myTable AS S RIGHT OUTER JOIN CHANGETABLE(CHANGES myTable,1) AS CT ON S.pk=CT.pk; END
在Synapse管道中用Script活动执行EXEC ExportChangesToParquet;即可。
2. Synapse Notebook(PySpark/Scala)
通过Notebook连接Azure SQL DB执行查询,再将结果写入Storage Gen2:
# PySpark示例代码 # 配置JDBC连接参数 jdbc_url = "jdbc:sqlserver://your-sql-server.database.windows.net:1433;databaseName=your-db" jdbc_properties = { "user": "your-username", "password": "your-password", "driver": "com.microsoft.sqlserver.jdbc.SQLServerDriver" } # 执行查询 query = """ SELECT * FROM myTable AS S RIGHT OUTER JOIN CHANGETABLE(CHANGES myTable,1) AS CT ON S.pk=CT.pk """ df = spark.read.jdbc(url=jdbc_url, table=f"({query}) AS temp", properties=jdbc_properties) # 写入Parquet到Storage Gen2 df.write.mode("overwrite").parquet("abfss://container@yourstorage.dfs.core.windows.net/path/to/output.parquet")
3. Lookup活动+辅助写入
利用Lookup活动执行SQL查询(支持最多5000行结果,你的场景完全适用),然后通过Azure Function或自定义活动将Lookup的输出序列化为Parquet格式写入Storage Gen2。
内容的提问来源于stack exchange,提问作者Jean-Christophe Rat-Patron
相关产品推荐
相关产品推荐

