Python 将内存中的数据帧与数据库中非常大的持久化表连接起来?

Python 将内存中的数据帧与数据库中非常大的持久化表连接起来?,python,sql,sql-server,pandas,dask,Python,Sql,Sql Server,Pandas,Dask,我在内存中有一个数据帧,它有特定的标识符,使用这些标识符,我只想从RDBMS(Sql server)中持久化的非常大(5亿行)的表中获取相关数据 最好的方法是什么?绝对不想把整个桌子都放在内存中。也不能循环。若它是用于查找的单列键,我仍然可以考虑构建一个逗号分隔的字符串,并对该列表执行IN子句,但我有多个作为标识符的字段 我看到的唯一选择是将数据帧保存到db中,在db服务器上执行join并将数据带回。但是看起来很笨重 我已经读过关于dask作为一种选项的文章,但并不是很确定,因为将整个表放入内存

我在内存中有一个数据帧,它有特定的标识符,使用这些标识符,我只想从RDBMS(Sql server)中持久化的非常大(5亿行)的表中获取相关数据

最好的方法是什么?绝对不想把整个桌子都放在内存中。也不能循环。若它是用于查找的单列键,我仍然可以考虑构建一个逗号分隔的字符串,并对该列表执行IN子句,但我有多个作为标识符的字段

我看到的唯一选择是将数据帧保存到db中,在db服务器上执行join并将数据带回。但是看起来很笨重

我已经读过关于dask作为一种选项的文章,但并不是很确定,因为将整个表放入内存/磁盘对我来说仍然不是一种有效的技术

我看到的唯一选择是将数据帧保存到db中,在db服务器上执行join并将数据带回。但是看起来很笨重

就计算时间而言,这似乎是最有效的选择

我已经读过关于dask作为一种选项的文章,但并不是很确定,因为将整个表放入内存/磁盘对我来说仍然不是一种有效的技术

若您关心的条目的数据帧很小,那个么Dask数据帧可能不会立即将所有内容读入内存。它可能会在很小的空间内智能地扫描您的数据库。在这里使用Dask的实际成本是需要将数据移入和移出数据库,这取决于数据库连接器的速度

我会尝试一下,看看它的性能如何

我看到的唯一选择是将数据帧保存到db中,在db服务器上执行join并将数据带回。但是看起来很笨重

就计算时间而言,这似乎是最有效的选择

我已经读过关于dask作为一种选项的文章,但并不是很确定,因为将整个表放入内存/磁盘对我来说仍然不是一种有效的技术

若您关心的条目的数据帧很小,那个么Dask数据帧可能不会立即将所有内容读入内存。它可能会在很小的空间内智能地扫描您的数据库。在这里使用Dask的实际成本是需要将数据移入和移出数据库,这取决于数据库连接器的速度


我会尝试一下,看看它的性能如何。

现在我使用了一个带有表值参数(tvp)的存储过程,很好的一点是表值参数定义还可以定义字段上的索引。 Pyodbc在2018年实现了tvp,所以您所要做的就是创建一个列表列表作为参数,该参数与SQL Server中用户定义的表参数的数据类型相匹配。(感谢您在注释中提及表值参数)


现在,我已经使用了一个带有表值参数(tvp)的存储过程,很好的一点是表值参数定义还可以定义字段上的索引。 Pyodbc在2018年实现了tvp,所以您所要做的就是创建一个列表列表作为参数,该参数与SQL Server中用户定义的表参数的数据类型相匹配。(感谢您在注释中提及表值参数)


您可以尝试使用表值参数创建存储过程吗?@RaviDesai:那么如何将python数据帧发送到该表值参数中?不要构建CSV字符串:您正面临SQL注入攻击。使用SQL Alchemy的
以及
函数在查询期间过滤表,以便尽可能少的行返回Python。你可以从我的回答中得到一些想法:。用更多的细节编辑你的问题,这样我就可以给你写一个更有针对性的答案。你可以尝试用表值参数创建存储过程吗?@RaviDesai:那么你如何将python数据帧发送到该表值参数中呢?不要构建CSV字符串:你正面临SQL注入攻击。使用SQL Alchemy的
以及
函数在查询期间过滤表,以便尽可能少的行返回Python。你可以从我的回答中得到一些想法:。用更多的细节编辑你的问题,这样我可以给你写一个更有针对性的答案
import pandas as pd
import pyodbc

conn_string = 'DRIVER={ODBC Driver 17 for SQL Server};SERVER=test;DATABASE=test;UID=user;PWD=password'
conn = pyodbc.connect(conn_string)        
tvp = []
dt = datetime(2011, 3, 4)
tvp.append(['123', dt])
tvp.append(['222', dt])
tvp.append(['333', dt])
sql = "exec dbo.p_test_tvp_sp ?"
df = pd.read_sql(sql, conn, params=[tvp])