Saya sedang berupaya memperbarui basis data produk situs web kami. Ini dibangun di MySQL tetapi ini lebih merupakan pertanyaan pola desain database umum.
Saya berencana beralih ke pola Supertype / Subtype. Basis data kami saat ini / sebelumnya sebagian besar merupakan tabel tunggal yang memiliki data pada satu jenis produk. Kami sedang memperluas penawaran produk kami untuk memasukkan produk yang berbeda.
Draf desain baru ini seperti ini:
Product product_[type] product_attribute_[name]
---------------- ---------------- ----------------------------
part_number (PK) part_number (FK) attributeId (PK)
UPC specific_attr1 (FK) attribute_name
price specific_attr2 (FK)
... ...
Saya punya pertanyaan tentang tabel atribut produk. Idenya di sini adalah produk dapat memiliki daftar atribut yang diberikan seperti warna: merah, hijau, biru, atau bahan: plastik, kayu, krom, aluminium, dll.
Daftar ini akan disimpan dalam sebuah tabel dan kunci utama (PK) untuk item atribut itu akan digunakan dalam tabel produk tertentu sebagai kunci asing (FK).
(Buku Martin Fowler, Pola Arsitektur Aplikasi Perusahaan menyebutnya " Pemetaan Kunci Asing ")
Ini memungkinkan antarmuka situs web untuk menarik daftar atribut untuk tipe atribut yang diberikan dan meludahkannya dalam menu pilih tarik turun atau elemen UI lainnya. Daftar ini dapat dianggap sebagai daftar "nilai atribut".
Jumlah sambungan yang akhirnya terjadi ketika menarik produk tertentu tampak berlebihan bagi saya. Anda harus bergabung dengan setiap tabel atribut produk ke produk sehingga Anda bisa mendapatkan bidang atribut itu. Umumnya, bidang itu mungkin hanya berupa string (varchar) untuk namanya.
Pola desain ini akhirnya membuat sejumlah besar tabel dan Anda berakhir dengan tabel untuk setiap atribut. Satu ide untuk mengatasi hal ini adalah membuat tabel “grab bag” untuk semua atribut produk. Sesuatu seperti ini:
product_attribute
----------------
attributeId (PK)
name
field_name
Dengan cara ini, meja Anda mungkin terlihat seperti ini:
1 red color
2 blue color
3 chrome material
4 plastic material
5 yellow color
6 x-large size
Ini bisa membantu mengurangi creep meja tetapi tidak mengurangi jumlah gabungan dan rasanya sedikit salah menggabungkan begitu banyak jenis yang berbeda menjadi satu tabel. Tetapi Anda akan bisa mendapatkan semua atribut "warna" yang tersedia dengan cukup mudah.
Namun, mungkin ada atribut yang memiliki bidang lebih dari sekadar "nama" seperti nilai RGB warna. Ini akan memerlukan atribut khusus untuk memiliki tabel lain atau memiliki bidang tunggal untuk pasangan nama: nilai (yang memiliki kelemahan sendiri).
Pola desain terakhir yang dapat saya pikirkan adalah menyimpan nilai atribut aktual dalam tabel produk tertentu dan tidak memiliki "tabel atribut" sama sekali. Sesuatu seperti ini:
Product product_[type]
---------------- ----------------
part_number (PK) part_number (FK)
UPC specific_attr1
price specific_attr2
... ...
Alih-alih Kunci Asing ke tabel lain, itu akan berisi nilai aktual seperti:
part_number color material
----------- ----- --------
1234 red plastic
Ini akan menghilangkan gabungan dan mencegah merayap meja (mungkin?). Namun, ini mencegah memiliki "daftar resmi" atribut. Anda bisa mengembalikan semua nilai yang saat ini dimasukkan untuk bidang tertentu (yaitu: warna) tetapi ini juga menghilangkan gagasan memiliki "daftar nilai" yang diotorisasi untuk atribut yang diberikan.
Untuk memiliki daftar itu, Anda masih harus membuat tabel atribut "grab bag" atau memiliki beberapa tabel (table creep) untuk setiap atribut.
Ini menciptakan kelemahan yang lebih besar (dan mengapa saya tidak pernah menggunakan pendekatan ini) sekarang memiliki nama produk di beberapa lokasi.
Jika Anda memiliki nilai warna "merah" di "tabel atribut utama" dan juga menyimpannya di tabel "product_ [type]", pembaruan ke tabel "master" akan menyebabkan masalah integritas data potensial jika aplikasi tidak perbarui semua catatan dengan nilai lama di tabel "product_type" juga.
Jadi, setelah penjelasan saya yang panjang lebar dan analisis skenario ini, kesadaran saya adalah bahwa ini bukan skenario yang tidak biasa dan bahkan mungkin ada nama untuk jenis situasi seperti ini.
Apakah ada solusi yang diterima secara umum untuk tantangan desain ini? Apakah jumlah gabungan yang berpotensi besar dapat diterima jika tabelnya relatif kecil? Apakah menyimpan nama atribut, alih-alih atribut PK dapat diterima dalam beberapa situasi? Apakah ada solusi lain yang tidak saya pikirkan?
Beberapa catatan tentang basis data / aplikasi produk ini:
- Produk tidak sering diperbarui / ditambahkan / dihapus
- Atribut tidak sering diperbarui / ditambahkan / dihapus
- Tabel ini paling sering ditanyakan untuk membaca / mengembalikan informasi
- Caching sisi server diaktifkan untuk men-cache hasil dari kueri / hasil yang diberikan
- Saya berencana memulai dengan hanya satu jenis produk dan memperluas / menambah yang lain dari waktu ke waktu dan akan berpotensi 10+ jenis yang berbeda
sumber
Jawaban:
Saya pribadi akan menggunakan model yang mirip dengan yang berikut:
Tabel produk akan sangat mendasar, detail produk utama Anda:
Kedua tabel atribut untuk menyimpan masing-masing atribut yang berbeda.
Terakhir, buat tabel product_attribute sebagai tabel JOIN antara setiap produk dan atributnya yang terkait dengannya.
Bergantung pada bagaimana Anda ingin menggunakan data yang Anda lihat pada dua gabungan:
Lihat SQL Fiddle dengan Demo . Ini mengembalikan data dalam format:
Tetapi jika Anda ingin mengembalikan data dalam
PIVOT
format di mana Anda memiliki satu baris dengan semua atribut sebagai kolom, Anda bisa menggunakanCASE
pernyataan dengan agregat:Lihat SQL Fiddle dengan Demo . Data dikembalikan dalam format:
Ketika Anda melihat data mungkin dalam format yang lebih baik untuk Anda, tetapi jika Anda memiliki jumlah atribut yang tidak diketahui, itu akan dengan mudah menjadi tidak dapat dipertahankan karena nama atribut pengodean keras, jadi di MySQL Anda dapat menggunakan pernyataan yang disiapkan untuk membuat pivot dinamis . Kode Anda adalah sebagai berikut (Lihat SQL Fiddle With Demo ):
Ini menghasilkan hasil yang sama seperti versi kedua tanpa perlu melakukan hard-code apa pun. Meskipun ada banyak cara untuk memodelkan ini saya pikir desain basis data ini adalah yang paling fleksibel.
sumber
Saya akan memperluas jawaban Taryn dan memodifikasi tabel atribut untuk memiliki fk_attribute_type_id kolom yang akan bukannya ATTRIBUTE_NAME kolom dan poin untuk attribute_type tabel baru.
Jadi, Anda memiliki tipe atribut terstruktur dalam satu tabel dan Anda dapat mengubahnya kapan saja di satu tempat.
Menurut pendapat saya itu lebih baik untuk bekerja dengan "dial" semacam itu (tabel dengan tipe yang mungkin) daripada dengan tipe enum (seperti itu di kolom atribut_name (dan di atas itu sebenarnya bukan nama, tipe atributnya)).
sumber