【问题标题】:How to speed up pandas to_sql如何加快熊猫 to_sql
【发布时间】:2020-07-05 17:30:29
【问题描述】:

我正在尝试使用 pandas to_sql 将数据上传到 MS Azure Sql 数据库,这需要很长时间。我经常需要在睡觉前运行它并在早上醒来,它已经完成但花了几个小时,如果出现错误,我无法解决它。这是我的代码:

params = urllib.parse.quote_plus(
'Driver=%s;' % driver +
'Server=%s,1433;' % server +
'Database=%s;' % database +
'Uid=%s;' % username +
'Pwd={%s};' % password +
'Encrypt=yes;' +
'TrustServerCertificate=no;'
)

conn_str = 'mssql+pyodbc:///?odbc_connect=' + params
engine = create_engine(conn_str)

@event.listens_for(engine, 'before_cursor_execute')
def receive_before_cursor_execute(conn, cursor, statement, params, context, executemany):
    if executemany:
        cursor.fast_executemany = True
        cursor.commit()
        
connection = engine.connect()
connection

然后我运行这个命令来获取 sql:

master_data.to_sql('table_name', engine, chunksize=500, if_exists='append', method='multi',index=False)

我玩过块大小,甜蜜点似乎是 100,考虑到我通常尝试一次上传 800,000-2,000,000 条记录,这还不够快。如果我将它增加到超过这个值,我会得到一个似乎只与块大小有关的错误。

OperationalError: (pyodbc.OperationalError) ('08S01', '[08S01] [Microsoft][ODBC Driver 17 for SQL Server]Communication link failure (0) (SQLExecDirectW)')

【问题讨论】:

    标签: python pandas azure-sql-database pandas-to-sql


    【解决方案1】:

    不确定您的问题是否已解决,但确实想在此处提供答案,以便提供Azure SQL Database libraries for Python 的具体信息和一些有用的资源来调查和解决此问题(如果适用)。

    使用pyodbc 直接查询 Azure SQL 数据库的示例: Quickstart: Use Python to query Azure SQL Database Single Instance & Managed Instance

    使用 Pandas 数据框的示例:How to read and write to an Azure SQL database from a Pandas dataframe

    main.py

    """Read write to Azure SQL database from pandas"""
    import pyodbc
    import pandas as pd
    import numpy as np
    from sqlalchemy import create_engine
    
    # 1. Constants
    AZUREUID = 'myuserid'                                    # Azure SQL database userid
    AZUREPWD = '************'                                # Azure SQL database password
    AZURESRV = 'shareddatabaseserver.database.windows.net'   # Azure SQL database server name (fully qualified)
    AZUREDB = 'Pandas'                                      # Azure SQL database name (if it does not exit, pandas will create it)
    TABLE = 'DataTable'                                      # Azure SQL database table name
    DRIVER = 'ODBC Driver 13 for SQL Server'                 # ODBC Driver
    
    def main():
    """Main function"""
    
    # 2. Build a connectionstring
    connectionstring = 'mssql+pyodbc://{uid}:{password}@{server}:1433/{database}?driver={driver}'.format(
        uid=AZUREUID,
        password=AZUREPWD,
        server=AZURESRV,
        database=AZUREDB,
        driver=DRIVER.replace(' ', '+'))
    
    # 3. Read dummydata into dataframe 
    df = pd.read_csv('./data/data.csv')
    
    # 4. Create SQL Alchemy engine and write data to SQL
    engn = create_engine(connectionstring)
    df.to_sql(TABLE, engn, if_exists='append')
    
    # 5. Read data from SQL into dataframe
    query = 'SELECT * FROM {table}'.format(table=TABLE)
    dfsql = pd.read_sql(query, engn)
    
    print(dfsql.head())
    
    
    if __name__ == "__main__":
        main()
    

    最后,以下资源应有助于比较特定实现、性能问题以及以下信息,其中堆栈溢出线程可能是最佳资源,但监控和性能调整文档对于调查和缓解任何服务器很有用 -侧面性能问题等。

    Speeding up pandas.DataFrame.to_sql with fast_executemany of pyODBC Monitoring and performance tuning in Azure SQL Database and Azure SQL Managed Instance

    问候, 迈克

    【讨论】:

    • 是的,我已经解决了我的问题。我将在下面为遇到类似问题的任何人发布我的代码更改。
    【解决方案2】:
    params = urllib.parse.quote_plus(
        'Driver=%s;' % driver +
        'Server=%s,1433;' % server +
        'Database=%s;' % database +
        'Uid=%s;' % username +
        'Pwd={%s};' % password +
        'Encrypt=yes;' +
        'TrustServerCertificate=no;'
        )
    
    
    conn_str = 'mssql+pyodbc:///?odbc_connect=' + params
    engine = create_engine(conn_str)
    
    @event.listens_for(engine, 'before_cursor_execute')
    def receive_before_cursor_execute(conn, cursor, statement, params, context, executemany):
        if executemany:
            cursor.fast_executemany = True
            cursor.commit()
            
    connection = engine.connect()
    connection
    

    数据库摄取是通过下一行完成的。我之前遇到过块大小的问题,但通过添加方法和索引来修复它。

    ingest_data.to_sql('db_table_name', engine, if_exists='append',chunksize=100000, method=None,index=False)
    

    【讨论】:

      猜你喜欢
      • 2015-01-02
      • 1970-01-01
      • 2017-10-12
      • 1970-01-01
      • 2020-02-22
      • 2021-10-17
      • 2019-12-15
      • 2018-11-17
      • 2021-09-17
      相关资源
      最近更新 更多