Ada dua tabel: Deal
dan DealCategories
. Satu kesepakatan dapat memiliki banyak kategori kesepakatan.
Jadi cara yang tepat adalah membuat tabel DealCategories
dengan struktur berikut:
DealCategoryId (PK)
DealId (FK)
DealCategoryId (FK)
Namun, tim outsourcing kami menyimpan beberapa kategori dalam Deal
tabel dengan cara ini:
DealId (PK)
DealCategory -- In here they store multiple deal ids separated by commas like this: 18,25,32.
Saya merasa apa yang mereka lakukan salah, tetapi saya tidak tahu bagaimana menjelaskan dengan jelas mengapa ini tidak benar.
Bagaimana saya harus menjelaskan kepada mereka bahwa ini salah? Atau mungkin akulah yang salah dan ini bisa diterima?
database-design
foreign-key
Sarawut Positwinyu
sumber
sumber
Jawaban:
Ya itu ide yang buruk.
Alih-alih pergi:
Anda sekarang harus pergi:
Maka Anda perlu melakukan hal-hal dalam kode aplikasi Anda untuk membagi daftar koma itu menjadi angka-angka individual, lalu query database secara terpisah:
Antipattern desain ini berasal dari kesalahpahaman lengkap pemodelan relasional (Anda tidak perlu takut tabel. Tabel adalah teman Anda. Gunakan mereka), atau keyakinan salah arah yang aneh, lebih cepat mengambil daftar yang dipisahkan koma dan membaginya dalam kode aplikasi daripada menambahkan tabel tautan (tidak pernah ada). Opsi ketiga adalah bahwa mereka tidak cukup percaya diri / cukup kompeten dengan SQL untuk dapat mengatur kunci asing, tetapi jika itu masalahnya mereka seharusnya tidak ada hubungannya dengan desain model relasional.
SQL Antipatterns (Karwin, 2010) mencurahkan seluruh bab untuk antipattern ini (yang ia sebut 'Jaywalking'), halaman 15-23. Juga, penulis telah memposting pertanyaan serupa di SO . Poin-poin penting yang dia catat (sebagaimana diterapkan pada contoh ini) adalah:
COUNT
,SUM
dll), sekali lagi, bervariasi dari 'rumit' hingga 'hampir tidak mungkin'. Tanyakan pengembang Anda bagaimana mereka membuat Anda daftar semua kategori dengan jumlah jumlah penawaran dalam kategori itu. Dengan desain yang tepat, itulah empat baris SQL.VARCHAR
batasan panjang daftar. Meskipun jika Anda memiliki daftar yang dipisahkan koma, lebih dari 4000 karakter, kemungkinan parsing monster itu akan menjadi lambat sekali.TLDR: Ini adalah desain yang cacat secara fundamental, tidak akan menskala dengan baik, ini memperkenalkan kompleksitas tambahan bahkan untuk pertanyaan paling sederhana, dan saat itu juga, itu akan memperlambat aplikasi Anda.
sumber
Itu sebenarnya desain yang bagus jika Anda hanya perlu menanyakan kategori untuk kesepakatan yang diberikan.
Tapi itu mengerikan jika Anda ingin mengetahui semua penawaran dalam kategori tertentu.
Dan itu juga membuatnya sangat sulit dan rawan kesalahan untuk melakukan hal lain - seperti pembaruan, hitungan, bergabung, dll.
Denormalization memiliki tempatnya, tetapi Anda harus mengingatnya melakukan optimasi untuk satu jenis kueri dengan mengorbankan semua lainnya yang mungkin Anda buat terhadap data yang sama. Jika Anda tahu Anda akan selalu bertanya dalam satu pola, maka mungkin memberi Anda keuntungan untuk menggunakan desain denormalized. Tetapi jika ada kemungkinan Anda bisa membutuhkan lebih banyak fleksibilitas dalam jenis pertanyaan, tetap dengan desain normal.
Seperti bentuk pengoptimalan lainnya, Anda perlu mengetahui kueri apa yang akan dijalankan sebelum Anda dapat memutuskan apakah denasionalisasi dibenarkan.
sumber
select * from DealCategories where DealId in (1,2,3,4,...)
. Anda memiliki lebih banyak pengalaman, mengenai desain basis data, daripada saya, jadi mungkin Anda memiliki alasan yang bagus dalam beberapa kasus untuk "penyetelan ekstrem" dalam kasus yang sangat spesifik. Satu-satunya ide saya untuk membenarkan ini adalahselect
beban yang sangat tinggi pada Deal / DealCategory. Bagi saya ini terlihat seperti beberapa tim outsourcing tanpa pengetahuan desain DB, selain membuat tabel, menciptakannya.Nilai berganda dalam suatu kolom bertentangan dengan formulir normal pertama.
Ini juga sama sekali tidak mendapatkan kecepatan, karena tabel harus ditautkan dalam database. Anda harus membaca dan mengurai string terlebih dahulu, lalu pilih semua kategori untuk "Kesepakatan".
Implementasi yang benar akan menjadi tabel persimpangan seperti "DealDealCategories", dengan DealId dan DealCategoryId.
Implementasi hierarki yang buruk?
Juga, FK di DealCategories ke DealCategory lain tampak seperti implementasi hierarki / pohon DealCategories yang buruk. Bekerja dengan pohon melalui relasi Parent ID (disebut adjacency list) sungguh menyebalkan!
Periksa Nested Set (bagus untuk dibaca, tetapi sulit dimodifikasi) dan Tabel Penutupan (kinerja keseluruhan terbaik, tetapi kemungkinan penggunaan memori tinggi - mungkin tidak terlalu banyak untuk DealCategories Anda) saat menerapkan hierarki!
sumber