问题陈述:
我们的数据存储在Azure Data Lake Storage Gen 2上,我们每天需要处理大约2500万条记录(30列)到Azure SQL Server数据库中。我们正在使用Databricks和PySpark代码从Delta Table中检索此数据,并将此数据加载到SQL Server数据库表中。
目前,我们正在尝试使用500万条记录的样本来调整我们的ETL过程,这平均需要25分钟。我们正在寻找如何进一步减少这一时间的提示和技巧,因为在我们的生产环境中,我们每天应该处理2500万条记录。
技术设置:
- 数据块集群:*
- 4个执行器,每个执行器4个内核,8 GB内存
- 驱动程序具有8 GB内存和4个核心
- Apache 12.2 LTS,包含Apache Spark 3.3.2
- SQL数据库 *:
- 标准型S2
- 50 DTU
代码示例:
dataframe = spark.table("hive_metastore.catalog.table") #5M records
dataframe_repartioned = dataframe.repartition(64)
sql_host_name = f'sql_server_hostname'
sql_db_name = f'sql_server_database'
sql_user_id = "admin"
sql_server_pwd = "***"
jdbc_url = f'jdbc:sqlserver://{sql_host_name}:1433;databaseName={sql_db_name};user={sql_user_id};password={sql_server_pwd};'
dataframe_repartioned.write \
.format("com.microsoft.sqlserver.jdbc.spark") \
.option("truncate", "true") \
.option("url", jdbc_url) \
.option("dbtable", "schema.TABLE") \
.option("tableLock", "true") \
.option("batchsize", "10000") \
.option("numPartitions", 64) \
.mode("overwrite") \
.save()
字符串
在谷歌搜索和阅读Stackoverflow上的类似问题后,我们已经尝试了以下方法:
在SQL数据库表中为nvarchars应用适当的长度:
- 最初所有的nvarchar列都是nvarchar(max)
- 我们将其更改为更适用的长度,在大多数情况下为nvarchar(10)
- 这将我们的处理时间从35 -> 25分钟缩短
在写入SQL Server数据库之前重新分区我们的框架: - 我们注意到,在将Delta表阅读到一个嵌套框架中之后,它全部位于一个分区中
- 我们把这个框架重新划分成64个分区
- 这对整个处理时间的影响很小(减少了45秒)
使用其他JDBC连接,而不是Databricks默认连接: - 一些文章/帖子建议使用com.microsoft.sqlserver.jdbc.spark连接器
- 我们将代码更改为使用此代码,但它没有任何影响
我们确实看到,在插入过程中,我们的Azure SQL数据库的DTU使用率上限为100%。当我们将Azure SQL数据库从S2 -> S3(从50 -> 100 DTU提高一倍性能)增加时,处理时间减少了4分钟。但5 M记录仍然需要21分钟。
是否有任何方法可以提高我们的写入效率,或者是增加Azure SQL数据库可用DTU的唯一解决方案?.option("batchsize", "10000")
似乎也没有任何影响。.option("tableLock", "true")
确实减少了1分钟的处理时间。
1条答案
按热度按时间vddsk6oq1#
经过进一步的性能测试,我们注意到Spark端的额外调优没有太大影响,但增加Azure SQL Server数据库层有非常大的影响。
每个服务层500万条记录的处理时间:
我们决定扩展Azure SQL数据库,并将在ETL过程中研究自动扩展Azure SQL数据库的选项。