Saya harus menerapkan sinkronisasi data antara dua database besar yang memiliki struktur yang sama sekali berbeda. Pada dasarnya, saya perlu menjepret beberapa data tentang produk dalam tabel yang berbeda di database pertama dan mengaturnya kembali untuk tabel lain di database kedua.
Menciptakan produk saya pada saat pertama tidak terlalu rumit. Tetapi saya sedang mencari cara untuk memperbarui beberapa data spesifik - tidak semua data - tentang setiap produk.
Jelas, ada beberapa masalah yang membuat ini rumit.
- Saya tidak diizinkan melakukan apa pun pada basis data sumber selain kueri pemilihan.
- Pada database target, saya dapat melakukan query biasa (pilih, perbarui, sisipkan, buat) tetapi saya tidak bisa memodifikasi struktur / tabel yang ada.
- Target dan sumber db memiliki struktur yang sama sekali berbeda, tabel tidak sama sekali, oleh karena itu data harus disusun ulang - tabel perbandingan tidak akan berfungsi.
- Basis data target menggunakan server MySQL - sumber mungkin DB2.
- Tidak ada bidang "waktu yang diperbarui" di mana pun.
Jadi seluruh proses perlu dilakukan dalam satu skrip Python (idealnya).
Saya berpikir tentang membuat hash untuk setiap produk, berdasarkan bidang untuk memperbarui dalam database target: md5 (kode + deskripsi + pemasok + sekitar 10 bidang lainnya). Hash baru berdasarkan data yang sama akan dibuat setiap hari dari basis data sumber. Saya akan menyimpan semua hash dalam satu tabel (kode item, current_hash, old_hash) untuk tujuan pertunjukan. Kemudian bandingkan dan perbarui produk jika hash baru berbeda dari yang lama.
Ada sekitar 500.000 produk jadi saya agak khawatir tentang penampilan.
Apakah ini cara yang baik untuk pergi?
Jawaban:
Ini cukup banyak apa yang telah saya lakukan atau hidup beberapa tahun terakhir, dan insting saya adalah bahwa waktu untuk membaca 500.000 item dari sumber database dan sinkronisasi di tujuan tidak akan mengambil banyak waktu seperti yang mungkin dipikirkan orang dan waktu yang dibutuhkan untuk membaca bidang "kunci", menghitung hash MD5, dan mengecek silang dengan meja Anda untuk menghindari sinkronisasi item yang tidak berubah tidak akan menghemat banyak waktu dan bahkan mungkin berjalan lebih lama. Saya cukup membaca semua dan memperbarui semua. Jika itu menghasilkan runtime yang terlalu panjang, maka saya akan memampatkan runtime dengan membuat ETL muti-threaded, dengan masing-masing thread hanya beroperasi pada segmen tabel tetapi bekerja secara paralel.
Penting untuk memastikan bahwa basis data tujuan Anda memiliki indeks kunci utama atau indeks unik. Jika tidak, setiap pembaruan / sisipan Anda dapat mengunci seluruh tabel. Ini akan menjadi buruk jika Anda mengambil pendekatan multithreaded, tetapi penting bahkan jika Anda tetap single-threaded karena pekerjaan Anda bisa mengunci tabel DB tujuan dan mengganggu aplikasi yang naik di atas DB itu.
Anda mengatakan sumber DB "mungkin DB2". Ketika Anda mengatakan "mungkin" itu menyiratkan bahwa DB masih dirancang / direncanakan? DB2 9 atau di atasnya memang memiliki pelacakan built-in dari waktu pembaruan terakhir, dan kemampuan untuk query dan mendapatkan kembali hanya item yang telah berubah sejak titik waktu. Mungkin ini sebabnya DB dirancang untuk tidak memiliki kolom yang menunjukkan waktu terakhir diperbarui, misalnya:
Batas waktu stempel untuk kueri di atas akan menjadi stempel waktu terakhir yang dijalankan oleh sinkronisasi Anda.
Jika ini masalahnya, itu akan menyelesaikan masalah Anda. Tetapi, solusi Anda pada akhirnya terikat erat dengan DB2 dan di masa depan mereka mungkin ingin pindah ke platform DB lain dan berharap pekerjaan sinkronisasi Anda tidak perlu dikunjungi kembali. Jadi, penting untuk memastikan semua orang yang tepat tahu bahwa produk Anda akan bergantung pada sisa pada DB2, atau jika mereka berencana untuk bermigrasi bahwa migrasi akan mencakup restrukturisasi DB untuk memiliki kolom "stempel waktu perubahan terakhir", dan membuat apa pun perubahan yang diperlukan di tingkat aplikasi untuk mengisi bidang itu.
sumber
Sinkronisasi data akan jauh lebih baik dan lebih cepat, jika dapat dilakukan atas dasar semacam pengidentifikasi atau tanda delta. Pada dasarnya, Anda harus memperbarui baris data target db hanya ketika tidak sinkron dengan sumber db.
Dalam SQL server db, Anda dapat mengambil bantuan Checksum fn juga untuk membangun pengidentifikasi berbasis delta.
Anda harus mengembangkan pekerjaan berbasis SQL untuk dipanggil pada waktu tertentu siang atau malam hari untuk mendapatkan logika sql ini dipecat. Lebih baik menjalankannya sebagai pekerjaan SQL malam, ketika penggunaan db sangat rendah. Jika delta sumber dan catatan target db tidak cocok, maka tarik catatan itu saja. Tetapi downside akan menghitung checksum dari baris data sumber setiap kali dan kemudian membandingkannya dengan data target.
Jika Anda memiliki kolom seperti "LastModifiedDate" di tabel sumber db, maka Anda dapat melewati pendekatan checksum. Dengan cara ini, evaluasi Anda akan dilaksanakan pada kolom berdasarkan tanggal dan membutuhkan waktu lebih sedikit dibandingkan dengan pendekatan checksum.
sumber
Menggunakan hash adalah ide yang bagus. Karena keamanan bukan tujuan dalam kasus ini, pilih fungsi hash yang cepat (md5 baik-baik saja).
Kecuali jika Anda berencana untuk membagi perhitungan hash di beberapa utas / proses, Anda tidak benar-benar perlu menyimpan nilai hash saat ini di database. Jika proses Anda adalah skrip tunggal, Anda hanya akan memiliki hash saat ini dalam memori, dan akan menuliskannya ke database sebagai hash lama setelah Anda memperbarui data dalam database baru.
sumber
Anda harus membuat layanan windows yang akan berjalan pada waktu tertentu kapan pun Anda mau dan itu akan menemukan perubahan dalam basis data sumber Anda dan menyisipkan perubahan itu dalam basis data tujuan Anda.
sumber