Wdrażam następujący model do przechowywania danych związanych z użytkownikiem w mojej tabeli - mam 2 kolumny - uid
(klucz podstawowy) i meta
kolumnę, która przechowuje inne dane o użytkowniku w formacie JSON.
uid | meta
--------------------------------------------------
1 | {name:['foo'],
| emailid:['[email protected]','[email protected]']}
--------------------------------------------------
2 | {name:['sann'],
| emailid:['[email protected]','[email protected]']}
--------------------------------------------------
Jest to lepszy sposób (wydajność mądry, design-wise) niż model jedna kolumna-per-mienia, gdzie tabela ma wiele kolumn, takich jak uid
, name
, emailid
.
W pierwszym modelu podoba mi się to, że możesz dodać tyle pól, ile to możliwe, nie ma ograniczeń.
Zastanawiałem się też, kiedy wdrożyłem pierwszy model. Jak wykonać na nim zapytanie, na przykład chcę pobrać wszystkich użytkowników o nazwach takich jak „foo”?
Pytanie - Jaki jest lepszy sposób przechowywania danych związanych z użytkownikiem (pamiętając, że liczba pól nie jest ustalona) w bazie danych przy użyciu JSON lub kolumna na pole? Ponadto, jeśli wdrożony jest pierwszy model, jak wykonać zapytanie do bazy danych, jak opisano powyżej? Czy powinienem używać obu modeli, przechowując wszystkie dane, które mogą być wyszukiwane przez zapytanie w oddzielnym wierszu, a inne dane w JSON (to inny wiersz)?
Aktualizacja
Ponieważ nie będzie zbyt wielu kolumn, w których muszę przeprowadzić wyszukiwanie, czy mądrze jest używać obu modeli? Klucz po kolumnie dla danych, które muszę wyszukać, i JSON dla innych (w tej samej bazie danych MySQL)?
źródło
Odpowiedzi:
Zaktualizowano 4 czerwca 2017 r
Biorąc pod uwagę, że to pytanie / odpowiedź zyskała popularność, uznałem, że warto było zaktualizować.
Kiedy to pytanie zostało pierwotnie opublikowane, MySQL nie obsługiwał typów danych JSON, a obsługa PostgreSQL była w powijakach. Od wersji 5.7 MySQL obsługuje teraz typ danych JSON (w binarnym formacie pamięci), a PostgreSQL JSONB znacznie dojrzał. Oba produkty zapewniają wydajne typy JSON, które mogą przechowywać dowolne dokumenty, w tym obsługę indeksowania określonych kluczy obiektu JSON.
Nadal jednak podtrzymuję moje oryginalne stwierdzenie, że domyślną preferencją podczas korzystania z relacyjnej bazy danych powinna być nadal kolumna według wartości. Relacyjne bazy danych są nadal budowane przy założeniu, że dane w nich zawarte będą dość dobrze znormalizowane. Planer zapytań ma lepsze informacje optymalizacyjne podczas przeglądania kolumn niż podczas przeglądania kluczy w dokumencie JSON. Klucze obce można tworzyć między kolumnami (ale nie między kluczami w dokumentach JSON). Co ważne: jeśli większość schematu jest wystarczająco niestabilna, aby uzasadnić użycie JSON, możesz przynajmniej rozważyć, czy relacyjna baza danych jest właściwym wyborem.
To powiedziawszy, niewiele aplikacji jest doskonale relacyjnych lub zorientowanych na dokumenty. Większość aplikacji ma kombinację obu. Oto kilka przykładów, w których osobiście uważam JSON za użyteczny w relacyjnej bazie danych:
Podczas przechowywania adresów e-mail i numerów telefonów dla kontaktu, gdzie przechowywanie ich jako wartości w tablicy JSON jest znacznie łatwiejsze do zarządzania niż wiele osobnych tabel
Zapisywanie preferencji użytkownika klucza / wartości (gdzie wartość może być logiczna, tekstowa lub numeryczna, a nie chcesz mieć oddzielnych kolumn dla różnych typów danych)
Przechowywanie danych konfiguracyjnych, które nie mają zdefiniowanego schematu (jeśli budujesz Zapier lub IFTTT i potrzebujesz przechowywać dane konfiguracyjne dla każdej integracji)
Jestem pewien, że są też inne, ale to tylko kilka szybkich przykładów.
Oryginalna odpowiedź
Jeśli naprawdę chcesz być w stanie dodać tyle pól, ile chcesz bez żadnych ograniczeń (innych niż arbitralny limit rozmiaru dokumentu), rozważ rozwiązanie NoSQL, takie jak MongoDB.
W przypadku relacyjnych baz danych: użyj jednej kolumny na wartość. Umieszczenie obiektu blob JSON w kolumnie sprawia, że zapytanie jest praktycznie niemożliwe (i boleśnie spowalnia, gdy faktycznie znajdziesz zapytanie, które działa).
Relacyjne bazy danych wykorzystują typy danych podczas indeksowania i są przeznaczone do implementacji ze znormalizowaną strukturą.
Na marginesie: nie oznacza to, że nigdy nie powinieneś przechowywać JSON w relacyjnej bazie danych. Jeśli dodajesz prawdziwe metadane lub jeśli Twój JSON opisuje informacje, które nie wymagają odpytywania i są używane tylko do wyświetlania, może być przesada, aby utworzyć osobną kolumnę dla wszystkich punktów danych.
źródło
virtually impossible to query
” - dzisiaj psql pozwala na wyszukiwanie i indeksowanie jej jsonb"For relational databases"
w swojej odpowiedzi = PJak większość rzeczy „to zależy”. Przechowywanie danych w kolumnach lub JSON nie jest dobre ani złe / dobre ani złe samo w sobie. To zależy od tego, co musisz z tym zrobić później. Jaki jest twój przewidywany sposób dostępu do tych danych? Czy będziesz musiał odwoływać się do innych danych?
Inne osoby dość dobrze odpowiedziały na kompromis techniczny.
Niewiele osób mówiło o tym, że Twoja aplikacja i funkcje ewoluują w czasie i jak ta decyzja o przechowywaniu danych wpływa na Twój zespół.
Ponieważ jedną z pokus używania JSON jest unikanie migracji schematu, więc jeśli zespół nie jest zdyscyplinowany, bardzo łatwo jest włożyć jeszcze jedną parę klucz / wartość w pole JSON. Nie ma dla niego migracji, nikt nie pamięta, po co. Nie ma na to żadnego potwierdzenia.
Mój zespół zastosował JSON obok tradycyjnych kolumn w postgresie i na początku była to najlepsza rzecz od czasu krojonego chleba. JSON był atrakcyjny i potężny, aż pewnego dnia zdaliśmy sobie sprawę, że elastyczność jest kosztowna i nagle staje się to prawdziwym problemem. Czasami ten punkt bardzo szybko się rozwija, a potem trudno go zmienić, ponieważ na podstawie tej decyzji projektowej zbudowaliśmy wiele innych rzeczy.
Nadgodziny, dodawanie nowych funkcji, posiadanie danych w JSON prowadziło do bardziej skomplikowanych zapytań niż to, co mogłoby zostać dodane, gdybyśmy trzymali się tradycyjnych kolumn. Więc zaczęliśmy łowić niektóre kluczowe wartości z powrotem do kolumn, abyśmy mogli tworzyć sprzężenia i porównywać wartości. Kiepski pomysł. Teraz mieliśmy duplikację. Nowy programista wszedłby na pokład i byłby zdezorientowany? Jaką wartość powinienem oszczędzać? JSON jeden czy kolumna?
Pola JSON stały się szufladami śmieciowymi dla małych kawałków tego i tamtego. Brak sprawdzania poprawności danych na poziomie bazy danych, brak spójności lub integralności dokumentów. To zepchnęło całą tę odpowiedzialność do aplikacji zamiast sprawdzania trudnych typów i ograniczeń z tradycyjnych kolumn.
Patrząc wstecz, JSON pozwolił nam bardzo szybko iterować i wyciągnąć coś za drzwi. To było wspaniałe. Jednak po osiągnięciu pewnego rozmiaru zespołu jego elastyczność pozwoliła nam również powiesić się na długiej linie długu technicznego, co następnie spowolniło postęp ewolucji funkcji. Używaj ostrożnie.
Zastanów się długo, jaki jest charakter Twoich danych. To podstawa Twojej aplikacji. Jak dane będą wykorzystywane w miarę upływu czasu. A jak to się może ZMIENIĆ?
źródło
Po prostu go tam wyrzucam, ale WordPress ma strukturę dla tego rodzaju rzeczy (przynajmniej WordPress był pierwszym miejscem, w którym go zauważyłem, prawdopodobnie pochodzi to gdzie indziej).
Pozwala na nieograniczoną liczbę kluczy i jest szybszy do wyszukiwania niż przy użyciu obiektu blob JSON, ale nie tak szybki jak niektóre rozwiązania NoSQL.
EDYTOWAĆ
Do przechowywania historii / wielu kluczy
i zapytaj za pomocą czegoś takiego:
źródło
emailid
klucz w przykładzie podanym w moim pytaniu.wadą tego podejścia jest dokładnie to, o czym wspomniałeś:
sprawia, że wyszukiwanie rzeczy jest BARDZO powolne, ponieważ za każdym razem musisz przeprowadzić na nim wyszukiwanie tekstu.
zamiast tego wartość na kolumnę pasuje do całego łańcucha.
Twoje podejście (dane oparte na JSON) jest w porządku w przypadku danych, których nie musisz wyszukiwać, i po prostu musisz je wyświetlić wraz z normalnymi danymi.
Edycja: Dla wyjaśnienia powyższe dotyczy klasycznych relacyjnych baz danych. NoSQL używa JSON wewnętrznie i jest prawdopodobnie lepszą opcją, jeśli jest to pożądane zachowanie.
źródło
Zasadniczo pierwszy używany model nazywany jest magazynem opartym na dokumentach. Powinieneś rzucić okiem na popularną bazę danych opartą na dokumentach NoSQL, taką jak MongoDB i CouchDB . Zasadniczo w bazach danych opartych na dokumentach przechowujesz dane w plikach json, a następnie możesz wyszukiwać te pliki json.
Drugi model to popularna struktura relacyjnych baz danych.
Jeśli chcesz korzystać z relacyjnej bazy danych, takiej jak MySql, sugeruję użycie tylko drugiego modelu. Nie ma sensu używanie MySql i przechowywanie danych jak w pierwszym modelu .
Aby odpowiedzieć na drugie pytanie, nie ma możliwości zapytania nazwy takiej jak „foo”, jeśli używasz pierwszego modelu .
źródło
Wygląda na to, że głównie się wahasz, czy użyć modelu relacyjnego, czy nie.
Na obecnym etapie twój przykład byłby dość dobrze dopasowany do modelu relacyjnego, ale problem może oczywiście pojawić się, gdy trzeba go rozwinąć.
Jeśli masz tylko jeden (lub kilka wcześniej określonych) poziomów atrybutów dla głównej jednostki (użytkownika), nadal możesz użyć modelu wartości atrybutu jednostki (EAV) w relacyjnej bazie danych. (Ma to również swoje zalety i wady.)
Jeśli spodziewasz się, że otrzymasz mniej uporządkowanych wartości, które będziesz chciał przeszukiwać za pomocą aplikacji, MySQL może nie być najlepszym wyborem tutaj.
Jeśli korzystasz z PostgreSQL, potencjalnie możesz uzyskać to, co najlepsze z obu światów. (To naprawdę zależy od faktycznej struktury danych tutaj ... MySQL niekoniecznie jest złym wyborem, a opcje NoSQL mogą być interesujące, po prostu sugeruję alternatywy).
Rzeczywiście, PostgreSQL może budować indeks na (niezmiennych) funkcjach (których MySQL nie potrafi, o ile wiem), aw najnowszych wersjach można było używać PLV8 na danych JSON bezpośrednio do budowania indeksów na określonych elementach JSON, które mogłyby się poprawić szybkość twoich zapytań podczas wyszukiwania tych danych.
EDYTOWAĆ:
Mieszanie dwóch modeli niekoniecznie jest złe (zakładając, że dodatkowa przestrzeń jest nieistotna), ale może powodować problemy, jeśli nie upewnisz się, że oba zestawy danych są zsynchronizowane: aplikacja nigdy nie może zmienić jednego bez aktualizacji drugiego .
Dobrym sposobem na osiągnięcie tego byłoby uruchomienie automatycznej aktualizacji przez wyzwalacz, uruchamiając procedurę przechowywaną na serwerze bazy danych za każdym razem, gdy wykonywana jest aktualizacja lub wstawianie. O ile mi wiadomo, język procedur przechowywanych MySQL prawdopodobnie nie obsługuje żadnego przetwarzania JSON. Ponownie PostgreSQL ze wsparciem PLV8 (i ewentualnie inne RDBMS z bardziej elastycznymi językami procedur składowanych) powinny być bardziej przydatne (automatyczne aktualizowanie kolumny relacyjnej za pomocą wyzwalacza jest dość podobne do aktualizowania indeksu w ten sam sposób).
źródło
przyłączenie się do stołu na jakiś czas będzie narzutem. powiedzmy dla OLAP. jeśli mam dwie tabele, jedna to tabela ZAMÓWIENIA, a druga to ZAMÓWIENIA. Aby uzyskać wszystkie szczegóły zamówienia, musimy połączyć dwie tabele. Spowoduje to spowolnienie zapytania, gdy liczba wierszy w tabelach wzrośnie, powiedzmy w milionach lub mniej więcej. Myślę, że jeśli dodamy ciąg JSON / Obiekt do odpowiedniego wpisu ZAMÓWIENIA, unikniemy JOIN. dodaj generowanie raportu będzie szybsze ...
źródło
krótka odpowiedź, którą musisz wymieszać, użyć json dla danych, których nie zamierzasz nawiązać z nimi relacji, takich jak dane kontaktowe, adres, różne produkty
źródło
Próbujesz dopasować nierelacyjny model do relacyjnej bazy danych, myślę, że lepiej byś był obsługiwany przy użyciu bazy danych NoSQL, takiej jak MongoDB . Nie ma predefiniowanego schematu, który pasowałby do twojego wymagania, aby nie mieć ograniczenia liczby pól (patrz typowy przykład kolekcji MongoDB). Sprawdź dokumentację MongoDB, aby dowiedzieć się, w jaki sposób sprawdzasz swoje dokumenty, np
źródło
Jak zauważyli inni, zapytania będą wolniejsze. Zamiast tego sugerowałbym dodanie do zapytania co najmniej kolumny „_ID”.
źródło