我非常清楚有很多类似的问题,并且大多数答案都暗示了诸如CSV批量插入(这比从R导出更让人头疼)之类的事情。
但是,我不知道与R进行任何比较,它可以解决pandas.DataFrame.to_sql()
是否能够达到与R的DBI::dbWriteTable
相同的速度。
我在Windows 10机器上运行Anaconda。作为测试,我将导出15个表,每个表具有10,000行,30列随机浮点数和3个字符串列。
时间是:
我尝试了pymssql,但无法正常工作(请参见代码中的注释)。
fast_executemany
是一个很大的改进,但仍需要花费R几乎两倍的时间。与R的区别令人惊讶!并且这也表明该连接本质上没有错到SQL服务器。
如果答案是:“不,R会更快,周期”,那么有人可以解释为什么吗?了解造成差异的原因将非常有趣。
对于巨型表,我可能会考虑将其导出为镶木地板或羽毛状的格式,让R读取它们,然后导出为R的SQL。但是,对于中型表(30到200 MB数据之间的任何数据)我宁愿在Python中找到更好的解决方案。
PS这是一个SQL Server Express,它运行在与我运行Python和R相同的PC上。
为回应评论,我比较了不同大小的执行时间,R的时间与pyodbc的时间比例似乎相当恒定。一点点地考虑一下-我不是数据库专家,很可能我缺少数据库配置或其他因素,这些因素正在起作用。底线仍然是,就我而言,R几乎快两倍。
我的代码:
import numpy as np
import pandas as pd
import timeit
from sqlalchemy import create_engine #, MetaData, Table, select
import pymssql
ServerName = myserver
Database = mydb
params = '?driver=SQL+Server+Native+Client+11.0'
# we define the pyodbc connection
engine_pyo = create_engine('mssql+pyodbc://' + ServerName + '/' + Database + params,
encoding='latin1', fast_executemany=True)
conn_pyo = engine_pyo.connect()
# now the turbodbc
engine_turbo = create_engine('mssql+turbodbc://' + ServerName + '/' + Database + params, encoding='latin1')
conn_turbo = engine_turbo.connect()
# pymssql is installed but doesn't work.
# I get:
# connect() got an unexpected keyword argument 'driver'
#engine_pyms = create_engine('mssql+pymssql://' + ServerName + '/' + Database + params, encoding='latin1')
#conn_pyms = engine_pyms.connect()
sheets = 15
rows= int(10e3)
def create_data(sheets, rows):
df = {} # dictionary of dataframes
for i in range(sheets):
df[i] = pd.DataFrame(data= np.random.rand(rows,30) )
df[i]['a'] = 'some long random text'
df[i]['b'] = 'some more random text'
df[i]['c'] = 'yet more text'
return df
def data_to_sql(df, conn):
for d in df:
df[d].to_sql('Test ' + str(d) , conn, if_exists='replace' )
#NB: df is a dictionary containing dataframes - it is NOT a dataframe
# df[key] is a dataframe
df = create_data(sheets, rows)
rep = 1
n = 1
t_pyodbc = timeit.Timer( "data_to_sql(df, conn_pyo)" , globals=globals() ).repeat(repeat = rep, number = n)
t_turbo = timeit.Timer( "data_to_sql(df, conn_turbo)" , globals=globals() ).repeat(repeat = rep, number = n)
我的R代码:
library(tictoc)
library(readxl)
library(tidyverse)
library(dplyr)
library(dbplyr)
library(DBI)
tic("data creation")
rows = 10000
cols = 30
tables = 15
dataframes <- list()
for (i in 1:tables){
newdf <- as_tibble( matrix(rnorm(rows * cols),rows , cols) )
newdf <- mutate(newdf, a = 'some long random text')
newdf <- mutate(newdf, b = 'some more random text')
newdf <- mutate(newdf, c = 'yet more text')
dataframes[[i]] <- newdf
}
toc()
tic("set up odbc")
con <- DBI::dbConnect(odbc::odbc(),
driver = "SQL Server",
server = "LTS-LNWS010\\SQLEXPRESS",
database = "CDL",
trusted_connection = TRUE)
toc()
tic("SQL export")
for(i in seq_along(dataframes)){
DBI::dbWriteTable(con, paste("Test_", i), dataframes[[i]], overwrite = TRUE)
}
toc()