Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Wydajność - Jedna ogólna baza vs kilka baz
Forum PHP.pl > Forum > PHP
pastan
Witam,
Aktualnie rozplanowuje na kartce swój najnowszy projekt i bardzo staram się dopiąć każdy element już podczas planowania by zaoszczędzić potem czasu i nerwów gdy będę to wszystko przekładał na kod. Podczas planowania mam pewien problem do rozgryzienia i mam nadzieję, że pomożecie.

Planuje stworzyć portal gdzie każdy z użytkowników po zarejestrowaniu będzie posiadał własne adresy, dokumenty oraz inne dane, które będą zapisywane w tabelach mySQL. Zakładam, że liczba rekordów dla jednego użytkownika będzie bardzo duża, na oko ponad milion. I teraz zastanawiam się czy stworzyć jedną bazę ogólną z tabelkami i w niej przechowywać wszystkie dane każdego z użytkowników. Boje się tylko, że wtedy taka tabela może mieć naprawdę sporo rekordów (np. 100 użytkowników * 1mln rekordów = 100mln rekordów!!!) co sprawi, że szybkość działania portalu bardzo drastycznie się zmniejszy.

Pomysł jaki mi wpadł do głowy to podczas rejestracji nowego użytkownika tworzyć nową bazę danych dla niego a w niej wszystkie tabelki. Wtedy jedna tabelka posiadała by maks 1mln rekordów a nie 100mln jak w poprzednim rozwiązaniu. Według mnie będzie to bardziej optymalne rozwiązanie jeżeli chodzi o szybkość działania portalu.

Czy ktoś z Was próbował już coś takiego zrobić? Czy moje myślenie jest poprawne? Czy rozdzielenie użytkowników tak by każdy posiadał własną bazę jest dobrym pomysłem? Czy aby na pewno tym rozwiązaniem zwiększę szybkość działania systemu?

Z góry dziękuję za pomoc!
ZaqU
Pomysł z tworzeniem osobnej bazy dla każdego użytkownika z osobna jest bardzo radykalny i abstrakcyjny. Przede wszystkim, odpada możliwość pracy na danych wielu użytkowników, gdyż tworzenie 100 połączeń dla 100 różnych użytkowników dopiero może obciążyć wykonanie skryptu php.

Wbrew pozorom, milion rekordów dla współczesnych serwerów to bułka z masłem. Oczywiście, najważniejsze jest odpowiednie zaplanowanie bazy przed jej utworzeniem (nigdy na odwrót!). O takich rzeczach jak stringi przechowywane w varchar'ach o odpowiedniej długości, czy też liczby o typie stosownym do ich maksymalnej wielkości chyba nie muszę wspominać, bo to jest raczej oczywiste. To o czym powinieneś pomyśleć, to przede wszystkim INDEKSY. Dobrze założone potrafią zdziałać cuda, nawet przy największych wydawać by się mogło bazach.

Trudno jest udzielić jakichś bardziej szczegółowych porad nie wiedząc co chcesz w tej bazie zapisać, ani jakie operacje na danych wykonywać. Może da się coś skrócić, bo milion rekordów na dane użytkownika to naprawdę bardzo dużo - zastanów się, czy rzeczywiście nie da się tej ilości zmniejszyć. Poczytaj też o testach wydajnościowych MySQL, a najlepiej przeprowadź własne testy obciążeniowe.
pastan
Dzięki za kilka cennych rad.
Mam jeszcze jedno pytanie ponieważ słyszałem, że jeżeli naprawdę chcemy zoptymalizować przechowywanie dużej ilości rekordów i operacji na nich to pomimo tego co nas nauczono powinniśmy powtarzać w tabelach dane zamiast pobierać ich po indeksach. Zaraz postaram się to wytłumaczyć na przykładzie bo tak z czystej teorii może to być nie jasne. Załóżmy mamy 2 tabele Użytkownicy i Konto. I teraz tak jak nas nauczano powinniśmy je zaprojektować w takim stylu:

  1. Użytkownicy:
  2. Id Username Password Name Surname
  3.  
  4. Konto:
  5. Id UserID money_usd money_pln money_eur


Mi zostało polecone, że gdy wiemy, że często potrzebne będzie nam oprócz wszystkich wartości z konta również nazwisko posiadacza konta to żeby duplikować dane bo to ponoć poprawi wydajność. Czyli tabelki powinny wyglądać tak:

  1. Użytkownicy:
  2. Id Username Password Name Surname
  3.  
  4. Konto:
  5. Id UserID Surname money_usd money_pln money_eur


Powyżej jest to tylko przykład. Czy ktoś z Was stosował takie rozwiązanie już? Czy jest to na pewno szybsze rozwiązanie?

Dodatkowo jeszcze jedno pytanko, poleci ktoś jakieś ciekawe artykuły na temat optymalizacji baz mysql do dużych projektów? biggrin.gif

Z góry dziękuję i pozdrawiam!
ZaqU
  1. Użytkownicy:
  2. Id Username Password Name Surname
  3.  
  4. Konto:
  5. Id UserID money_usd money_pln money_eur


Jeśli występuje tu relacja 1 do 1, to czy nie lepiej będzie po prostu zrobić to w ten sposób:

  1. Użytkownicy:
  2. Id Username Password Name Surname money_usd money_pln money_eur


?
Sama metoda z duplikowaniem danych jest jak wyważanie otwartych drzwi: Jeżeli ta przeważająca część zapytań będzie odwoływała się tylko do tabeli Konto (bez Użytkowników), to owszem, będzie widoczne zwiększenie szybkości, ale spowoduje to masę błędów:
  • Jest to całkowicie sprzeczne z relacyjnymi bazami danych i programowaniem obiektowym.
  • Aktualizacja powielonych danych będzie wymagała wielokrotnej zmiany tych samych danych w różnych tabelach
  • W pewnych sytuacjach można jeszcze bardziej zwiększyć czas wykonania zapytania MySQL.

Na pewno nie jest to żadnym wyjściem z sytuacji i osobiście odradzam w większości (99%) przypadków.

Pyton_000
Jeżeli przewidujesz faktycznie tak spore ilości danych per user to tutaj wchodzi partycjonowanie, Robisz partycje wg. ID użytkownika, dzięki czemu fizycznie nadal masz 1 tabelę z ogromną ilością rekordów ale logicznie jest tych tabel tyle ile użytkowników.

Wydajność tego rozwiązania polega na tym, że silnik odwołując się po ID usera szpera tylko w "bazie" dla tego konkretnego ID, więc ew. Lock tabeli odbędzie się tylko na tej jednej partycji a nie na całej bazie.
Kolejnym pkt. wydajności w takim wypadku jest wyszukiwanie. Przyklad.
Baza ma 100mln rekordów czyli 100 userów. Wyszukiwanie danych pomiędzy datami dla Usera ID 55 będzie odbywało się tylko na 1mln rekordów (partycja konkretnego usera) a nie na wszystkich (100mln), analogicznie WHERE user_id IN(55,66,77) przeszuka "tylko" 3mln rekordów.

Ogólnie wzrost wydajności jest bardzo duży, kosztem zajmowanego miejsca na serwerze (ale to żaden argument) i musem skonfigurowania tego poprawnie.


Innym rozwiązaniem może być replikacja, gdzie replikujesz rekordy np. parzyste do jednego serwera, nieparzyste do innego, a wyszukiwanie będzie odbywało się w zależności od ID usera. Równie dobre rozwiązanie j.w. jednak dużo bardziej kosztowne i wymagające większej zabawy.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.