Apakah praktik yang buruk untuk menggabungkan data dari tabel yang berbeda menjadi satu?

12

Latar Belakang

Saya menulis banyak laporan besar untuk dan umumnya memelihara catatan kesehatan besar DB (menulis SP, fungsi, pekerjaan, dll.). Skema asli, dan perangkat lunak yang menggunakannya, berasal dari vendor yang berbeda, jadi saya tidak bisa banyak berubah tentang hal itu secara struktural. Ada banyak catatan yang memerlukan pelacakan seperti laboratorium, prosedur, vaksin, dll. Dan mereka tersebar di puluhan meja, banyak di antaranya membengkak dan indeksnya buruk (saya sudah bisa memperbaikinya).

Masalah

Masalahnya adalah karena kita memiliki sedikit kendali atas DB, dan karena dapat berubah dari pembaruan atau tambalan apa pun, itu membuat penulisan dan pemeliharaan laporan ini menjadi sulit dan melelahkan - terutama ketika ada banyak tumpang tindih. Yang diperlukan hanyalah satu tambalan dan saya buntu menulis ulang sebagian besar laporan. Selain itu, kueri dengan cepat menjadi dikaburkan dan lambat saat bergabung, bersarang memilih, dan menerapkan tumpukan.

"Solusi" saya

Rencana saya adalah untuk menulis semua catatan ini ke satu tabel "catch-all", dan menulis pemicu pada tabel asli untuk mempertahankan catatan dalam tabel agregat ini. Tentu saja saya perlu memastikan pemicu saya tetap utuh setelah pembaruan, tetapi ini akan jauh lebih mudah dari sudut pandang rawatan, dan hanya merujuk data.

Tabelnya akan tipis dan panjang, hanya menyimpan data yang diperlukan, sesuatu seperti ini:

CREATE TABLE dbo.HCM_Event_Log (
    id INT IDENTITY,
    type_id INT NULL,
    orig_id VARCHAR(36) NULL,
    patient_id UNIQUEIDENTIFIER NOT NULL,
    visit_id UNIQUEIDENTIFIER NULL,
    lookup_id VARCHAR(50) NULL,
    status VARCHAR(15) NULL,
    ordered_datetime DATETIME NULL,
    completed_datetime DATETIME NULL,
    CONSTRAINT PK_HCM_Event_Log PRIMARY KEY CLUSTERED (id)
)

Kemudian saya akan memiliki berbagai tabel relasional untuk hal-hal seperti pengelompokan type_id dan item.

Saya mulai menebak ide ini karena beberapa tabel ini ditulis untuk sedikit, SP dan laporan yang akan saya tulis akan referensi data banyak juga. Jadi saya khawatir bahwa tabel ini akan menjadi penguncian rekor dan mimpi buruk kinerja dengan begitu banyak I / O.

Pertanyaan saya

Apakah itu ide yang buruk atau bagus? Saya menyadari setiap situasi berbeda dalam SQL Server (2008 r2 Edisi Standar BTW), dan aturan "kadang-kadang", tapi saya benar-benar hanya mencari saran umum.

Saya mulai mempertimbangkan untuk menggunakan broker layanan, tetapi saya hanya akan melakukan pembaruan / sisipan sederhana ( Lihat alternatif untuk jawaban yang diterima ). Data dalam banyak kasus harus realtime, jadi menggunakan cadangan DB tidak akan berfungsi. Kinerja sudah agak menjadi masalah bagi kami, tetapi sebagian besar terkait perangkat keras yang akan segera diatasi.

jreed121
sumber
1
Bisakah Anda menerapkan pemadaman yang direncanakan? Jika tidak salah satu dari pembaruan tersebut dapat menghapus pemicu dan Anda tidak akan memperbarui agregat Anda yang mungkin mengarah ke data yang buruk.
Erik
Anda mempertimbangkan memasukkan semua informasi tentang laboratorium, dan tentang prosedur, dan tentang vaksin, dan tentang pasien ke dalam satu tabel? Ide buruk. Anda mungkin dapat menggunakan skema bintang, jika itu sesuai dengan jenis kueri yang Anda jalankan.
Michael Green
1
Sudahkah Anda melihat untuk membuat beberapa tampilan indeks? Ini akan menempatkan lapisan logis antara kode Anda dan vendor sehingga Anda bisa memperbarui tampilan jika vendor mengubah hal-hal di bawahnya. Selain itu, tampilan yang diindeks akan disiapkan untuk Anda dan memberikan kinerja baca yang baik. Salah satu pertimbangan yang lebih besar dalam melakukan ini adalah berapa banyak beban yang diletakkan pada operasi penulisan tabel database vendor. Namun, ini kemungkinan akan menjadi solusi yang lebih bersih dan lebih mudah untuk dipertahankan daripada menggunakan pemicu, dll.
Micah Nikkel
Maaf untuk balasan terlambat kawan, terima kasih atas umpan baliknya. @Erik - Ya, kami telah merencanakan pembaruan, dan saya memeriksa untuk memastikan semua perubahan saya sebelumnya masih ada melalui serangkaian skrip checklist yang saya jalankan, jadi tidak akan ada kejutan di sana dan saya akan membuat skrip CREATE untuk semua pemicunya.
jreed121
@MichaelGreen - Saya akan melihat skema bintang, tapi saya ingin tahu mengapa Anda berpikir memiliki semua data dalam satu tabel adalah ide yang buruk? Lingkungan aplikasi sepenuhnya terisolasi pada VPN, tidak dapat diakses di luar jaringan. Jika ada yang salah dengan meja, maka itu bukan akhir dunia karena saya bisa menulis semuanya kembali ke sana. Tabel tidak akan digunakan untuk data misi-kritis, atau setidaknya itu bukan satu-satunya, atau primer, tempat data disimpan.
jreed121

Jawaban:

8

Jika saya mengerti Anda dengan benar,

  • Anda memiliki sistem pihak ketiga yang besar,
  • Anda tidak memiliki banyak kendali atasnya,
  • Anda membuat laporan kompleks yang membaca data langsung dari basis data pihak ketiga ini,
  • pertanyaan Anda bergantung pada struktur internal basis data pihak ketiga.

Saya akan mendekatinya seperti ini:

  • Atur database saya sendiri yang terpisah, yang saya kendalikan sepenuhnya.
  • Siapkan proses sinkronisasi yang membaca data dari tabel dan kolom yang relevan dari basis data pihak ketiga dan masukkan / perbarui ke tambang.
  • Kembangkan laporan kompleks saya berdasarkan pada struktur stabil dari basis data saya.

Dalam hal ini Anda dapat menyempurnakan struktur dan indeks database Anda untuk meningkatkan kinerja laporan Anda, tanpa mempengaruhi sistem pihak ketiga. Kecuali jika struktur data asli berubah secara dramatis, logika kueri Anda untuk laporan Anda tidak akan berubah jika database pihak ketiga berubah. Anda harus menyesuaikan hanya proses sinkronisasi.

Proses sinkronisasi secara efektif adalah proses konversi - Anda mengonversi data dari basis data pihak ketiga ke dalam struktur yang Anda butuhkan. Bagian dari proses konversi ini dapat memperbaiki masalah normalisasi yang mungkin dimiliki oleh database pihak ketiga. Hanya bagian dari sistem ini yang harus mengetahui dan bergantung pada struktur internal sistem pihak ketiga. Laporan utama dan pertanyaan utama Anda hanya akan bergantung pada basis data Anda.

Jadi, intinya adalah - pisahkan dan batasi bagian sistem Anda yang tergantung pada internal sistem pihak ketiga.

memperbarui

Mengenai persyaratan waktu-nyata. BTW, saya selalu berpikir bahwa definisi "waktu nyata" adalah "waktu respons yang dijamin", bukan "waktu respons yang kecil". Itu tergantung pada aplikasi Anda, tentu saja. Dalam praktik saya sudah cukup jika saya menyinkronkan dua database dalam satu menit dari perubahan yang terdeteksi. Jika pengguna melihat laporan di layar dan beberapa perubahan data yang mendasarinya, laporan tersebut harus dijalankan kembali untuk mencerminkan perubahan ini. Anda dapat polling untuk perubahan atau mendengarkan beberapa acara / pesan, masih permintaan laporan harus dieksekusi lagi untuk menunjukkan perubahan terbaru.

Anda sudah bermaksud menulis pemicu untuk menangkap perubahan di tabel asli dan menulis perubahan ini ke satu tabel umum. Jadi, ambil perubahan seperti yang Anda inginkan, tetapi tulislah untuk tabel yang dinormalisasi dengan benar, bukan satu.

Jadi, ini adalah kasus ekstrem - konversi struktur data pihak ketiga ke dalam struktur data internal Anda dilakukan di pemicu yang mengaktifkan INSERT/UPDATE/DELETEtabel pihak ketiga. Ini bisa rumit. Kode pemicu akan tergantung pada struktur internal kedua sistem. Jika konversi non-sepele itu mungkin menunda yang asli INSERT/UPDATE/DELETEke titik kegagalan mereka. Jika ada bug di pemicu Anda, hal itu dapat memengaruhi transaksi asli hingga gagal. Jika sistem pihak ketiga berubah, hal itu dapat merusak pelatuk Anda, yang akan menyebabkan transaksi sistem pihak ketiga gagal.

Kasus yang kurang ekstrim. Untuk membuat kode pemicu Anda lebih sederhana dan lebih rentan terhadap kesalahan, tulis semua perubahan yang diambil ke beberapa tabel pementasan / audit / diff, tetapkan beberapa tanda / kirim pesan bahwa ada perubahan yang tertunda dan luncurkan proses konversi utama yang akan dilakukan melalui tabel perantara ini dan melakukan konversi. Hal utama di sini adalah bahwa proses konversi yang berpotensi berat harus terjadi di luar ruang lingkup transaksi asli.

Pada pandangan kedua, ini terlihat seperti saran awal Anda dalam pertanyaan. Tapi, perbedaannya adalah: tabel capture-all menampung data hanya sementara; jumlah data kecil - hanya apa yang telah berubah; tidak harus berupa satu tabel; akhirnya data akan disimpan dalam tabel permanen yang dinormalisasi dengan benar, yang Anda kendalikan sepenuhnya, yang independen dari sistem pihak ketiga dan yang dapat Anda sesuaikan dengan pertanyaan Anda.

Vladimir Baranov
sumber
Jika Anda menggunakan rute transfer batch, kami telah berhasil dengan Change Tracking (dan Change Capture Data, tergantung pada kebutuhan Anda) dengan jumlah transaksi yang cukup tinggi (100 ribu per hari). Ini lebih sederhana daripada menerapkan tabel staging / audit / diff Anda sendiri dan dapat digunakan tanpa perubahan kode aplikasi atau pemicu.
Michael Green
Baik itu pemicu atau CDC, satu-satunya cara Anda akan benar-benar mendekati real-time adalah streaming atau antrian. Berbasis antrian adalah kompromi yang baik untuk latensi dan efektivitas biaya. Waktu Anda akan dihabiskan pada metode untuk memproses antrian lebih cepat. meninggalkan sebagian besar pekerjaan tidak sinkron dari aplikasi, dan menempatkan lebih sedikit beban pada transaksi pengguna. Di masa lalu saya telah melakukan hal ini terhadap Allscripts Sunrise EMR dengan layanan yang memproses antrian dengan beberapa panggilan paralel untuk setiap panggilan C #. latensi umum untuk data baru yang akan diproses dan tersedia di gudang adalah kurang dari 30 detik
Brad D
Saya mungkin telah menyatakan "waktu-nyata," saya tidak terlalu peduli dengan milidetik atau bahkan 5 detik, tetapi saya memiliki banyak pertanyaan yang staf kami andalkan untuk mengarahkan alur kerja. Jika klien telah melakukan sesuatu untuk mereka (prosedur, imunisasi, dll.) Kami harus menunjukkannya dalam waktu singkat. Konversi sepele, dan / atau bahkan bukan konversi. Saya tidak terlalu khawatir dengan perubahan ke tabel vendor, karena mereka tidak sering berubah, dan saya harus melakukannya sekarang, tapi saya pikir lebih mudah untuk memperbarui / membuat ulang satu pemicu daripada selusin laporan / kueri / SPs. Saya menjalankan cek setelah setiap pembaruan.
jreed121
@ jreed121, saya juga berpikir bahwa itu adalah lebih mudah untuk memicu update (s) dari laporan. Anda mungkin memiliki pemicu pada setiap tabel sumber untuk menangkap perubahan, sehingga kemungkinan lebih dari satu pemicu. Namun, jangan mencoba untuk menulis semua perubahan yang diambil ini menjadi satu tabel besar yang didenormalisasi. Menuliskannya ke set tabel yang dinormalisasi dengan benar. Laporan Anda harus didasarkan pada tabel yang dinormalisasi ini yang Anda kontrol dan tidak boleh bergantung pada tabel asli yang mungkin berubah.
Vladimir Baranov
3

Dengan segala cara memasukkannya ke dalam seperangkat tabel standar sehingga Anda dapat mengubah tahap impor daripada harus mengubah laporan dan kueri yang rumit. Tetapi data masih harus dinormalisasi yang akan membutuhkan beberapa tabel (tetapi dengan indeks yang baik).

Seperti yang disebutkan orang lain, jangan gunakan pemicu, sinkronkan dalam batch.

Jangan khawatir tentang banyak gabungan, ketika data dinormalkan dan diindeks dengan benar, ini tidak menambah biaya atau beban manajemen yang signifikan.

Waktu untuk mendenormalisasi menjadi sesuatu seperti data warehouse adalah ketika Anda harus dapat membuat banyak jenis kueri yang berbeda pada data yang tidak dapat Anda prediksi. Ini memiliki kelemahan dan overhead sendiri dan harus digunakan di mana sesuai, bukan sebagai hal yang masuk akal.

JamesRyan
sumber
3

Saya bekerja dengan situasi yang sangat mirip seperti ini di masa lalu di perusahaan manufaktur 24x7 dan akhirnya memutuskan untuk menggunakan replikasi transaksional. Dimungkinkan untuk mengkonfigurasi DDL untuk direplikasi sedemikian rupa sehingga Anda dapat mendorong keluar apa pun tambalan yang berubah menjadi pelanggan. Jelas ada pro dan kontra untuk semuanya dan Anda perlu menimbang mereka untuk menentukan apa yang dapat Anda dukung terhadap apa yang terbaik untuk perusahaan.

Di sisi positif:

  1. "Waktu nyata" hanya terbatas pada kinerja komit jaringan dan transaksi pada pelanggan. Dalam pengalaman saya dengan sistem TPS yang cukup tinggi, kami direplikasi dalam waktu kurang dari 10 detik dari data "waktu nyata".
  2. Pemisahan beban kerja. Anda sedang menjalankan beban kerja campuran pada satu server. Jika Anda dapat memisahkan dua masalah ini, maka Anda mungkin bisa mendapatkan manfaat kinerja pada kedua sistem karena menghapus satu beban kerja dari persamaan
  3. Kontrol. Anda dapat membuat pengindeksan / statistik / modifikasi pemeliharaan yang sesuai dengan beban kerja pelaporan Anda.

Ada kontra, meskipun:

  1. Biaya. Lisensi lain dan lebih banyak perangkat keras (virtual, atau lainnya).
  2. Replikasi Ini berfungsi dengan baik setelah diatur dengan benar, tetapi bisa merepotkan untuk sampai ke titik itu.
  3. Pemeliharaan. Jika Anda membuat perubahan yang merusak pada struktur (mis. Menjatuhkan indeks), mereka akan kembali ketika snapshot diterapkan (setelah publikasi berubah atau ketika artikel telah berubah).
swasheck
sumber
2

Rencana saya adalah untuk menulis semua catatan ini ke satu tabel "catch-all", dan menulis pemicu pada tabel asli untuk mempertahankan catatan dalam tabel agregat ini.

Pemicu memiliki banyak masalah sehingga Anda harus menghindarinya:

  • Kesalahan dalam pemicu dapat menyebabkan transaksi asli dibatalkan
  • Pemicu yang benar menangani operasi multi-baris sulit untuk ditulis
  • Pemicu dapat membingungkan aplikasi klien dengan memodifikasi rowset yang dikembalikan (misalnya, pemicu menimpa jumlah baris yang terpengaruh)
  • Ketika satu pemicu memicu yang lain, hasilnya sulit diprediksi

Opsi yang lebih baik adalah pekerjaan yang secara berkala menyalin data ke tabel baru. Laporan Anda dapat menjalankan salinannya. Pekerjaan yang menyalin baris mudah untuk ditulis dan dipelihara, dan tidak ada risiko bahwa itu akan mempengaruhi operasi aplikasi pihak ketiga.

Andomar
sumber
1. Pemicu akan sederhana, sehingga kesalahan yang dilemparkan akan menjadi minimal jika ada sama sekali. 2. Pemicu itu sendiri tidak akan menangani beberapa baris (IE satu baris diperbarui pada tabel dengan pelatuk tidak akan menyebabkan beberapa baris diperbarui di tempat lain), tetapi beberapa baris bisa dimasukkan / diperbarui / dihapus sekaligus di sumbernya meja - apakah ini yang Anda maksud? 3. tidak bisakah ini ditangani NOCOUNT? 4. Tidak akan ada pemicu pada tabel tujuan, dan saya bisa memastikan yang sama untuk yang lain.
jreed121
Seperti yang Anda katakan, secara teori dimungkinkan untuk membuat pemicu berfungsi. Hanya saja dalam praktiknya mereka tidak pernah melakukannya.
Andomar