
[英]Pulling data from SQL Server using Dask pyodbc, and SQLAlchemy
[英]Using Dask's NEW to_sql for improved efficiency (memory/speed) or alternative to get data from dask dataframe into SQL Server Table
我的最终目标是将 SQL/Python 一起用于一个数据太多的项目,pandas 无法处理(至少在我的机器上)。 所以,我已经与dask
一起去:
对于 #1 和 #2,它们使用最少的 memory (几个 SQL 查询约 200 行代码来处理带有 dask 的大型数据集)需要大约 30 秒的时间来执行。 又快又好玩!!!
但是,上面的#3 一直是主要瓶颈。 就(1. Memory 和 2. Speed(执行时间))而言,使用 dask 或其他替代方法完成 #3 有哪些有效方法? 查看更多背景信息,以及我尝试过的内容和得出的一些结论。
对于上面的#1、#2 和#3,由于 memory 限制/执行时间长,我发现这是一项不可能用 pandas 完成的任务,但是dask
通过飞行 Z62848E3I79804AA98B251 解决了上面的 #1 和 #2,但是是仍在为#3苦苦挣扎-以自动方式将数据返回到SQL表中,我没有发送到a.csv,然后导入SQL服务器。 I tried .compute()
to transform the dask dataframe to a pandas dataframe and then write to_sql
, but that kind of defeated the purpose of using dask to read/data model and again was running out of memory/taking forever to execute anyway.
因此,新计划是每天使用to_csv
生成一个 new.csv 并使用查询将数据批量插入到表中。 我认为这仍然是一个可行的解决方案; but, today, I was VERY happy to find out that dask released a new to_sql
function ( https://docs.dask.org/en/latest/dataframe-api.html#dask.dataframe.DataFrame.to_sql ). 利用有关此主题的现有 StackOverflow 文章/博客(例如来自 Francois Leblanc - https://leblancfg.com/benchmarks_writing_pandas_dataframe_SQL_Server.html ),我修补了所有参数的最有效组合来执行当您每天为报告编写大型数据集时,这很重要)。 这是我发现的,类似于很多关于pd.to_sql
的帖子,包括 Leblanc 的:
import sqlalchemy as sa
import dask.dataframe as dd
from dask.diagnostics import ProgressBar
pbar = ProgressBar()
pbar.register()
#windows authentication + fast_executemany=True
to_sql_uri = sa.create_engine(f'mssql://@{server}/{database}?trusted_connection=yes&driver={driver_name}', fast_executemany=True)
ddf.to_sql('PowerBI_Report', uri=to_sql_uri, if_exists='replace', index=False)
使用以下非默认参数的任意组合都会减慢我的to_sql
的执行时间(再次与 LeBlanc 在他的博客中提到的一致):
chunksize=40
(根据 2098 SQL 服务器参数限制,我可以为 52 列传递的最大值为 40),method='multi'
,parallel=True
) 注意:我意识到除了(或替代)传递chunksize=40
之外,我还可以遍历我的 33 个 dask dataframe 分区并单独处理每个块to_sql
。 这样 memory 的效率会更高,也可能更快。 一个分区需要 45 秒到 1 分钟,而一次完成整个 dask dataframe 对于所有分区需要 > 1 小时。 我将尝试遍历所有分区并发布更新,如果这样更快的话。 一个小时似乎很多,但当我尝试使用 pandas 进行计算时,我感到完全受阻,这需要整晚或用完 memory,所以这是一个步骤。 老实说,我对此感到很满意,我现在可能会使用pyinstaller
并让 .exe 每天运行,因此这是完全自动化的,go 从那里开始,但我认为这对其他人有帮助,因为在过去的几周里,我一直在努力解决各种解决方案。
我测试了通过循环在分区中将 dataframe 写入 SQL 服务器,而不是一次全部完成,完成所有内容的时间类似于一次编写所有内容。
import sqlalchemy as sa
import dask.dataframe as dd
from dask.diagnostics import ProgressBar
pbar = ProgressBar()
pbar.register()
#windows authentication + fast_executemany=True
to_sql_uri = sa.create_engine(f'mssql://@{server}/{database}?trusted_connection=yes&driver={driver_name}', fast_executemany=True)
# From my question, I have replaced the commented out line of code with everything below that to see if there was a significant increase in speed. There was not. It was about the same as the cod in the question.
# ddf.to_sql('PowerBI_Report', uri=to_sql_uri, if_exists='replace', index=False)
i = 0
for i in range(ddf.npartitions):
partition = ddf.get_partition(i)
if i == 0:
partition.to_sql('CDR_PBI_Report', uri=to_sql_uri, if_exists='replace', index=False)
if i > 0:
partition.to_sql('CDR_PBI_Report', uri=to_sql_uri, if_exists='append', index=False)
i += 1
选择将 dask 数据帧作为分区插入不应加快插入过程所需的总时间。
每次调用insert
时,无论是分区还是整条数据插入,都会调用.compute()
方法从 memory 中提取数据并使用,无法通过此优化。 我真的怀疑是否有必要提取分区,我认为在to_sql()
dask 方法背后已经使用了这种方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.