Pyt*_*ous 21 python sql sqlalchemy pyodbc pandas
我有一个大约155,000行和12列的数据帧.如果我使用dataframe.to_csv将其导出到csv,则输出为11MB文件(即时生成).
但是,如果我使用to_sql方法导出到Microsoft SQL Server,则需要5到6分钟!没有列是文本:只有int,float,bool和日期.我见过ODBC驱动程序设置nvarchar(max)的情况,这会减慢数据传输速度,但这不是这种情况.
有关如何加快出口流程的任何建议?导出11 MB数据需要6分钟,这使得ODBC连接几乎无法使用.
谢谢!
我的代码是:
import pandas as pd
from sqlalchemy import create_engine, MetaData, Table, select
ServerName = "myserver"
Database = "mydatabase"
TableName = "mytable"
engine = create_engine('mssql+pyodbc://' + ServerName + '/' + Database)
conn = engine.connect()
metadata = MetaData(conn)
my_data_frame.to_sql(TableName,engine)
Run Code Online (Sandbox Code Playgroud)
fir*_*ynx 13
该DataFrame.to_sql方法为ODBC连接器生成插入语句,然后ODBC连接器将其视为常规插入.
当这很慢时,它不是大熊猫的错.
将DataFrame.to_sql方法的输出保存到文件,然后通过ODBC连接器重播该文件将花费相同的时间.
将数据批量导入数据库的正确方法是生成csv文件,然后使用load命令,该命令在SQL数据库的MS风格中被调用 BULK INSERT
例如:
BULK INSERT mydatabase.myschema.mytable
FROM 'mydatadump.csv';
Run Code Online (Sandbox Code Playgroud)
语法参考如下:
BULK INSERT
[ database_name . [ schema_name ] . | schema_name . ] [ table_name | view_name ]
FROM 'data_file'
[ WITH
(
[ [ , ] BATCHSIZE = batch_size ]
[ [ , ] CHECK_CONSTRAINTS ]
[ [ , ] CODEPAGE = { 'ACP' | 'OEM' | 'RAW' | 'code_page' } ]
[ [ , ] DATAFILETYPE =
{ 'char' | 'native'| 'widechar' | 'widenative' } ]
[ [ , ] FIELDTERMINATOR = 'field_terminator' ]
[ [ , ] FIRSTROW = first_row ]
[ [ , ] FIRE_TRIGGERS ]
[ [ , ] FORMATFILE = 'format_file_path' ]
[ [ , ] KEEPIDENTITY ]
[ [ , ] KEEPNULLS ]
[ [ , ] KILOBYTES_PER_BATCH = kilobytes_per_batch ]
[ [ , ] LASTROW = last_row ]
[ [ , ] MAXERRORS = max_errors ]
[ [ , ] ORDER ( { column [ ASC | DESC ] } [ ,...n ] ) ]
[ [ , ] ROWS_PER_BATCH = rows_per_batch ]
[ [ , ] ROWTERMINATOR = 'row_terminator' ]
[ [ , ] TABLOCK ]
[ [ , ] ERRORFILE = 'file_name' ]
)]
Run Code Online (Sandbox Code Playgroud)
您可以使用它:使它更快的是methodpandas的参数to_sql。我希望这有帮助。
根据我的经验,结果是从无限时间到 8 秒。
df = pd.read_csv('test.csv')
conn = create_engine(<connection_string>)
start_time = time.time()
df.to_sql('table_name', conn, method='multi',index=False, if_exists='replace')
print("--- %s seconds ---" % (time.time() - start_time))
Run Code Online (Sandbox Code Playgroud)
我最近遇到了同样的问题,并想为其他人添加一个答案。
to_sql似乎INSERT为每行发送一个查询,这确实很慢。但是由于0.24.0有一个method参数pandas.to_sql(),您可以在其中定义自己的插入函数,或者仅用于method='multi'告诉熊猫在单个INSERT查询中传递多行,这使其速度大大提高。
请注意,您的数据库可能有参数限制。在这种情况下,您还必须定义一个块大小。
因此解决方案应该看起来像这样:
my_data_frame.to_sql(TableName, engine, chunksize=<yourParameterLimit>, method='multi')
Run Code Online (Sandbox Code Playgroud)
如果您不知道数据库参数限制,请尝试不使用chunksize参数。它会运行或提示您限制的错误。
您可以使用d6tstack,它具有快速 pandas 到 SQL 功能,因为它使用本机数据库导入命令。它支持 MS SQL、Postgres 和 MYSQL
uri_psql = 'postgresql+psycopg2://usr:pwd@localhost/db'
d6tstack.utils.pd_to_psql(df, uri_psql, 'table')
uri_mssql = 'mssql+pymssql://usr:pwd@localhost/db'
d6tstack.utils.pd_to_mssql(df, uri_mssql, 'table', 'schema') # experimental
Run Code Online (Sandbox Code Playgroud)
对于在写入数据库之前导入多个包含数据模式更改和/或使用 pandas 进行预处理的 CSV 也很有用,请参阅示例笔记本中的进一步内容
d6tstack.combine_csv.CombinerCSV(glob.glob('*.csv'),
apply_after_read=apply_fun).to_psql_combine(uri_psql, 'table')
Run Code Online (Sandbox Code Playgroud)
pandas.DataFrame.to_sql慢?将数据上传到pandasMicrosoft SQL Server 时,大部分时间实际上花在从pandasPython 对象转换为 MS SQL ODBC 驱动程序所需的表示形式上。分析速度比基本 Python 代码快得多的原因之一pandas是,它适用于整数/浮点数/\xe2\x80\xa6 的精简本机数组,这些数组与各自的 Python 对应项没有相同的开销。该to_sql方法实际上是将所有这些精简列转换为许多单独的 Python 对象,因此不会像其他pandas操作那样获得通常的性能处理。
turbodbc.Cursor.insertmanycolumns加快速度给定 a pandas.DataFrame,您可以使用turbodbc和pyarrow插入数据,其转换开销比转换为 Python 对象时要少。
import pyarrow as pa\nimport turbodbc\n\ncursor = \xe2\x80\xa6 # cursor to a MS SQL connection initiated with turbodbc\ndf = \xe2\x80\xa6 # the pd.DataFrame to be inserted\n\n# Convert the pandas.DataFrame to a pyarrow.Table, most of the columns\n# will be zero-copy and thus this is quite fast.\ntable = pa.Table.from_pandas(table)\n\n# Insert into the database\ncursor.executemanycolumns("INSERT INTO my_table VALUES (?, ?, ?)",\n table)\nRun Code Online (Sandbox Code Playgroud)\n我们不是进行 -> Python 对象集合 -> ODBC 数据结构的转换,而是进行路径-> -> ODBC 结构pd.DataFrame的转换。由于以下原因,它的性能更高:pd.DataFramepyarrow.Table
pandas.DataFrame即可转换为 the 的列。pyarrow.Table表的列将引用相同的内存。所以没有进行实际的转换。object。| 归档时间: |
|
| 查看次数: |
21788 次 |
| 最近记录: |