JSONB z indeksowaniem vs. hstore

28

Na tym etapie próbuję zdecydować o projekcie bazy danych, przy możliwie jak najmniejszej liczbie założeń (dotyczących tego, jak faktycznie rozwija się aplikacja internetowa).

Pierwszym krokiem jest zrozumienie, że DOŁĄCZENIA są drogie, rozważam niewielką liczbę monolitycznych tabel w przeciwieństwie do dużej liczby znormalizowanych mniejszych tabel. Po drugie, jestem zdezorientowany między używaniem hstore a zwykłymi tabelami vs. JSONB (z indeksowaniem GiST).

AFAIK (prosimy o poprawienie):

  1. Ogólnie w Postgres wiadomo, że hstore działa lepiej niż inne typy danych. Ta prezentacja FOSDEM PGDAY ma kilka interesujących statystyk (w drugiej połowie slajdów). https://wiki.postgresql.org/images/b/b4/Pg-as-nosql-pgday-fosdem-2013.pdf

  2. Zaletą hstore jest szybkie indeksowanie (GiN lub GiST). Jednak w przypadku JSONB, indeksowanie GiN i GiST może być również stosowane do danych JSON.

  3. Ten blog profesjonalisty z 2nd Quadrant mówi: „W tym momencie prawdopodobnie warto zastąpić używanie hstore jsonb we wszystkich nowych aplikacjach” (przewiń do końca): http://blog.2ndquadrant.com/postgresql-anti-patterns-unnecessary -jsonhstore-dynamic-columns /

Chciałbym więc zdecydować o następujących kwestiach:

  1. W przypadku głównej (ustrukturyzowanej) części danych: czy powinna ona znajdować się w kilku relacyjnych tabelach (względnie duża z wieloma kolumnami), czy powinna to być pewna liczba sklepów z kluczową wartością przy użyciu hstore?
  2. W przypadku danych ad hoc (przekazanych przez użytkownika / nieustrukturyzowanych) powinny one znajdować się w JSON lub w magazynach wartości kluczy ad hoc w hstore (z kluczami przechowywanymi w jednej z głównych tabel relacyjnych)?
Yogesch
źródło
7
Połączenia nie są drogie. Kto ci to powiedział? Ponieważ w zasadzie cała koncepcja relacyjnych baz danych koncentruje się na złączeniach (z praktycznego punktu widzenia), produkty te są bardzo dobre w łączeniu. Normalny sposób myślenia zaczyna się od właściwie znormalizowanych struktur i przechodzi w fantazyjne denormalizacje i podobne rzeczy, kiedy przedstawienie naprawdę tego potrzebuje po stronie czytelniczej. JSON(B)i hstore(i EAV) są dobre dla danych o nieznanej strukturze.
dezso
6
@Yogesch te linki zawierają ciekawe i szalenie sprzeczne rzeczy :) Moralnie wygląda na to, że MySQL jest (było) złe w złączeniach, a ludzie NoSQL mają tendencję do generalizowania tego pojęcia bez jakiejkolwiek faktycznej podstawy. Z drugiej strony, Aaron i Max są wrażliwi na to słowo p - jego szerokie użycie pokazuje, w jaki sposób obcy użytkownicy (w tym ja) używają na szczęście niewłaściwego słowa.
dezso
4
@Yogesch realistycznie jestem pewien, że w Internecie istnieje źródło, które „dowodzi” czegokolwiek, podobnie jak każdy tekst religijny może być użyty do usprawiedliwienia okrucieństwa (co dramatycznie pokazano w całej historii). To prawda, że ​​im mniej pracy wykonasz, tym mniej to kosztuje, ale zawsze jest trochę kompromisu .
Erik
4
@Yogesch: Unikanie złączeń jest ważne w operacjach wymagających dużego odczytu, w których z góry znasz wzorzec dostępu do danych, dzięki czemu możesz bezpiecznie umieścić wszystkie potrzebne dane w jednym rzędzie. Jednak powoduje to, że inne połączenia są potencjalnie bardziej kosztowne. Kto powiedział, że nie musisz łączyć danych na wiele różnych sposobów, aby odpowiedzieć na różne pytania? Teraz zajmiemy się teorią relacyjnego modelowania danych ...
Chris,
5
@Yogesch W mojej praktyce, w bazach danych wąskim gardłem jest rzadko pamięć RAM lub procesor, ale jest to I / O - w ten sposób unikanie przechowywania zbędnych danych jest nadal ważną sprawą. Jak mówi Chris, jeśli zawsze widzisz swoje dane tylko w jeden sposób, może to być warte swojej ceny. Jeśli nie, jesteś tam z nieporęczną i bardzo nieelastyczną częścią danych.
dezso

Odpowiedzi:

41

Relacyjne bazy danych są zaprojektowane wokół sprzężeń i zoptymalizowane pod kątem ich dobrego wykonania.

Jeśli nie masz uzasadnionego powodu, aby nie używać znormalizowanego projektu, użyj znormalizowanego projektu.

jsonbi takie rzeczy hstoresą dobre, gdy nie można użyć znormalizowanego modelu danych, na przykład gdy model danych zmienia się szybko i jest zdefiniowany przez użytkownika.

Jeśli możesz to modelować relacyjnie, modeluj go relatywnie. Jeśli nie możesz, rozważ json itp. Jeśli wybierasz między json / jsonb / hstore, zazwyczaj wybieraj jsonb, chyba że masz powód, aby tego nie robić.

Tak powiedziałem w moim blogu , który dotyczy tylko tego tematu. Przeczytaj cały post . Cytowany akapit wskazuje, że jeśli wybierasz strukturę dynamiczną , powinieneś wybrać jsonb zamiast hstore, ale reszta posta na blogu mówi o tym, dlaczego zazwyczaj powinieneś modelować relatywnie, jeśli możesz.

Więc. Modeluj główną część strukturalną relacyjnie. Jeśli tabele są naprawdę szerokie z dużą ilością kolumn, może to oznaczać, że wymagana jest dalsza normalizacja. Nie bój się dołączeń. Naucz się kochać dołączenia. Dołączanie do wielu małych tabel często będzie szybsze niż wyszukiwanie i utrzymywanie dużych zdenormalizowanych tabel. Denormalizuj tylko wtedy, gdy jest to konieczne w określonych przypadkach, najlepiej za pośrednictwem zmaterializowanych widoków ... ale nie rób tego, dopóki nie dowiesz się, że potrzebujesz konkretnego problemu do rozwiązania.

W przypadku danych udostępnianych przez użytkownika, które są dowolne i nieustrukturyzowane, użyj jsonb. Powinien działać równie dobrze jak hstore, ale jest bardziej elastyczny i łatwiejszy w obsłudze.

Jedną istotną rzecz do zrozumienia: indeksy GiST i GIN, takie jak te stosowane w jsonb, są ogólnie znacznie mniej wydajne niż zwykły indeks b-drzewa. Są bardziej elastyczne, ale indeks b-drzewa w normalnej kolumnie prawie zawsze będzie znacznie, znacznie szybszy.

Craig Ringer
źródło
Wielkie dzięki Craig, teraz mam znacznie lepsze zrozumienie i wiem, co robić. Kolejne pytanie: jeśli przechowuję coś takiego jak polubienia lub obserwujący w formacie dwóch kolumn (post_id i user_id, dla polubień ), czy lepiej jest użyć tabeli relacyjnej z dwiema kolumnami lub hstore? (Nie mam nic przeciwko przekształceniu tego w nowe pytanie)
Yogesch,
5
@Yogesch Brzmi jak standardowa tabela łączenia m: n ze spójnym i stabilnym formatem. Pytanie powinno zawsze brzmieć: „czy jest dobry powód, dla którego nie powinienem robić tego w zwykły sposób relacyjny dla tego konkretnego przypadku?”.
Craig Ringer
hstorejest przestarzałe. Zastosowanie jsonb.
niebezpieczne89
2
@ niebezpieczeństwo89 W rzeczywistości nie jest to formalnie przestarzałe, choć nie sądzę, aby istniał jakiś powód, aby używać go na korzyść jsonb. W każdym razie ... to trochę mija się z celem. Pytanie dotyczy tego, czy modelować relacyjnie, czy użyć ustrukturyzowanego typu danych.
Craig Ringer