Pandas: to_sql terlalu lambat

Dibuat pada 1 Feb 2017  ·  24Komentar  ·  Sumber: pandas-dev/pandas

Contoh Kode,

df_name.to_sql('table_name',
                          schema = 'public',
                          con = engine,
                          index = False,
                          if_exists = 'replace')

Deskripsi masalah

Saya sedang menulis kerangka data 500.000 baris ke database AWS postgres dan dibutuhkan waktu yang sangat, sangat lama untuk mendorong datanya.

Ini adalah server SQL yang cukup besar dan koneksi internet saya sangat baik, jadi saya telah mengesampingkan itu sebagai penyebab masalah.

Sebagai perbandingan, csv2sql atau menggunakan cat dan piping ke psql pada baris perintah jauh lebih cepat.

IO SQL Usage Question

Komentar yang paling membantu

Tambahkan kode ini di bawah engine = create_engine(connection_string) :

from sqlalchemy import event

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

Dalam kode saya, to_sql fungsi membutuhkan 7 menit untuk dieksekusi, dan sekarang hanya membutuhkan 5 detik;)

Semua 24 komentar

lihat di sini: http://stackoverflow.com/questions/33816918/write-large-pandas-dataframes-to-sql-server-database

dengan SQLServer Anda perlu mengimpor melalui csv dengan unggahan massal untuk efisiensi

Anda mungkin menemukan ini berguna: http://odo.pydata.org/en/latest/perf.html

ODO tidak akan berfungsi untuk saya, ini menghasilkan kesalahan yang tidak dapat saya perbaiki, tetapi d6tstack berfungsi dengan baik https://github.com/d6t/d6tstack/blob/master/examples-sql.ipynb. Anda dapat melakukan preprocess dengan panda dan menggunakan postgres COPY FROM untuk melakukan impor dengan cepat. Bekerja dengan baik dengan postgres RDS.

Tambahkan kode ini di bawah engine = create_engine(connection_string) :

from sqlalchemy import event

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

Dalam kode saya, to_sql fungsi membutuhkan 7 menit untuk dieksekusi, dan sekarang hanya membutuhkan 5 detik;)

Terima kasih @llautert!
Itu sangat membantu!

# dont forget to import event
from sqlalchemy import event, create_engine

engine = create_engine(connection_string)

@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()

Saya sudah mencoba menjalankan perbaikan ini, tetapi mengalami pesan kesalahan:

AttributeError: 'psycopg2.extensions.cursor' object has no attribute 'fast_executemany'

Ada yang tau apa yang terjadi?

Hai @ tim-sauchuk, mengalami kesalahan yang sama juga, meskipun saya menemukan solusi yang berfungsi dengan baik yang melibatkan sedikit pengeditan pada file pandas.io.sql.py (cukup hapus file .pyc dari __pycache__ sebelum mengimpor lagi untuk memastikannya menulis versi baru ke file terkompresi)

https://github.com/pandas-dev/pandas/issues/8953

Hai @ tim-sauchuk, mengalami kesalahan yang sama juga, meskipun saya menemukan solusi yang berfungsi dengan baik yang melibatkan sedikit pengeditan pada file pandas.io.sql.py (cukup hapus file .pyc dari

8953

Masalah # 8953 yang @ bsaunders23 sebutkan juga menunjukkan cara untuk "tambalan monyet" (perbaiki saat dijalankan). Saya mencobanya, dan kumpulan data 20k yang membutuhkan 10+ menit untuk diunggah kemudian hanya membutuhkan waktu 4 detik.

Terima kasih @llautert!
Itu sangat membantu!

# dont forget to import event
from sqlalchemy import event, create_engine

engine = create_engine(connection_string)

@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()

Adakah yang tahu bagaimana saya dapat mengimplementasikan solusi ini di dalam kelas dengan contoh self.engine?

Adakah yang tahu bagaimana saya dapat mengimplementasikan solusi ini di dalam kelas dengan contoh self.engine?

Bekerja untuk saya dengan merujuk ke self.engine

Contoh:

    self.engine = sqlalchemy.create_engine(connectionString, echo=echo)
    self.connection = self.engine.connect()

    @event.listens_for(self.engine, 'before_cursor_execute')
    def receive_before_cursor_execute(conn, cursor, statement, params, context, executemany):
        print("Listen before_cursor_execute - executemany: %s" % str(executemany))
        if executemany:
            cursor.fast_executemany = True
            cursor.commit()

Tidak bekerja untuk saya. Versi panda dan sqlalchemy apa yang Anda gunakan?

Saya mencobanya dengan menjalankan sqlalchemy: 1.2.4-py35h14c3975_0 dan 1.2.11-py35h7b6447c_0

tapi saya mendapatkan

AttributeError: objek 'psycopg2.extensions.cursor' tidak memiliki atribut 'fast_executemany'

@ dean_muhammad

Seperti apa pemanggilan fungsi dalam konteks ini? Atau dengan kata lain, apa yang Anda gunakan untuk argumen berhasil mengupload tabel?

<# dont forget to import event
from sqlalchemy import event, create_engine

engine = create_engine(connection_string)

@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()>``

Saya mencobanya dengan menjalankan sqlalchemy: 1.2.4-py35h14c3975_0 dan 1.2.11-py35h7b6447c_0

tapi saya mendapatkan

AttributeError: objek 'psycopg2.extensions.cursor' tidak memiliki atribut 'fast_executemany'

Anda menggunakan psycopg2, yang merupakan driver postgresql. Masalah dan perbaikan ini berkaitan dengan Microsoft SQL Server menggunakan pengandar pyodbc.

bagaimana dengan menambahkan parameter 'dtype'

Adakah yang tahu bagaimana saya dapat mengimplementasikan solusi ini di dalam kelas dengan contoh self.engine?

Bekerja untuk saya dengan merujuk ke self.engine

Contoh:

    self.engine = sqlalchemy.create_engine(connectionString, echo=echo)
    self.connection = self.engine.connect()

    @event.listens_for(self.engine, 'before_cursor_execute')
    def receive_before_cursor_execute(conn, cursor, statement, params, context, executemany):
        print("Listen before_cursor_execute - executemany: %s" % str(executemany))
        if executemany:
            cursor.fast_executemany = True
            cursor.commit()

Sudahkah Anda mengetahui caranya?

Saya pikir jawaban yang benar adalah menggunakan https://docs.sqlalchemy.org/en/13/dialects/postgresql.html#psycopg2 -batch-mode-fast-execution, jika Anda mencoba menghemat pandas dataframe menjadi postgres

Versi baru panda berisi method parameter yang dapat dipilih sebagai 'multi'. Ini membuat kode berjalan lebih cepat.

fast_executemany dapat dilakukan dalam satu langkah sekarang (sqlalchemy> = 1.3.0):

engine = sqlalchemy.create_engine(connection_string, fast_executemany=True)

Mungkin ada baiknya menyebutkannya di suatu tempat di dokumen atau dengan contoh? Ini adalah kasus tertentu yang tidak terkait dengan panda, tetapi ini adalah tambahan kecil yang dapat meningkatkan kinerja secara drastis dalam banyak kasus.

Versi baru panda berisi method parameter yang dapat dipilih sebagai 'multi'. Ini membuat kode berjalan lebih cepat.

Anda akan berpikir bahwa pengaturan parameter chunksize akan cukup untuk membuat to_sql penyisipan batch tetapi tidak.

Alternatif untuk pengguna MS SQL adalah juga menggunakan turbodbc.Cursor.insertmanycolumns , saya telah menjelaskannya di postingan StackOverflow yang ditautkan: https://stackoverflow.com/a/62671681/1689261

Untuk pembaca selanjutnya, ada dua opsi untuk menggunakan 'batch_mode' untuk to_sql. Berikut ini adalah dua kombinasi:

create_engine(connection_string, executemany_mode='batch', executemany_batch_page_size=x)

atau

create_engine(connection_string, executemany_mode='values', executemany_values_page_size=x)

Detail tentang argumen ini dapat ditemukan di sini: https://docs.sqlalchemy.org/en/13/dialects/postgresql.html#psycopg2 -fast-execution-helpers

Untuk pengguna postgres, saya merekomendasikan pengaturan method ke callable:

callable dengan tanda tangan (pd_table, conn, keys, data_iter): Ini dapat digunakan untuk mengimplementasikan metode penyisipan yang lebih berkinerja berdasarkan fitur dialek backend tertentu.

dan panggil fungsi dari kode contoh di sini https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html#insertion -method dan

Menggunakan COPY FROM benar-benar jauh lebih cepat 🚀

Apakah halaman ini membantu?
0 / 5 - 0 peringkat