Memilih Normalisasi Basis Data vs. Transparansi Skema?

10

Sebuah persyaratan baru telah muncul pada basis kode lama, yang pada dasarnya memungkinkan komunikasi langsung (internal) antara dua kelas pengguna yang sebelumnya tidak terkait langsung (disimpan dalam tabel yang berbeda dengan skema yang sama sekali berbeda dan, sayangnya, kode ini hampir tidak sadar OO, banyak kurang dirancang, jadi tidak ada kelas induk). Karena kita keluar untuk menggantung tas pada pengaturan lama ini yang tidak pernah mempertimbangkan fungsi ini, tidak ada jaminan bahwa tidak ada tabrakan PK - mengingat dataset yang digunakan, secara praktis dijamin ada ADA.

Jadi, solusinya tampak jelas: bunuh dengan api dan tulis ulang seluruh tabel pemetaan berantakan . Saya mendapatkan dua arah untuk cara-cara yang mungkin untuk mengimplementasikan peta, tapi saya bukan DBA, jadi saya tidak yakin apakah ada pro dan kontra yang saya lewatkan.

Demi memperjelas abstraksi, pertimbangkan tiga kelompok data pengguna yang berbeda: Profesor, Administrasi, Siswa (Tidak, ini bukan tugas pekerjaan rumah. Janji!)

Pemetaan 1

(professor_id, admin_id, dan student_id adalah kunci asing ke tabel masing-masing)

| mailing_id (KEY) | professor_id | admin_id | student_id | 
-------------------------------------------------------
| 1001             |     NULL     |    87    |  NULL      |
| 1002             |     123      |   NULL   |  NULL      |
| 1003             |     NULL     |   NULL   |  123       |

+/- untuk pendekatan ini tampaknya cukup berat di kontra:

  • Dua bidang "terbuang" per baris
  • Melanggar 2NF
  • Rentan untuk menyisipkan / memperbarui anomali (baris dengan hanya 0-1 bidang yang disetel NULL, mis.)

Pro bukan tanpa kemampuan mereka sendiri, meskipun:

  • Pemetaan dapat dilakukan dengan pencarian tunggal
  • Mudah menentukan "sumber" data untuk pengguna yang diberikan dari mailing_id

Sejujurnya, dalam perut saya, saya tidak suka ide ini sama sekali.

Pemetaan 2

(anggap MSG_ * adalah konstanta yang didefinisikan, tipe enum, atau pengidentifikasi lain yang sesuai)

| mailing_id (KEY)  | user_type (UNIQUE1) | internal_id (UNIQUE2)| 
------------------------------------------------------------------
| 1001              | MSG_ADMIN          | 87                    |
| 1002              | MSG_PROF           | 123                   |
| 1003              | MSG_STUDENT        | 123                   |

Dengan pengaturan ini, dan indeks komposit unik dari {user_type, internal_id} segalanya menjadi jauh lebih bersih, 3NF dipertahankan, dan kode aplikasi tidak harus memeriksa untuk anomali I / U.

Pada sisi negatifnya, ada sedikit kehilangan transparansi dalam menentukan tabel sumber pengguna yang harus ditangani di luar DB, pada dasarnya berjumlah pemetaan tingkat aplikasi nilai-nilai user_type ke tabel. Saat ini, saya (agak kuat) condong ke arah pemetaan ke-2 ini, karena downside agak kecil.

TETAPI saya dengan susah payah menyadari keterbatasan saya sendiri, dan saya yakin saya mungkin telah melewatkan keuntungan atau batu sandungan di kedua arah, jadi saya beralih ke pikiran yang lebih bijaksana daripada milik saya.

GeminiDomino
sumber
2
Anda mungkin menemukan gagasan Martin Fowler tentang peran sebagai bacaan yang menarik.
Marjan Venema
Itu memang menarik. Sayangnya tidak terlalu banyak wawasan tentang masalah spesifik saya
GeminiDomino
Anda akan mendapatkan profesor yang menjadi administrator dan mahasiswa yang mendapatkan pekerjaan di administrasi atau bahkan kembali 10 tahun kemudian sebagai staf pengajar. Anda mungkin sudah memilikinya. Apakah Anda akan memisahkan mereka atau mencoba menyatukan?
Elin
Peran hanyalah contoh, tapi saya mengerti maksud Anda. Dalam praktiknya, bahkan jika pengguna memang beralih peran, mereka akan tetap sebagai catatan terpisah.
GeminiDomino
Jika akan lebih bagus jika Anda akan frase ulang paragraf pertama. Agak tidak jelas. Maksud saya, jelas ada masalah tetapi tidak cukup jelas apa itu.
Tulains Córdova

Jawaban:

1

Ide kedua Anda adalah yang benar. Pendekatan ini memungkinkan Anda melakukan semua pemetaan yang perlu Anda lakukan untuk mengintegrasikan tiga ruang utama bertabrakan Anda.

Yang penting, ini memungkinkan database memaksakan sebagian besar konsistensi yang Anda butuhkan menggunakan batasan deklaratif .

Anda sudah memiliki lebih banyak kode daripada yang Anda inginkan, jadi jangan menambahkan kode lebih dari yang diperlukan untuk menjaga agar daftar kunci terintegrasi Anda konsisten. Biarkan mesin database Anda melakukan apa yang dibangun untuk dilakukan.

"Anak bermasalah" yang membuat Anda tidak nyaman dalam Pemetaan 2 adalah USER_TYPEkolom. Kolom ini penting karena Anda perlu memastikan bahwa itu INTERNAL_IDhanya muncul paling banyak satu kali per jenis pengguna. Satu-satunya saat Anda membutuhkan kode yang bahkan disadari USER_TYPEadalah kode yang menyisipkan dan menghapus dari tabel pemetaan Anda. Ini bisa dilokalisasi dengan cukup baik. Saya akan berasumsi bahwa Anda akan membuat satu titik dalam kode Anda di mana konten tabel pemetaan dipertahankan. Kolom tambahan di tempat yang satu ini tempat data ditulis bukanlah masalah besar. Yang benar-benar ingin Anda hindari adalah menambahkan kolom tambahan di mana pun data dibaca .

Kode dalam sub-aplikasi Anda yang perlu menggunakan pemetaan bisa sangat tidak tahu apa-apa USER_TYPEhanya dengan memberikan masing-masing sub-aplikasi tampilan yang menyaring pemetaan ke tipe pengguna satu aplikasi tertentu.

Joel Brown
sumber
3

Dari pengalaman, rekomendasi saya adalah memilih konsistensi daripada keanggunan atau 'praktik terbaik'. Yaitu untuk mencocokkan desain yang ada dan pergi dengan TIGA milis (satu untuk setiap peran) dengan mailing_id, user_idstruktur bidang sederhana .

Ini tidak elegan tetapi memiliki beberapa keuntungan ...

  1. Menyesuaikan struktur yang ada akan lebih mudah bagi siapa saja yang akan mengerjakan skema ini sebelum dimasukkan ke padang rumput.
  2. Anda tidak memiliki bidang terbuang dan Anda tidak meminta db untuk mencocokkan hal-hal yang tidak akan ada.
  3. Karena setiap tabel hanya untuk satu sama lain dan itu akan relatif mudah untuk membuat tampilan yang mengikat semua data untuk rutinitas Anda untuk digunakan.

Saya yakin banyak orang lain akan tidak setuju dengan pendekatan ini, tetapi tujuan utama normalisasi dan praktik terbaik adalah untuk membuat kode lebih konsisten sehingga lebih mudah untuk mengikuti dan men-debug ... dan jelas membawa seluruh basis kode ke awal mungkin tidak layak.

James Snell
sumber
Masalah dengan pendekatan itu adalah bahwa database kemudian tidak dapat menegakkan keunikan dalam id surat, yang merupakan tujuan utama pemetaan di tempat pertama: jika tidak, memasangkan bidang ID individu dari setiap tabel, dengan indikator "tipe pengguna" bisa menjadi dilakukan tanpa perubahan apa pun.
GeminiDomino
Saya melihat apa yang Anda maksud tetapi setelah bekerja pada sistem semacam itu saya telah memberikan opsi yang mungkin tidak Anda pertimbangkan. Sejauh yang saya lihat id surat akan memerlukan beberapa konten untuk merujuk ke suatu tempat (apa yang dikirim atau bagaimana menemukan dokumen) jadi id surat harus tetap merupakan kunci asing yang berarti masalah keunikan akan diselesaikan di tempat lain. Saat saya membacanya, tabel admin data siswa dan prof yang ditautkan mungkin memiliki struktur yang berbeda sehingga saya tidak bisa melihat bidang tipe pengguna menambahkan nilai. Pengembang asli pasti telah menemukan masalah ini, apa yang mereka lakukan?
James Snell
Bidang "tipe pengguna" akan menentukan tabel mana yang akan dikaitkan dengan catatan tertentu. Itu harus ditangani pada tingkat aplikasi, dan karena mereka ADA dalam tabel yang berbeda, tidak ada cara yang baik untuk menjadikannya sebagai batasan kunci asing. Sayangnya, pengembang asli tampaknya tidak mempertimbangkan masalah ini sama sekali, itulah sebabnya ia berubah menjadi berantakan. :)
GeminiDomino