Saya seorang pengembang perangkat lunak. Saya suka kode, tapi saya benci database ... Saat ini, saya membuat situs web di mana pengguna akan diizinkan untuk menandai entitas yang disukai (seperti di FB), beri tag dan komentar .
Saya terjebak pada desain tabel database untuk menangani fungsi ini. Solusi itu sepele, jika kita bisa melakukan ini hanya untuk satu jenis hal (mis. Foto). Tetapi saya perlu mengaktifkan ini untuk 5 hal yang berbeda (untuk saat ini, tetapi saya juga berasumsi bahwa jumlah ini dapat bertambah, seiring dengan meningkatnya seluruh layanan).
Saya menemukan beberapa pertanyaan serupa di sini, tetapi tidak ada yang memiliki jawaban yang memuaskan, jadi saya mengajukan pertanyaan ini lagi.
Pertanyaannya adalah, bagaimana mendesain database dengan benar, efisien dan elastis , sehingga dapat menyimpan komentar untuk tabel yang berbeda , suka untuk tabel yang berbeda dan tag untuk mereka. Beberapa pola desain sebagai jawaban akan lebih baik;)
Penjelasan terperinci : Saya memiliki tabel User
dengan beberapa data pengguna, dan 3 tabel lagi : Photo
dengan foto , Articles
dengan artikel , Places
dengan tempat . Saya ingin mengaktifkan semua pengguna yang login untuk:
mengomentari salah satu dari 3 tabel tersebut
tandai salah satu dari mereka sebagai disukai
tandai salah satu dari mereka dengan beberapa tag
Saya juga ingin menghitung jumlah suka untuk setiap elemen dan berapa kali tag tertentu digunakan.
1 st pendekatan :
a) Untuk tag , saya akan membuat tabel Tag [TagId, tagName, tagCounter]
, maka saya akan membuat banyak-ke-banyak hubungan tabel untuk: Photo_has_tags
, Place_has_tag
, Article_has_tag
.
b) Jumlah yang sama untuk komentar.
c) Aku akan membuat tabel LikedPhotos [idUser, idPhoto]
, LikedArticles[idUser, idArticle]
, LikedPlace [idUser, idPlace]
. Jumlah suka akan dihitung oleh kueri (yang, saya anggap buruk). Dan...
Saya benar-benar tidak suka desain ini untuk bagian terakhir, baunya buruk bagi saya;)
2 nd pendekatan :
Saya akan membuat tabel ElementType [idType, TypeName == some table name]
yang akan diisi oleh administrator (saya) dengan nama-nama tabel yang dapat disukai , dikomentari atau ditandai . Maka saya akan membuat tabel :
a) LikedElement [idLike, idUser, idElementType, idLikedElement]
dan sama untuk Komentar dan Tag dengan kolom yang tepat untuk masing-masing. Sekarang, ketika saya ingin membuat foto disukai saya akan memasukkan:
typeId = SELECT id FROM ElementType WHERE TypeName == 'Photo'
INSERT (user id, typeId, photoId)
dan untuk tempat:
typeId = SELECT id FROM ElementType WHERE TypeName == 'Place'
INSERT (user id, typeId, placeId)
dan seterusnya ... Saya pikir pendekatan kedua lebih baik, tetapi saya juga merasa ada sesuatu yang hilang dalam desain ini juga ...
Akhirnya, saya juga bertanya-tanya di mana tempat terbaik untuk menyimpan counter berapa kali elemen itu disukai. Saya hanya bisa memikirkan dua cara:
- dalam
Photo/Article/Place
tabel elemen ( ) - dengan pilih count ().
Saya harap penjelasan saya tentang masalah ini lebih menyeluruh sekarang.
Jawaban:
Solusi yang paling dapat dikembangkan adalah memiliki hanya satu "basis" tabel (terhubung ke "suka", tag dan komentar), dan "mewarisi" semua tabel lain darinya. Menambahkan jenis entitas baru melibatkan hanya dengan menambahkan tabel "baru" - itu kemudian secara otomatis dihubungkan ke seluruh mesin suka / tag / komentar.
Istilah entitas-hubungan untuk ini adalah "kategori" (lihat Panduan Metode ERwin , bagian: "Hubungan Subtipe"). Simbol kategori adalah:
Dengan asumsi pengguna dapat menyukai banyak entitas, tag yang sama dapat digunakan untuk lebih dari satu entitas tetapi komentar bersifat spesifik entitas, model Anda dapat terlihat seperti ini:
BTW, ada sekitar 3 cara untuk menerapkan "kategori ER":
Kecuali Anda memiliki persyaratan kinerja yang sangat ketat, pendekatan ketiga mungkin yang terbaik (artinya tabel fisik cocok dengan 1: 1 entitas dalam diagram di atas).
sumber
BIGINT
adalah 9223372036854775807. Dengan asumsi Anda memasukkan satu baris setiap detik, Anda akan kehabisan nilai yang tersedia dalam ~ 300 miliar tahun. Tentunya, Anda akan dapat melakukan porting ke integer 128-bit saat itu!Karena Anda "membenci" database, mengapa Anda mencoba mengimplementasikannya? Sebagai gantinya, mintalah bantuan dari seseorang yang mencintai dan bernafas dalam hal ini.
Kalau tidak, belajarlah untuk mencintai basis data Anda. Basis data yang dirancang dengan baik menyederhanakan pemrograman, merekayasa situs, dan memperlancar operasinya. Bahkan seorang desainer d / b yang berpengalaman tidak akan memiliki pandangan ke depan yang lengkap dan sempurna: beberapa perubahan skema akan dibutuhkan saat pola penggunaan muncul atau persyaratan berubah.
Jika ini adalah proyek satu orang, programkan antarmuka basis data menjadi operasi sederhana menggunakan prosedur tersimpan: add_user, update_user, add_comment, add_like, upload_photo, list_comments, dll. Jangan menanamkan skema ke dalam satu baris kode pun. Dengan cara ini, skema database dapat diubah tanpa memengaruhi kode apa pun: hanya prosedur tersimpan yang harus tahu tentang skema tersebut.
Anda mungkin harus memperbaiki skema beberapa kali. Ini normal. Jangan khawatir tentang menyempurnakannya untuk pertama kali. Jadikan itu cukup fungsional untuk membuat prototipe desain awal. Jika Anda memiliki banyak waktu, gunakan beberapa, lalu hapus skema dan lakukan lagi. Itu selalu lebih baik yang kedua kalinya.
sumber
Ini adalah ide umum, tolong jangan terlalu memperhatikan gaya nama bidang, tetapi lebih pada hubungan dan struktur
Pseudocode ini akan mendapatkan semua komentar foto dengan ID 5
SELECT * DARI tindakan
WHERE action.id_Stuff = 5
AND actions.typeStuff = "photo"
AND actions.typeAction = "comment"
Kodesemu ini akan mendapatkan semua suka atau pengguna yang menyukai foto dengan ID 5
(Anda dapat menggunakan count () untuk mendapatkan jumlah suka)
sumber
SELECT * FROM actions WHERE actions.id=133 AND actions.typeStuff = "comment" AND actions.typeAction = "like"
id_stuff
kolom tersebut berisi nilai unik di masing-masing dari tiga tabel?sejauh yang saya mengerti. diperlukan beberapa tabel. Ada banyak hubungan di antara mereka.
sumber
Lihatlah pola akses yang akan Anda butuhkan. Apakah ada di antara mereka yang membuat pilihan desain saya sulit atau tidak efisien?
Jika tidak mendukung yang membutuhkan lebih sedikit tabel
Pada kasus ini:
Saya pikir pendekatan "diskriminatif" Anda, opsi 2, menghasilkan pertanyaan yang lebih sederhana dalam beberapa kasus dan tampaknya tidak jauh lebih buruk dalam kasus lain sehingga saya akan melakukannya.
sumber
Jelas pergi dengan pendekatan kedua di mana Anda memiliki satu tabel dan menyimpan tipe elemen untuk setiap baris, itu akan memberi Anda lebih banyak fleksibilitas. Pada dasarnya ketika sesuatu secara logis dapat dilakukan dengan lebih sedikit tabel, hampir selalu lebih baik untuk pergi dengan lebih sedikit tabel. Satu keuntungan yang muncul di benak saya saat ini tentang kasus khusus Anda, pertimbangkan Anda ingin menghapus semua elemen yang disukai pengguna tertentu, dengan pendekatan pertama Anda, Anda perlu mengeluarkan satu permintaan untuk setiap jenis elemen tetapi dengan pendekatan kedua itu dapat dilakukan dengan hanya satu kueri atau pertimbangkan ketika Anda ingin menambahkan tipe elemen baru, dengan pendekatan pertama melibatkan membuat tabel baru untuk setiap tipe baru tetapi dengan pendekatan kedua Anda tidak boleh melakukan apa pun ...
sumber
Pertimbangkan untuk menggunakan tabel per entitas untuk komentar dan lain-lain. Lebih banyak tabel - sharding dan scaling yang lebih baik. Ini bukan masalah untuk mengontrol banyak tabel yang serupa untuk semua framework yang saya tahu.
Suatu hari Anda harus mengoptimalkan bacaan dari struktur tersebut. Anda dapat dengan mudah membuat tabel agragasi dari basis dan kehilangan sedikit waktu menulis.
Satu meja besar dengan kamus mungkin menjadi tidak terkendali suatu hari.
sumber