Saya menerapkan model berikut untuk menyimpan data terkait pengguna di tabel saya - Saya punya 2 kolom - uid
(kunci utama) dan meta
kolom yang menyimpan data lain tentang pengguna dalam format JSON.
uid | meta
--------------------------------------------------
1 | {name:['foo'],
| emailid:['[email protected]','[email protected]']}
--------------------------------------------------
2 | {name:['sann'],
| emailid:['[email protected]','[email protected]']}
--------------------------------------------------
Apakah ini cara yang lebih baik (kinerja-bijaksana, desain-bijaksana) dari model satu-kolom-per-properti, di mana meja akan memiliki banyak kolom seperti uid
, name
, emailid
.
Yang saya suka tentang model pertama adalah, Anda dapat menambahkan sebanyak mungkin bidang tidak ada batasan.
Juga, saya bertanya-tanya, sekarang saya telah menerapkan model pertama. Bagaimana cara saya melakukan kueri, seperti, saya ingin mengambil semua pengguna yang memiliki nama seperti 'foo'?
Pertanyaan - Manakah cara terbaik untuk menyimpan data terkait pengguna (dengan mengingat bahwa jumlah bidang tidak diperbaiki) dalam basis data menggunakan - JSON atau kolom per bidang? Juga, jika model pertama diterapkan, bagaimana cara query database seperti dijelaskan di atas? Haruskah saya menggunakan kedua model, dengan menyimpan semua data yang dapat dicari oleh kueri di baris terpisah dan data lainnya di JSON (apakah baris berbeda)?
Memperbarui
Karena tidak akan ada terlalu banyak kolom di mana saya perlu melakukan pencarian, apakah sebaiknya menggunakan kedua model? Kunci-per-kolom untuk data yang saya butuhkan untuk mencari dan JSON untuk orang lain (dalam database MySQL yang sama)?
sumber
Jawaban:
Diperbarui 4 Juni 2017
Mengingat bahwa pertanyaan / jawaban ini telah mendapatkan popularitas, saya pikir itu layak diperbarui.
Ketika pertanyaan ini awalnya diposting, MySQL tidak memiliki dukungan untuk tipe data JSON dan dukungan di PostgreSQL masih dalam tahap awal. Sejak 5.7, MySQL sekarang mendukung tipe data JSON (dalam format penyimpanan biner), dan PostgreSQL JSONB telah matang secara signifikan. Kedua produk menyediakan tipe JSON yang dapat menyimpan dokumen sewenang-wenang, termasuk dukungan untuk mengindeks kunci tertentu dari objek JSON.
Namun, saya masih mendukung pernyataan asli saya bahwa preferensi default Anda, ketika menggunakan database relasional, masih harus berupa kolom-per-nilai. Database relasional masih dibangun dengan asumsi bahwa data di dalamnya akan dinormalisasi dengan cukup baik. Perencana permintaan memiliki informasi pengoptimalan yang lebih baik ketika melihat kolom daripada ketika melihat kunci dalam dokumen JSON. Kunci asing dapat dibuat antar kolom (tetapi tidak antara kunci dalam dokumen JSON). Yang penting: jika sebagian besar skema Anda cukup volatile untuk membenarkan menggunakan JSON, Anda mungkin ingin setidaknya mempertimbangkan jika database relasional adalah pilihan yang tepat.
Yang mengatakan, beberapa aplikasi yang sempurna berhubungan atau berorientasi pada dokumen. Sebagian besar aplikasi memiliki campuran keduanya. Berikut adalah beberapa contoh di mana saya secara pribadi menemukan JSON berguna dalam database relasional:
Saat menyimpan alamat email dan nomor telepon untuk kontak, tempat menyimpannya sebagai nilai dalam array JSON jauh lebih mudah dikelola daripada beberapa tabel terpisah
Menyimpan preferensi pengguna kunci / nilai sewenang-wenang (di mana nilainya bisa boolean, tekstual, atau numerik, dan Anda tidak ingin memiliki kolom terpisah untuk tipe data yang berbeda)
Menyimpan data konfigurasi yang tidak memiliki skema yang ditentukan (jika Anda sedang membangun Zapier, atau IFTTT dan perlu menyimpan data konfigurasi untuk setiap integrasi)
Saya yakin ada yang lain juga, tetapi ini hanya beberapa contoh singkat.
Jawaban Asli
Jika Anda benar-benar ingin dapat menambahkan bidang sebanyak yang Anda inginkan tanpa batasan (selain batas ukuran dokumen sewenang-wenang), pertimbangkan solusi NoSQL seperti MongoDB.
Untuk database relasional: gunakan satu kolom per nilai. Menempatkan gumpalan JSON di kolom membuatnya hampir tidak mungkin untuk permintaan (dan sangat lambat ketika Anda benar-benar menemukan permintaan yang berfungsi).
Database relasional mengambil keuntungan dari tipe data saat pengindeksan, dan dimaksudkan untuk diimplementasikan dengan struktur yang dinormalisasi .
Sebagai catatan tambahan: ini bukan untuk mengatakan Anda tidak boleh menyimpan JSON dalam database relasional. Jika Anda menambahkan metadata sebenarnya, atau jika JSON Anda menggambarkan informasi yang tidak perlu ditanyakan dan hanya digunakan untuk tampilan, mungkin akan terlalu sulit untuk membuat kolom terpisah untuk semua titik data.
sumber
virtually impossible to query
" - hari ini psql memungkinkan Anda untuk mencari dan mengindeks jsonb"For relational databases"
dalam jawaban Anda = PSeperti kebanyakan hal "itu tergantung". Tidak benar atau salah / baik atau buruk dalam dirinya sendiri untuk menyimpan data dalam kolom atau JSON. Itu tergantung pada apa yang perlu Anda lakukan dengannya nanti. Bagaimana cara Anda memperkirakan mengakses data ini? Apakah Anda perlu referensi silang data lain?
Orang lain telah menjawab dengan cukup baik apa trade-off teknisnya.
Tidak banyak orang yang membahas bahwa aplikasi dan fitur Anda berkembang seiring waktu dan bagaimana keputusan penyimpanan data ini memengaruhi tim Anda.
Karena salah satu godaan menggunakan JSON adalah untuk menghindari migrasi skema dan jadi jika tim tidak disiplin, sangat mudah untuk memasukkan pasangan kunci / nilai lain ke dalam bidang JSON. Tidak ada migrasi untuk itu, tidak ada yang ingat untuk apa itu. Tidak ada validasi untuk itu.
Tim saya menggunakan JSON di sepanjang kolom sisi tradisional di postgres dan pada awalnya itu yang terbaik sejak memotong roti. JSON sangat menarik dan kuat, sampai suatu hari kami menyadari bahwa fleksibilitas datang pada biaya dan tiba-tiba merupakan titik yang sangat menyakitkan. Kadang-kadang titik itu merayap dengan sangat cepat dan kemudian menjadi sulit untuk berubah karena kami telah membangun banyak hal lain di atas keputusan desain ini.
Lembur, menambahkan fitur baru, memiliki data dalam JSON menyebabkan kueri tampak lebih rumit daripada apa yang mungkin ditambahkan jika kita terjebak pada kolom tradisional. Jadi kami mulai memancing nilai-nilai kunci tertentu kembali ke kolom sehingga kami bisa membuat gabungan dan membuat perbandingan antara nilai-nilai. Ide buruk. Sekarang kami memiliki duplikasi. Pengembang baru akan muncul dan menjadi bingung? Nilai apa yang harus saya simpan kembali? JSON satu atau kolom?
Bidang JSON menjadi laci sampah untuk potongan kecil ini dan itu. Tidak ada validasi data pada tingkat basis data, tidak ada konsistensi atau integritas antara dokumen. Itu mendorong semua tanggung jawab itu ke dalam aplikasi alih-alih mendapatkan tipe keras dan memeriksa kendala dari kolom tradisional.
Melihat ke belakang, JSON memungkinkan kami untuk beralih dengan sangat cepat dan mendapatkan sesuatu dari pintu. Itu bagus. Namun setelah kami mencapai ukuran tim tertentu, fleksibilitasnya juga memungkinkan kami untuk menggantung diri dengan tali panjang hutang teknis yang kemudian memperlambat kemajuan evolusi fitur selanjutnya. Gunakan dengan hati-hati.
Pikirkan panjang dan keras tentang apa sifat data Anda. Ini adalah dasar dari aplikasi Anda. Bagaimana data akan digunakan seiring waktu. Dan bagaimana mungkin MENGUBAH?
sumber
Hanya melemparkannya ke luar sana, tetapi WordPress memiliki struktur untuk hal-hal semacam ini (setidaknya WordPress adalah tempat pertama yang saya amati, mungkin berasal dari tempat lain).
Ini memungkinkan kunci tanpa batas, dan lebih cepat untuk mencari daripada menggunakan gumpalan JSON, tetapi tidak secepat beberapa solusi NoSQL.
EDIT
Untuk menyimpan histori / beberapa kunci
dan permintaan melalui sesuatu seperti ini:
sumber
emailid
kunci pada contoh yang saya berikan dalam pertanyaan saya.kelemahan dari pendekatan ini persis seperti yang Anda sebutkan:
itu membuatnya SANGAT lambat untuk menemukan sesuatu, karena setiap kali Anda perlu melakukan pencarian teks di atasnya.
nilai per kolom sebagai gantinya cocok dengan seluruh string.
Pendekatan Anda (data berbasis JSON) tidak masalah untuk data yang tidak perlu Anda cari, dan hanya perlu ditampilkan bersama dengan data normal Anda.
Sunting: Hanya untuk memperjelas, hal di atas berlaku untuk database relasional klasik. NoSQL menggunakan JSON secara internal, dan mungkin merupakan opsi yang lebih baik jika itu adalah perilaku yang diinginkan.
sumber
Pada dasarnya, model pertama yang Anda gunakan disebut sebagai penyimpanan berbasis dokumen. Anda harus melihat pada basis data berbasis dokumen NoSQL yang populer seperti MongoDB dan CouchDB . Pada dasarnya, dalam db berbasis dokumen, Anda menyimpan data dalam file json dan kemudian Anda dapat meminta file json ini.
Model kedua adalah struktur basis data relasional yang populer.
Jika Anda ingin menggunakan database relasional seperti MySql maka saya akan menyarankan Anda untuk hanya menggunakan model kedua. Tidak ada gunanya menggunakan MySql dan menyimpan data seperti pada model pertama .
Untuk menjawab pertanyaan kedua Anda, tidak ada cara untuk menanyakan nama seperti 'foo' jika Anda menggunakan model pertama .
sumber
Tampaknya Anda terutama ragu apakah akan menggunakan model relasional atau tidak.
Seperti contohnya, contoh Anda akan cocok dengan model relasional dengan cukup baik, tetapi masalahnya mungkin muncul ketika Anda perlu membuat model ini berkembang.
Jika Anda hanya memiliki satu (atau beberapa tingkat yang ditentukan sebelumnya) atribut untuk entitas utama Anda (pengguna), Anda masih bisa menggunakan model Nilai Atribut Nilai Entitas (EAV) dalam database relasional. (Ini juga memiliki pro dan kontra.)
Jika Anda mengantisipasi bahwa Anda akan mendapatkan nilai yang kurang terstruktur yang ingin Anda cari menggunakan aplikasi Anda, MySQL mungkin bukan pilihan terbaik di sini.
Jika Anda menggunakan PostgreSQL, Anda berpotensi mendapatkan yang terbaik dari kedua dunia. (Ini benar-benar tergantung pada struktur data yang sebenarnya di sini ... MySQL juga bukan pilihan yang salah, dan opsi NoSQL bisa menarik, saya hanya menyarankan alternatif.)
Memang, PostgreSQL dapat membangun indeks pada fungsi-fungsi (yang tidak dapat diubah) (yang tidak dapat saya ketahui sejauh MySQL) dan dalam versi terbaru, Anda dapat menggunakan PLV8 pada data JSON secara langsung untuk membangun indeks pada elemen-elemen minat JSON tertentu, yang akan meningkatkan kecepatan pertanyaan Anda saat mencari data itu.
EDIT:
Menggabungkan kedua model tidak selalu salah (dengan asumsi ruang tambahan dapat diabaikan), tetapi dapat menyebabkan masalah jika Anda tidak memastikan dua set data tetap sinkron: aplikasi Anda tidak boleh mengubah satu tanpa harus memperbarui yang lain .
Cara yang baik untuk mencapai ini adalah memiliki pemicu melakukan pembaruan otomatis, dengan menjalankan prosedur yang tersimpan dalam server database setiap kali pembaruan atau penyisipan dilakukan. Sejauh yang saya ketahui, bahasa prosedur tersimpan MySQL mungkin kurang mendukung untuk segala jenis pemrosesan JSON. Lagi PostgreSQL dengan dukungan PLV8 (dan mungkin RDBMS lainnya dengan bahasa prosedur tersimpan yang lebih fleksibel) harus lebih bermanfaat (memperbarui kolom relasional Anda secara otomatis menggunakan pemicu sangat mirip dengan memperbarui indeks dengan cara yang sama).
sumber
beberapa waktu bergabung di atas meja akan menjadi overhead. katakanlah untuk OLAP. jika saya memiliki dua tabel, satu adalah tabel PESANAN dan yang lainnya adalah ORDER_DETAILS. Untuk mendapatkan semua detail pesanan, kita harus menggabungkan dua tabel, ini akan membuat kueri lebih lambat ketika tidak ada baris dalam tabel yang bertambah, katakanlah dalam jutaan atau lebih .. gabung kiri / kanan terlalu lambat daripada gabung dalam. Saya pikir jika kita menambahkan string JSON / Objek dalam entri PESANAN masing-masing BERGABUNG akan dihindari. tambah pembuatan laporan akan lebih cepat ...
sumber
jawaban singkat Anda harus mencampur di antara mereka, gunakan json untuk data yang Anda tidak akan membuat hubungan dengan mereka seperti data kontak, alamat, berbagai produk
sumber
Anda mencoba memasukkan model non-relasional ke dalam basis data relasional, saya pikir Anda akan lebih baik dilayani menggunakan database NoSQL seperti MongoDB . Tidak ada skema standar yang sesuai dengan kebutuhan Anda untuk tidak membatasi jumlah bidang (lihat contoh koleksi MongoDB khas). Periksa dokumentasi MongoDB untuk mendapatkan gambaran tentang bagaimana Anda akan menanyakan dokumen Anda, misalnya
sumber
Seperti orang lain telah menunjukkan pertanyaan akan lebih lambat. Saya sarankan untuk menambahkan setidaknya kolom '_ID' ke permintaan dengan itu.
sumber