web-dev-qa-db-ja.com

SQLAlchemy、Psycopg2、Postgresql COPY

Psycopgには [〜#〜] copy [〜#〜] を実行するためのカスタムコマンドがあるようです。

cursor.copy_from()を使用したpsycopg2 COPYは、大きな入力でフリーズします

SQLAlchemyを使用してこの機能にアクセスする方法はありますか?

19
EoghanM

それはそれのようには見えません

この機能を公開し、ORM機能を放棄するには、psycopg2を使用する必要がある場合があります。とにかく、このような操作でORMの利点はあまりわかりません。これは、ストレートバルクインサートであり、ORMで個々のオブジェクトを処理することはあまり意味がないためです。

12
swasheck

受け入れられた答えは正しいですが、EoghanMのコメント以上のものを続けたい場合は、テーブルをCSVにコピーするのに役立ちました...

_from sqlalchemy import sessionmaker, create_engine

eng = create_engine("postgresql://user:pwd@Host:5432/db")
ses = sessionmaker(bind=engine)

dbcopy_f = open('/tmp/some_table_copy.csv','wb')

copy_sql = 'COPY some_table TO STDOUT WITH CSV HEADER'

fake_conn = eng.raw_connection()
fake_cur = fake_conn.cursor()
fake_cur.copy_expert(copy_sql, dbcopy_f)
_

sessionmakerは必要ありませんが、_raw_connection_を使用するためにエンジンとセッションを同時に作成する習慣がある場合は、それらを分離する必要があります(を介してエンジンにアクセスする方法がない限り)私が知らないセッションオブジェクト)。 _copy_expert_に提供されるSQL文字列もそれへの唯一の方法ではありません。通常のCOPYTOクエリに渡すことができるパラメータのサブセットで使用できる基本的な_copy_to_関数があります。コマンドの全体的なパフォーマンスは私には速いようで、最大20000行のテーブルをコピーします。

http://initd.org/psycopg/docs/cursor.html#cursor.copy_tohttp://docs.sqlalchemy.org/en/latest/core/connections.html# sqlalchemy.engine.Engine.raw_connection

33
dnfehren

エンジンがpsycopg2接続文字列(デフォルトであるため、"postgresql://..."または"postgresql+psycopg2://..."のいずれか)で構成されている場合は、SQLAlchemyセッションからpsycopg2カーソルを作成できます。

cursor = session.connection().connection.cursor()

実行に使用できます

cursor.copy_from(...)

カーソルは、現在のセッションと同じトランザクションでアクティブになります。 commitまたはrollbackが発生した場合、さらにpsycopg2.InterfaceErrorをスローしてカーソルを使用すると、新しいカーソルを作成する必要があります。

18
dtheodor

次を使用できます。

def to_sql(engine, df, table, if_exists='fail', sep='\t', encoding='utf8'):
    # Create Table
    df[:0].to_sql(table, engine, if_exists=if_exists)

    # Prepare data
    output = cStringIO.StringIO()
    df.to_csv(output, sep=sep, header=False, encoding=encoding)
    output.seek(0)

    # Insert data
    connection = engine.raw_connection()
    cursor = connection.cursor()
    cursor.copy_from(output, table, sep=sep, null='')
    connection.commit()
    cursor.close()

4分ではなく5秒で200000行を挿入します

8

Psycopg2にドロップダウンする必要はなく、raw_connectionもカーソルも使用しません。

通常どおりSQLを実行するだけで、バインドパラメータを text() で使用することもできます。

_engine.execute(text('''copy some_table from :csv
                       delimiter ',' csv'''
                   ).execution_options(autocommit=True),
               csv='/tmp/a.csv')
_

このPR が受け入れられる場合は、execution_options(autocommit=True)を削除できます。

4
berdario