JSONB dengan pengindeksan vs hstore

28

Saya mencoba untuk memutuskan pada desain database, dengan asumsi sesedikit mungkin (mengenai bagaimana aplikasi web benar-benar berkembang) mungkin pada tahap ini.

Sebagai langkah pertama, memahami bahwa BERGABUNG itu mahal, saya mempertimbangkan sejumlah kecil tabel monolitik dibandingkan dengan sejumlah besar tabel kecil yang dinormalisasi. Sebagai poin kedua, saya bingung antara menggunakan tabel hstore vs reguler vs JSONB (dengan indeks GiST).

AFAIK (jangan ragu untuk memperbaiki):

  1. Secara umum, di Postgres, hstore dikenal berkinerja lebih baik daripada tipe data lainnya. Presentasi dari FOSDEM PGDAY ini memiliki beberapa statistik menarik (pada paruh kedua slide). https://wiki.postgresql.org/images/b/b4/Pg-as-nosql-pgday-fosdem-2013.pdf

  2. Keuntungan dengan hstore adalah pengindeksan cepat (GiN atau GiST). Namun, dengan JSONB, pengindeksan GiN dan GiST juga dapat diterapkan pada data JSON.

  3. Blog ini dari seorang profesional di Kuadran ke-2 mengatakan "Pada titik ini mungkin layak mengganti penggunaan hstore dengan jsonb di semua aplikasi baru" (gulir ke akhir): http://blog.2ndquadrant.com/postgresql-anti-patterns- perlu diperlukan -jsonhstore-dynamic-kolom /

Jadi saya ingin memutuskan yang berikut ini:

  1. Untuk bagian utama (terstruktur) dari data: haruskah masuk dalam beberapa tabel relasional (relatif besar dengan banyak kolom), atau haruskah itu sejumlah toko nilai kunci menggunakan hstore?
  2. Untuk data ad hoc (kontribusi pengguna / tidak terstruktur), haruskah dalam JSON atau toko nilai kunci ad hoc di hstore (dengan kunci disimpan di salah satu tabel relasional utama)?
Yogesch
sumber
7
Bergabung tidak mahal. Siapa yang mengatakannya padamu? Karena pada dasarnya seluruh konsep database relasional berputar di sekitar bergabung (dari sudut pandang praktis), produk ini sangat baik untuk bergabung. Cara berpikir normal dimulai dengan struktur yang dinormalisasi dengan benar dan pergi ke denormalisasi mewah dan hal-hal serupa ketika kinerja benar-benar membutuhkannya di sisi membaca. JSON(B)dan hstore(dan EAV) baik untuk data dengan struktur yang tidak dikenal.
dezso
6
@Yogesch tautan-tautan itu mengandung beberapa hal yang menarik dan sangat kontradiktif :) Sebagai moral, sepertinya MySQL buruk pada saat bergabung, dan orang-orang NoSQL cenderung menggeneralisasikan gagasan ini tanpa dasar faktual yang sebenarnya. Di sisi lain, Aaron dan Max peka terhadap kata-p itu - penggunaannya yang luas menunjukkan bagaimana penutur asing (termasuk saya sendiri) menggunakan kata yang salah dengan senang hati.
dezso
4
@Yogesch realistis Saya yakin ada sumber di Internet untuk "membuktikan" apa pun, sama seperti teks agama apa pun dapat digunakan untuk membenarkan kekejaman (seperti yang secara dramatis ditunjukkan di sepanjang sejarah). Memang benar semakin sedikit pekerjaan yang Anda lakukan semakin sedikit biayanya, tetapi selalu ada trade off .
Erik
4
@Yogesch: Menghindari penggabungan penting untuk operasi baca-berat di mana Anda mengetahui pola akses data sebelumnya, dan agar Anda dapat dengan aman memasukkan semua data yang Anda butuhkan ke dalam satu baris. Namun, ini membuat sambungan lain berpotensi lebih mahal. Siapa bilang Anda tidak perlu bergabung dengan data dalam berbagai cara untuk menjawab berbagai pertanyaan? Sekarang kita akan turun ke teori pemodelan data relasional ...
Chris
5
@Yogesch Dalam praktik saya, dengan basis data kemacetan jarang RAM atau CPU tetapi I / O - cara ini menghindari menyimpan data yang berlebihan masih merupakan hal yang penting. Seperti kata Chris, jika Anda selalu melihat data hanya dalam satu cara, ini mungkin sepadan dengan harganya. Jika tidak, Anda berada di sana dengan data yang besar dan sangat tidak fleksibel.
dezso

Jawaban:

41

Database relasional dirancang di sekitar bergabung, dan dioptimalkan untuk melakukannya dengan baik.

Kecuali Anda memiliki alasan yang kuat untuk tidak melakukannya untuk menggunakan desain yang dinormalisasi, gunakan desain yang dinormalisasi.

jsonbdan hal-hal seperti hstoreitu baik untuk ketika Anda tidak dapat menggunakan model data yang dinormalisasi, seperti ketika model data berubah dengan cepat dan ditentukan oleh pengguna.

Jika Anda bisa memodelkannya secara relasional, memodelkannya secara relasional. Jika Anda tidak bisa, pertimbangkan json dll. Jika Anda memilih antara json / jsonb / hstore, umumnya pilih jsonb kecuali Anda memiliki alasan untuk tidak melakukannya.

Itulah yang saya katakan di posting blog saya , yang membahas topik ini saja. Baca seluruh pos . Paragraf yang Anda kutip menunjukkan bahwa jika Anda memilih struktur dinamis, Anda harus memilih jsonb daripada hstore, tetapi sisa posting blog adalah tentang mengapa Anda biasanya lebih suka memodelkan secara relasional jika Anda bisa.

Begitu. Model bagian terstruktur utama secara relasional. Jika tabel benar-benar lebar dengan banyak kolom, ini mungkin merupakan tanda bahwa diperlukan normalisasi lebih lanjut. Jangan takut bergabung. Belajar mencintai bergabung. Bergabung dengan banyak tabel kecil sering kali lebih cepat daripada meminta dan mempertahankan tabel yang didenormalkan besar. Denormalkan hanya jika Anda perlu untuk kasus-kasus tertentu, dan lebih disukai melalui pandangan terwujud ... tetapi jangan lakukan sampai Anda tahu Anda perlu dan memiliki masalah nyata yang nyata untuk dipecahkan.

Untuk data kontribusi pengguna yang berbentuk bebas dan tidak terstruktur, gunakan jsonb. Ini harus bekerja sebaik hstore, tetapi lebih fleksibel dan lebih mudah untuk dikerjakan.

Satu hal yang relevan untuk dipahami: indeks GiST dan GIN seperti yang digunakan pada jsonb umumnya jauh lebih efisien daripada indeks b-tree biasa. Mereka lebih fleksibel, tetapi indeks b-tree pada kolom normal hampir selalu jauh lebih cepat.

Craig Ringer
sumber
Terima kasih banyak Craig, sekarang saya memiliki pemahaman yang lebih baik dan tahu apa yang harus dilakukan. Pertanyaan tindak lanjut: jika saya menyimpan sesuatu seperti suka atau pengikut dalam format dua kolom (post_id dan user_id, untuk suka ), apakah lebih baik menggunakan tabel relasional dengan dua kolom, atau hstore? (Saya tidak keberatan membuat ini menjadi pertanyaan baru)
Yogesch
5
@Yogesch Kedengarannya seperti bog-standard m: n join table dengan format yang konsisten dan stabil. Pertanyaannya harus selalu "apakah ada alasan bagus saya tidak harus melakukan ini dengan cara hubungan biasa untuk kasus khusus ini?".
Craig Ringer
hstoresudah ditinggalkan. Gunakan jsonb.
hazard89
2
@ hazard89 Sebenarnya, itu tidak secara resmi ditinggalkan, meskipun saya tidak berpikir ada alasan untuk menggunakannya demi jsonb lagi. Bagaimanapun ... itu agak tidak penting. Pertanyaannya adalah apakah akan memodelkan secara relasional atau menggunakan tipe data terstruktur.
Craig Ringer