Przechowuję różne dane użytkownika w mojej bazie danych MySQL. Pierwotnie był ustawiony w różnych tabelach, co oznaczało, że dane są połączone z identyfikatorami użytkowników i wyprowadzane za pomocą czasami skomplikowanych wywołań w celu wyświetlenia i manipulowania danymi zgodnie z wymaganiami. Konfigurując nowy system, prawie sensowne jest połączenie wszystkich tych tabel w jeden duży zbiór powiązanych treści.
- Czy to będzie pomoc czy przeszkoda?
- Szybsze rozważania przy dzwonieniu, aktualizowaniu lub wyszukiwaniu / manipulowaniu?
Oto przykład niektórych struktur moich tabel:
- użytkownicy - identyfikator użytkownika, nazwa użytkownika, adres e-mail, zaszyfrowane hasło, data rejestracji, ip
- user_details - dane z plików cookie, imię i nazwisko, adres, dane kontaktowe, przynależność, dane demograficzne
- user_activity - wkład, ostatnio online, ostatnie przeglądanie
- user_settings - ustawienia wyświetlania profilu
- user_interests - zmienne reklamowe, na które można kierować reklamy
- user_levels - prawa dostępu
- user_stats - trafienia, podliczenia
Edycja: Głosowałem za wszystkimi odpowiedziami do tej pory, wszystkie zawierają elementy, które zasadniczo odpowiadają na moje pytanie.
Większość tabel ma relację 1: 1, co było głównym powodem ich denormalizacji.
Czy wystąpią problemy, jeśli tabela obejmuje ponad 100 kolumn, podczas gdy duża część tych komórek prawdopodobnie pozostanie pusta?
źródło
Odpowiedzi:
Wiele tabel pomaga w następujący sposób / przypadkach:
(a) jeśli różne osoby będą tworzyć aplikacje wykorzystujące różne tabele, warto je podzielić.
(b) Jeśli chcesz przyznać różne uprawnienia różnym osobom dla różnych części zbierania danych, wygodniej będzie je podzielić. (Oczywiście można przyjrzeć się definiowaniu widoków i odpowiednim nadawaniu im uprawnień).
(c) W przypadku przenoszenia danych w różne miejsca, szczególnie podczas programowania, może być sensowne użycie tabel, które skutkują mniejszymi rozmiarami plików.
(d) Mniejszy ślad może zapewnić wygodę podczas tworzenia aplikacji na określonym zbiorze danych pojedynczej jednostki.
(e) Jest taka możliwość: to, co myśleliście, jako dane o pojedynczej wartości, może w przyszłości okazać się naprawdę wieloma wartościami. np. limit kredytu jest od teraz pojedynczym polem wartości. Ale jutro możesz zdecydować o zmianie wartości na (data od, data do, wartość kredytu). Dzielone tabele mogą się teraz przydać.
Mój głos byłby na wiele tabel - z odpowiednio podzielonymi danymi.
Powodzenia.
źródło
Łączenie tabel nazywa się denormalizowaniem.
Może (ale nie musi) pomóc wykonanie niektórych zapytań (które robią dużo
JOIN
), aby działały szybciej kosztem tworzenia piekła konserwacyjnego.MySQL
jest w stanie używać tylkoJOIN
metody, a mianowicieNESTED LOOPS
.Oznacza to, że dla każdego rekordu w tabeli sterującej
MySQL
lokalizuje pasujący rekord w tabeli sterowanej w pętli.Lokalizowanie płyty jest dość kosztowną operacją, która może zająć dziesiątki razy dłużej niż zwykłe skanowanie płyt.
Przeniesienie wszystkich rekordów do jednej tabeli pomoże ci pozbyć się tej operacji, ale sama tabela się powiększy, a skanowanie tabeli potrwa dłużej.
Jeśli masz dużo rekordów w innych tabelach, zwiększenie skanowania tabeli może przeważyć korzyści wynikające z sekwencyjnego skanowania rekordów.
Z drugiej strony piekło konserwacji jest gwarantowane.
źródło
Czy wszystkie są związkami 1: 1? Chodzi mi o to, że jeśli użytkownik mógłby należeć, powiedzmy, do różnych poziomów użytkownika, lub jeśli interesy użytkowników są reprezentowane jako kilka rekordów w tabeli zainteresowań użytkownika, to natychmiastowe scalenie tych tabel byłoby wykluczone.
Odnosząc się do poprzednich odpowiedzi na temat normalizacji, należy powiedzieć, że reguły normalizacji bazy danych całkowicie zignorowały wydajność i dotyczą tylko schludnego projektu bazy danych. To często jest to, co chcesz osiągnąć, ale są chwile, kiedy warto aktywnie denormalizować się w pogoni za wydajnością.
Podsumowując, powiedziałbym, że pytanie sprowadza się do tego, ile pól znajduje się w tabelach i jak często są one dostępne. Jeśli aktywność użytkownika często nie jest zbyt interesująca, może być po prostu uciążliwe, aby zawsze mieć ją w tym samym rejestrze, ze względu na wydajność i konserwację. Jeśli niektóre dane, na przykład ustawienia, są używane bardzo często, ale po prostu zawierają zbyt wiele pól, scalanie tabel może nie być wygodne. Jeśli interesuje Cię tylko wzrost wydajności, możesz rozważyć inne podejścia, takie jak oddzielne przechowywanie ustawień, ale zapisywanie ich we własnej zmiennej sesji, aby nie trzeba było często wysyłać zapytań do bazy danych.
źródło
3NF
normalizacji, więc skorzystaj z drugiej tabeli, aby rozwiązać ten problem, ale wydaje się, że nie jest to tym, co OP odnosi się do innych tabel.)Czy wszystkie te tabele są
1-to-1
powiązane? Na przykład, czy każdy wiersz użytkownika będzie miał tylko jeden odpowiadający wiersz wuser_stats
lubuser_levels
? Jeśli tak, warto połączyć je w jedną tabelę. Jeśli jednak związek nie jest1 to 1
, prawdopodobnie nie miałoby sensu ich łączenie (denormalizacja).Jednak umieszczenie ich w osobnych tabelach w porównaniu z jedną tabelą prawdopodobnie będzie miało niewielki wpływ na wydajność, chyba że masz setki tysięcy lub miliony rekordów użytkowników. Jedyną prawdziwą korzyścią, jaką uzyskasz, jest uproszczenie zapytań poprzez ich połączenie.
ETA:
Jeśli obawiasz się zbyt wielu kolumn , zastanów się, jakich rzeczy zwykle używasz razem i połącz je , pozostawiając resztę w osobnej tabeli (lub w kilku oddzielnych tabelach, jeśli to konieczne).
Jeśli spojrzysz na sposób, w jaki korzystasz z danych, domyślam się, że około 80% zapytań wykorzystuje 20% tych danych, a pozostałe 80% danych jest wykorzystywanych sporadycznie. Połącz te często używane 20% w jedną tabelę i pozostaw 80%, których rzadko używasz w osobnych tabelach, a prawdopodobnie uzyskasz dobry kompromis.
źródło
Tworzenie jednej ogromnej tabeli jest sprzeczne z podmiotami zarządzającymi relacyjnej bazy danych. Nie połączyłbym ich wszystkich w jeden stół. Otrzymasz wiele wystąpień powtarzających się danych. Jeśli na przykład twój użytkownik ma trzy zainteresowania, będziesz mieć 3 wiersze z tymi samymi danymi użytkownika tylko po to, aby zapisać trzy różne zainteresowania. Zdecydowanie wybierz metodę wielokrotnej „znormalizowanej” tabeli. Zobacz tę stronę Wiki w celu normalizacji bazy danych.
Edycja: zaktualizowałem moją odpowiedź, ponieważ zaktualizowałeś swoje pytanie ... Zgadzam się z moją początkową odpowiedzią jeszcze bardziej, odkąd ...
Jeśli na przykład użytkownik nie miał żadnych zainteresowań, jeśli znormalizujesz, po prostu nie będziesz mieć wiersza w tabeli odsetek dla tego użytkownika. Jeśli masz wszystko w jednej ogromnej tabeli, będziesz mieć kolumny (i najwyraźniej wiele z nich), które zawierają tylko wartości NULL.
Pracowałem dla firmy telekomunikacyjnej, w której było mnóstwo tabel, a uzyskanie danych może wymagać wielu połączeń. Gdy wydajność odczytu z tych tabel była krytyczna, wtedy powstawały procedury, które mogły generować tabelę płaską (tj. Tabelę zdenormalizowaną), która nie wymagałaby łączenia, obliczeń itp., Na które mogłyby wskazywać raporty. Te były następnie używane w połączeniu z agentem serwera SQL do uruchamiania zadania w określonych odstępach czasu (tj. Tygodniowy widok niektórych statystyk był uruchamiany raz w tygodniu itd.).
źródło
Dlaczego nie zastosować tego samego podejścia, co Wordpress, mając tabelę użytkowników z podstawowymi informacjami o użytkowniku, które każdy ma, a następnie dodać tabelę „user_meta”, która może być w zasadzie dowolną parą klucza i wartości powiązaną z identyfikatorem użytkownika. Więc jeśli chcesz znaleźć wszystkie metadane użytkownika, możesz po prostu dodać je do swojego zapytania. Nie zawsze będziesz musiał dodawać dodatkowe zapytanie, jeśli nie jest to potrzebne do takich rzeczy, jak logowanie. Korzyści płynące z tego podejścia pozostawiają również możliwość dodawania nowych funkcji dla użytkowników, takich jak przechowywanie ich uchwytów na Twitterze lub poszczególnych zainteresowań. Nie będziesz też musiał zajmować się labiryntem powiązanych identyfikatorów, ponieważ masz jedną tabelę, która rządzi wszystkimi metadanymi i ograniczysz ją do tylko jednego powiązania zamiast 50.
Wordpress robi to specjalnie po to, aby umożliwić dodawanie funkcji za pośrednictwem wtyczek, dzięki czemu projekt jest bardziej skalowalny i nie będzie wymagał całkowitego przeglądu bazy danych, jeśli musisz dodać nową funkcję.
źródło
wp_usermeta
Stół Wordpress rośnie geometrycznie. Każdy użytkownik dodaje X wierszy dowp_usermeta
tabeli, po jednym wierszu na każdą metainformację, którą chcemy zachować dla tego użytkownika. Jeśli zachowasz 8 niestandardowych pól dla każdego użytkownika, oznacza to, że wp_usermeta będzie miałousers * 8
długość wierszy. Wydaje się, że powoduje to problemy z wydajnością, ale nie jestem pewien, czy to jest problem, czy nie…get_users()
) tylko do obliczenia paginacji. Gdy poprawiliśmy kod, abySELECT COUNT(…)
zamiast tego używał zapytania do paginacji, czas ładowania strony wzrósł z 28 sekund do około 400 ms. Nadal zastanawiam się, jak wypada porównanie wydajności z połączonymi tabelami lub pojedynczym płaskim stołem… Mam problem ze znalezieniem jakichkolwiek metryk wydajności w Internecie.Myślę, że to jedna z tych sytuacji „to zależy”. Posiadanie wielu tabel jest czystsze i prawdopodobnie teoretycznie lepsze. Ale kiedy musisz dołączyć do 6-7 tabel, aby uzyskać informacje o pojedynczym użytkowniku, możesz zacząć przemyśleć to podejście.
źródło
Powiedziałbym, że zależy to od tego, co naprawdę oznaczają inne tabele. Czy user_details zawiera więcej niż 1 użytkownika więcej / users i tak dalej. To, jaki poziom normalizacji najlepiej odpowiada Twoim potrzebom, zależy od Twoich wymagań.
Jeśli masz jedną tabelę z dobrym indeksem, prawdopodobnie będzie to szybsze. Ale z drugiej strony prawdopodobnie trudniejsze w utrzymaniu.
Dla mnie wygląda na to, że możesz pominąć User_Details, ponieważ prawdopodobnie jest to relacja 1 do 1 z użytkownikami. Ale reszta to prawdopodobnie dużo wierszy na użytkownika?
źródło