Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 加快从CSV文件插入到SQL Server的速度,而无需使用批量插入或熊猫到SQL_Python_Sql Server_Pandas_Pyodbc - Fatal编程技术网

Python 加快从CSV文件插入到SQL Server的速度,而无需使用批量插入或熊猫到SQL

Python 加快从CSV文件插入到SQL Server的速度,而无需使用批量插入或熊猫到SQL,python,sql-server,pandas,pyodbc,Python,Sql Server,Pandas,Pyodbc,我想把熊猫数据框作为一个整体放在MS SQL Server数据库的一个表中。像我这样的普通用户不允许批量插入。我正在使用pyodbc连接到我的数据库。我使用的是熊猫0.13.1。我在某个地方读到,从0.14版开始,您可以使用to_sql方法,因此它不适用于我的pandas dataframe。因此我使用了迭代器。我的数据帧有两列:Col1和Col2 我的代码正在运行,看起来像: from pyodbc import connect import pandasas pd df = pd.read

我想把熊猫数据框作为一个整体放在MS SQL Server数据库的一个表中。像我这样的普通用户不允许批量插入。我正在使用pyodbc连接到我的数据库。我使用的是熊猫0.13.1。我在某个地方读到,从0.14版开始,您可以使用to_sql方法,因此它不适用于我的pandas dataframe。因此我使用了迭代器。我的数据帧有两列:Col1和Col2

我的代码正在运行,看起来像:

from pyodbc import connect
import pandasas pd

df = pd.read_csv('PathToMyCSVfile', sep=';', header=0)

cnxn = connect(DRIVER = '{SQL Server}', SERVER = 'MyServer', DATABASE = 'MyDatabase')
cursor = cnxn.cursor()

for index, row in df.interrows():
  cursor.execute("INSERT INTO MySchema.MyTable VALUES (?,?)", df['Col1'][index], def['Col2'][index]
  cnxn.commit()
如上所述,上述代码正在工作,但速度很慢。。。
如何加快速度?

您面临的瓶颈是代码为数据帧中的每一行发送INSERT语句。也就是说,对于示例数据文件

id;文本
1.阿尔法
2.好极了
3.查理
4.三角洲
5.回声
6.狐步舞
7.高尔夫球运动
您需要七(7)次往返服务器才能发送等效的

插入MySchema.MyTable值(1,'alpha')
插入MySchema.MyTable值(2,'bravo')
插入MySchema.MyTable值(3,'charlie')
...
插入MySchema.MyTable值(7,'golf')
通过使用a在一次往返中执行相同的操作,您可以显著加快速度:

插入MySchema.MyTable值(1,'alpha'),(2,'bravo'),(3,'charlie'),(7,“高尔夫”)
下面的代码就是这样做的。当我使用5000行的文件测试它时,使用
rows\u per\u batch=1000(最大值)运行它比使用
rows\u per\u batch=1(相当于您当前的方法)快大约100倍

导入numpy
作为pd进口熊猫
导入pyodbc
导入时间
类MydInsert:
定义初始化(self、cnxn、sql存根、数据帧、每批行=1000):
#注意:SQL Server表值构造函数的硬限制为1000
self.\u rows\u per\u batch=1000,如果rows\u per\u batch>1000,其他情况下,rows\u per\u batch
自。_cnxn=cnxn
self.\u sql\u stub=sql\u stub
self.\u num\u columns=None
self.\u行\u占位符=无
self.\u num\u rows\u previous=无
self.\u all\u占位符=无
self.\u sql=None
行计数=0
参数列表=列表()
对于data_frame.itertuples()中的df_行:
param_list.append(tuple(df_row[1:])#省略基于零的行索引
行计数+=1
如果行数>=self.\u每批行数:
self._send_insert(参数列表)#发送整批
行计数=0
参数列表=列表()
self._send_insert(参数列表)#发送任何剩余行
定义发送插入(自身、参数列表):
如果len(参数列表)>0:
如果self.\u num\u列为无:
#打印(“[DEBUG](根据列数生成项目…))
#这种情况只发生一次
self.\u num\u columns=len(参数列表[0])
self.\u行\占位符=','。连接(['?'表示范围内的x(self.\u num\u列)])
#例如:“什么?”
行数=列(参数列表)
如果有行数!=self.\u num\u rows\u previous:
#打印(“[DEBUG](根据行数生成项目…))
self._all_占位符='({})'.format('),('.join([self._row_占位符用于范围内的x(num_rows)])
#例如:“(?,?),(?,?),(?,?)”
self.\u sql=f'{self.\u sql\u stub}值{self.\u all\u占位符}'
self.\u num\u rows\u previous=num\u rows
params=[int(element)if isinstance(element,numpy.int64)else元素
对于参数列表中的行,对于行中的元素]
#打印('[DEBUG]sql:'+repr(self.\u sql))
#打印('[DEBUG]参数:'+repr(参数))
crsr=self.\u cnxn.cursor()
crsr.execute(self.\u sql,params)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
连接线=(
'DRIVER=SQL Server的ODBC驱动程序11;'
'服务器=192.168.1.13449242;'
'Trusted_Connection=yes;'
)
cnxn=pyodbc.connect(conn_str,autocommit=True)
crsr=cnxn.cursor()
crsr.execute(“创建表#tmp(id INT主键,txt NVARCHAR(50))”)
df=pd.read_csv(r'C:\Users\Gord\Desktop\Query1.txt',sep=';',header=0)
t0=时间。时间()
MyDfInsert(cnxn,“插入到#tmp(id,txt)”,df,每批行数=1000)
打印()
打印(f'插入在{time.time()-t0:.2f}秒内完成。“)
cnxn.close()

可能重复@IgnacioVergaraKausel我不认为它是重复的。我的服务器上不允许大容量插入。另外,可能的副本提到executemany是一个包装器,而不是一种不同的方法,因此我认为它不会比我使用的execute快(很多)。Thanx@Gord Thompson,我复制了脚本并调整了驱动程序、服务器和csv文件等内容。我还用格式化字符串替换了行
self.\u sql='{0}值{1}'。format(self.\u sql\u stub,self.\u all\u占位符)
,因为我使用的是Python 2.7。这本应该有效,但没有。Pyodbc-error 42000被引发,表明参数数量超过了最大参数数量(2100)。您提到这个表值构造函数的硬限制是1000。在CSV文件中有两列。我猜1000是2100除以2列得到的。所以我用8列除以2100=262.50。我用250替换了你的1000,效果很好!Thanx的主要目标是加快速度。这个目标实现了:我的方法用了1074秒,你的方法用了32秒。速度大幅度提高@MA53QXR re:“我猜1000是2100除以2列得出的”-不,T-SQL表值构造函数被限制为1000行,而不管列数如何。对参数数量的限制是另一种限制,很可能是由于SQL语句最终由系统存储过程执行(可能是
sp_prepexec
)。