PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

node-postgres dengan sejumlah besar kueri

PERBARUI

Jawaban ini telah digantikan dengan artikel ini:Impor Data , yang mewakili pendekatan paling mutakhir.

Untuk meniru skenario Anda, saya menggunakan pg-promise perpustakaan, dan saya dapat mengonfirmasi bahwa mencobanya secara langsung tidak akan pernah berhasil, tidak peduli perpustakaan mana yang Anda gunakan, pendekatannyalah yang penting.

Di bawah ini adalah pendekatan yang dimodifikasi di mana kita mempartisi sisipan ke dalam potongan dan kemudian mengeksekusi setiap potongan dalam suatu transaksi, yang merupakan penyeimbangan beban (alias pelambatan):

function insertRecords(N) {
    return db.tx(function (ctx) {
        var queries = [];
        for (var i = 1; i <= N; i++) {
            queries.push(ctx.none('insert into test(name) values($1)', 'name-' + i));
        }
        return promise.all(queries);
    });
}
function insertAll(idx) {
    if (!idx) {
        idx = 0;
    }
    return insertRecords(100000)
        .then(function () {
            if (idx >= 9) {
                return promise.resolve('SUCCESS');
            } else {
                return insertAll(++idx);
            }
        }, function (reason) {
            return promise.reject(reason);
        });
}
insertAll()
    .then(function (data) {
        console.log(data);
    }, function (reason) {
        console.log(reason);
    })
    .done(function () {
        pgp.end();
    });

Ini menghasilkan 1000.000 catatan dalam waktu sekitar 4 menit, secara dramatis melambat setelah 3 transaksi pertama. Saya menggunakan Node JS 0.10.38 (64-bit), yang menghabiskan sekitar 340MB memori. Dengan cara ini kami memasukkan 100.000 catatan, 10 kali berturut-turut.

Jika kita melakukan hal yang sama, hanya saja kali ini memasukkan 10.000 record dalam 100 transaksi, 1.000.000 record yang sama ditambahkan hanya dalam 1m25s, tidak melambat, dengan Node JS menghabiskan sekitar 100MB memori, yang memberitahu kita bahwa mempartisi data seperti ini adalah sangat ide bagus.

Tidak masalah perpustakaan mana yang Anda gunakan, pendekatannya harus sama:

  1. Mempartisi/membatasi sisipan Anda menjadi beberapa transaksi;
  2. Simpan daftar sisipan dalam satu transaksi di sekitar 10.000 catatan;
  3. Jalankan semua transaksi Anda dalam rantai sinkron.
  4. Lepaskan koneksi kembali ke pool setelah COMMIT setiap transaksi.

Jika Anda melanggar salah satu dari aturan itu, Anda dijamin mendapat masalah. Misalnya, jika Anda melanggar aturan 3, proses Node JS Anda kemungkinan akan kehabisan memori dengan sangat cepat dan menimbulkan kesalahan. Aturan 4 dalam contoh saya disediakan oleh perpustakaan.

Dan jika Anda mengikuti pola ini, Anda tidak perlu repot dengan pengaturan kumpulan koneksi.

PERBARUI 1

Versi pg-promise yang lebih baru mendukung skenario seperti itu dengan sempurna, seperti yang ditunjukkan di bawah ini:

function factory(index) {
    if (index < 1000000) {
        return this.query('insert into test(name) values($1)', 'name-' + index);
    }
}

db.tx(function () {
    return this.batch([
        this.none('drop table if exists test'),
        this.none('create table test(id serial, name text)'),
        this.sequence(factory), // key method
        this.one('select count(*) from test')
    ]);
})
    .then(function (data) {
        console.log("COUNT:", data[3].count);
    })
    .catch(function (error) {
        console.log("ERROR:", error);
    });

dan jika Anda tidak ingin memasukkan sesuatu yang ekstra, seperti pembuatan tabel, maka tampilannya akan lebih sederhana:

function factory(index) {
    if (index < 1000000) {
        return this.query('insert into test(name) values($1)', 'name-' + index);
    }
}

db.tx(function () {
    return this.sequence(factory);
})
    .then(function (data) {
        // success;
    })
    .catch(function (error) {
        // error;
    });

Lihat Transaksi Sinkron untuk rincian.

Menggunakan Bluebird sebagai perpustakaan janji, misalnya, dibutuhkan 1m43 detik pada mesin produksi saya untuk menyisipkan 1.000.000 catatan (tanpa mengaktifkan pelacakan tumpukan panjang).

Anda hanya perlu memiliki factory metode mengembalikan permintaan sesuai dengan index , sampai tidak ada yang tersisa, sesederhana itu.

Dan bagian terbaiknya, ini tidak hanya cepat, tetapi juga membuat sedikit beban pada proses NodeJS Anda. Proses pengujian memori tetap di bawah 60 MB selama keseluruhan pengujian, hanya menghabiskan 7-8% dari waktu CPU.

PERBARUI 2

Dimulai dengan versi 1.7.2, pg-promise mendukung transaksi super besar-besaran dengan mudah. Lihat bab Transaksi Sinkron .

Misalnya, saya dapat memasukkan 10.000.000 catatan dalam satu transaksi hanya dalam 15 menit di PC rumah saya, dengan Windows 8.1 64-bit.

Untuk pengujian, saya menyetel PC ke mode produksi, dan menggunakan Bluebird sebagai perpustakaan janji. Selama pengujian, konsumsi memori tidak melebihi 75MB untuk seluruh proses NodeJS 0.12.5 (64-bit), sedangkan CPU i7-4770 saya menunjukkan beban 15% yang konsisten.

Memasukkan 100m catatan dengan cara yang sama hanya membutuhkan lebih banyak kesabaran, tetapi tidak lebih banyak sumber daya komputer.

Sementara itu, pengujian sebelumnya untuk 1m insert turun dari 1m43s menjadi 1m31s.

PERBARUI 3

Pertimbangan berikut dapat membuat perbedaan besar:Peningkatan Kinerja .

PERBARUI 4

Pertanyaan terkait, dengan contoh implementasi yang lebih baik:Insersi besar-besaran dengan pg-promise .

PERBARUI 5

Contoh yang lebih baik dan lebih baru dapat ditemukan di sini:nodeJS memasukkan Data ke dalam kesalahan PostgreSQL



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. isi kolom dengan nilai terakhir dari partisi di postgresql

  2. Cadangkan/Pulihkan database PostgreSQL yang di-docker

  3. Menyebarkan Django + Python 3 + PostgreSQL ke AWS Elastic Beanstalk

  4. Opsi Pencadangan Cloud untuk PostgreSQL

  5. Cara membatasi panjang tampilan maksimum kolom di PostgreSQL