2011-02-07 4 views
5

Dodaję nową funkcję do mojego modułu użytkownika dla mojego CMS i trafiłem na blokadę drogi ... Albo, jak sądzę, widelec na drodze, i chciałem uzyskać opinie od stackoverflow zanim zobowiązuję się do byle co.
Zasadniczo chcę umożliwić administratorom dodawanie nowych "dodatkowych" pól użytkownika, które użytkownicy mogą wypełniać przy rejestracji, edytować w swoim profilu i/lub być kontrolowani przez inne moduły. Przykładem może być pole urodzinowe, długi opis samego siebie lub może punkty, które użytkownik zarobił na stronie. Nie trzeba dodawać, że przechowywane dane będą się różnić i będą się wahać od dużych ilości tekstu do małej wartości całkowitej. Co gorsza - chcę mieć możliwość przeszukiwania tych danych.Najlepszy sposób na przechowywanie "dodatkowych" danych użytkownika w MySQL?

Z tym, co na uboczu - jaki byłby najlepszy sposób na zrobienie tego? Teraz pochylam się do stołu z następującymi kolumnami.

userid, refFieldID, varchar, tinyint, smallint, int, text, date, datetime, etc. 

wolałbym to jak miałoby to poszukiwanie znacznie szybciej, a tabela referencyjna (który przechowuje wszystkie dane dziedzinie, takich jak imię tej dziedzinie, czy to do przeszukiwania lub nie, itd.) Może wskazać, która kolumna powinna być używana podczas przechowywania danych dla tego pola.

Inna idea, która została mi zasugerowana i widziałem używane w innych rozwiązaniach (vBulletin jest jednym, chociaż widziałem innych, których nazwy uciekają od mnie w tej chwili), gdzie po prostu masz identyfikator użytkownika, identyfikator referencyjny i pole medtekstu. Nie wiem wystarczająco dużo o MySQL, aby powiedzieć to z całą pewnością, ale ta metoda wydaje się wolniejsza w wyszukiwaniu i może mieć większy narzut.

Która metoda byłaby "najlepsza"? Czy istnieje inna metoda, której mi brakuje? Bez względu na to, którą metodę wykorzystam, musi być ona szybka w wyszukiwaniu, a nie masywna (niewielki nadmiar jest w porządku), a najlepiej zezwalać na stosowanie złożonych zapytań dotyczących danych.

Odpowiedz

3

Zgadzam się, że tabela klucz-wartość jest prawdopodobnie najlepszym rozwiązaniem. Moja pierwsza skłonność to po prostu przechowywanie kolumny tekstowej, takiej jak vBulletin. Ale, jeśli chcesz dodać zdolność do przechowywania danych, aby być nieco bardziej rozciągliwe i przeszukiwać jakbyś rozplanowany, mógłbym zasugerować:

  • 1 średni/longtext lub średnie/pole longblob dla dowolnego tekstu/binary storage (wszystko, co jest przechowywane + narzut 3-4 bajty na długość ciągu znaków). Jedynym powodem, aby wybrać medium na długo, jest ograniczenie tego, co można zapisać na 2^24 bajty (16,7 MB) w porównaniu z 2^32 bajtami (2 GB).
  • 1 całkowita (4 bajty) lub bigint (8 bajtów)
  • 1 DateTime (8 bajtów)
  • Może jeden pływak lub dwu (4-8 bajtów) do unoszenia SKŁADOWANIA punkt

Te pola pozwoli ci na przechowywanie prawie każdego rodzaju danych w tabeli, ale bez nadmuchiwania szerokości tabeli ** (tak jak robiłby to varchar) i unikania zbędnych pamięci (jak na przykład tinyint i mediumint itp.). Tekst zapisany w długim polu tekstowym może być w dalszym ciągu właściwie wyszukiwany przy użyciu pełnotekstowego indeksu lub zwykłego indeksu o ograniczonej długości (na przykład index longtext_storage(8)).

** wszystkie wartości typu blob, takie jak longtext, są przechowywane niezależnie od tabeli głównej.

+0

Wow, dzięki, miałem zamiar odpowiedzieć na pierwszą osobę, która zgadza się z # 1, które kolumny wybrać - ale chyba już nie muszę :). Odnośnie twojego posta - masz na myśli tekst AND BLOB, int AND bigint? Lub jednego lub drugiego? Co myślisz o dodaniu kolumny "bool" (tinyint (1))? Widziałam, że jest bardzo przydatny i prawdopodobnie bardzo często używany - czy warto by było zapisać 3 bajty, według ciebie? Czy liczba kolumn zwiększa rozmiar rzędu na dysku? Oczywiście puste kolumny. Nie wątpię w twój (niesamowity) układ tabeli, tylko ciekawy. – Jon

+0

1 dla każdej pozycji na mojej liście, więc 3 lub 4 kolumny łącznie, w zależności od tego, czy chcesz wspierać wsparcie. Jeśli chodzi o tinyint (1) - zapisz te w kolumnie całkowitej. Marnujesz bajt, dodając tinyint (1), nie zapisując 3. Każdy wiersz w tabeli ma zawsze taką samą szerokość w MySQL - działa tak samo w większości innych RDBMS. (W jaki sposób varchary wpływają na to, staje się nieco skomplikowane.) "Szerokość" jest również nazywana "rozmiarem wiersza". – wuputah

0

Jedną z technik, która może Ci się przydać, jest przechowywanie tych arbitralnych danych jako tekstu, w niektórych zapisach takich jak JSON, XML lub YAML. Ta decyzja zależy od tego, w jaki sposób będziesz potrzebować dostępu do danych: jeśli będziesz szukał tylko pełnego zbioru danych użytkownika, może to być idealne. Jeśli chcesz uruchomić kwerendy SQL w określonych polach w danych użytkownika, musisz użyć podejścia czystego SQL lub hybrydowego.

Wiele nowszych, wysoce skalowalnych systemów "NoSQL" wydaje się faworyzować dane JSON (np. MongoDB, CouchDB i Project Voldemort). Jest to ładne i zwięzłe i można tworzyć dowolnie złożone struktury, w tym mapy (obiekty JSON) i listy (tablice JSON).