【问题标题】:How to write data frame to Postgres table without using SQLAlchemy engine?如何在不使用 SQLAlchemy 引擎的情况下将数据框写入 Postgres 表?
【发布时间】:2020-02-28 00:58:47
【问题描述】:

我有一个要写入 Postgres 数据库的数据框。此功能需要是 Flask 应用的一部分。

现在,我通过创建 SQLAlchemy 引擎 并将其传递给 df.to_sql() 以将数据框写入数据库表,将这个插入部分作为单独的脚本运行。

但是,当我将此功能集成到 Flask 应用程序中时,我已经与使用 Psycopg2 连接池创建的 Postgres 数据库建立了现有连接。

查看df.to_sql() 文档时,提到它使用SQLAlchemy 引擎。我没有看到任何其他连接机制。 https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_sql.html#pandas-dataframe-to-sql

我的问题是,当我拥有现有连接时,为什么需要创建这个 SQLAlchemy 引擎。为什么我不能使用它们?

【问题讨论】:

    标签: python pandas postgresql sqlalchemy


    【解决方案1】:

    您可以使用这些连接并避免使用 SQLAlchemy。这听起来很不直观,但它会比常规插入快得多(即使您要删除 ORM 并进行一般查询,例如使用executemany)。即使使用原始查询,插入也很慢,但您会看到 COPYHow to speed up insertion performance in PostgreSQL 中被多次提及。在这种情况下,我采用以下方法的动机是:

    1. 使用COPY 而不是INSERT
    2. 不要相信 Pandas 会为此操作生成正确的 SQL(尽管 Ilja Everilä 指出,这种方法实际上得到了added to Pandas in V0.24
    3. 不要将数据写入磁盘以创建实际的文件对象;记在心里

    使用cursor.copy_from()的建议方法:

    import csv
    import io
    import psycopg2
    
    df = "<your_df_here>"
    
    # drop all the columns you don't want in the insert data here
    
    # First take the headers
    headers = df.columns
    
    # Now get a nested list of values
    data = df.values.tolist()
    
    # Create an in-memory CSV file
    string_buffer = io.StringIO()
    csv_writer = csv.writer(string_buffer)
    csv_writer.writerows(data)
    
    # Reset the buffer back to the first line
    string_buffer.seek(0)
    
    # Open a connection to the db (which I think you already have available)
    with psycopg2.connect(dbname=current_app.config['POSTGRES_DB'], 
                          user=current_app.config['POSTGRES_USER'],
                          password=current_app.config['POSTGRES_PW'], 
                          host=current_app.config['POSTGRES_URL']) as conn:
        c = conn.cursor()
    
        # Now upload the data as though it was a file
        c.copy_from(string_buffer, 'the_table_name', sep=',', columns=headers)
        conn.commit()
    

    这应该比实际插入要快几个数量级。

    【讨论】:

    • 关于你的第二点,值得注意的是你可以很容易地使用COPYto_sqlpandas.pydata.org/pandas-docs/stable/user_guide/…
    • @IljaEverilä 有趣。我不知道它被添加到0.24。谢谢
    • 这个答案可以帮助我提高性能。但是,我正在寻找确认是否可以使用现有的数据库连接使用df.to_sql 插入数据框。提前致谢。
    • 提前什么?
    • @SukumarRdjf 好吧,您需要自己确定。我看不出你还希望我在这里说什么;我已经向您确切展示了您的要求
    猜你喜欢
    • 2017-11-10
    • 2018-04-20
    • 2023-04-05
    • 2017-09-08
    • 2013-03-13
    • 2022-06-13
    • 1970-01-01
    • 2012-01-31
    • 2017-08-27
    相关资源
    最近更新 更多