Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP/MySQL] Liczba kolumn w tabeli a wydajność
Forum PHP.pl > Forum > PHP
MalyKazio
Witam.

Przyszło mi rozbudować nieco dane przechowywane w tabelach w bazie danych ale w trakcie zacząłem zastanawiać się nad sensownością mojego pomysłu. Otóż mam tabelę zbudowaną z około 40 kolumn. Większość z nich jest typu int. Czy można jeszcze do takiej tabeli dodawać kolejne kolumny, czy też raczej lepiej stworzyć nową tabelę i tam je wrzucać? Czy ilość kolumn ma jakieś widoczne przełożenie na wydajność zapytań i całego kodu napisanego w php? Z jednej strony chyba bezsensowne jest dzielenie tabel i potem ich łącznie za pomocą JOIN, czy nawet późniejsze sklejanie tablic z rezultatami zapytań, ale z drugiej taki podział nie wydaje się całkiem pozbawiony sensu.
woj_tas
Cytat(MalyKazio @ 26.03.2008, 21:44:46 ) *
Czy można jeszcze do takiej tabeli dodawać kolejne kolumny, czy też raczej lepiej stworzyć nową tabelę i tam je wrzucać? Czy ilość kolumn ma jakieś widoczne przełożenie na wydajność zapytań i całego kodu napisanego w php? Z jednej strony chyba bezsensowne jest dzielenie tabel i potem ich łącznie za pomocą JOIN, czy nawet późniejsze sklejanie tablic z rezultatami zapytań, ale z drugiej taki podział nie wydaje się całkiem pozbawiony sensu.


Wydaje mi się że ilość kolumn nie determinuje w znaczący sposób czasu zapytań itp. Łączenie tabel left joinami w niczym nie pomoże...


Cytat(MalyKazio @ 26.03.2008, 21:44:46 ) *
Otóż mam tabelę zbudowaną z około 40 kolumn.


Skłaniałbym się bardziej do optymalizacji tabeli, oraz innego przechowywania danych. Prawdopodobnie problem wynika ze źle zaprojektowanej bazy.
pyro
Cytat(MalyKazio @ 26.03.2008, 21:44:46 ) *
Witam.

Przyszło mi rozbudować nieco dane przechowywane w tabelach w bazie danych ale w trakcie zacząłem zastanawiać się nad sensownością mojego pomysłu. Otóż mam tabelę zbudowaną z około 40 kolumn. Większość z nich jest typu int. Czy można jeszcze do takiej tabeli dodawać kolejne kolumny, czy też raczej lepiej stworzyć nową tabelę i tam je wrzucać? Czy ilość kolumn ma jakieś widoczne przełożenie na wydajność zapytań i całego kodu napisanego w php? Z jednej strony chyba bezsensowne jest dzielenie tabel i potem ich łącznie za pomocą JOIN, czy nawet późniejsze sklejanie tablic z rezultatami zapytań, ale z drugiej taki podział nie wydaje się całkiem pozbawiony sensu.


Owszem oddziałowuje to na wydajność, lecz nie w stopniu, który miałby specjalnie rzucać się w oczy.

To, czy tworzyc tabele, czy dodawać kolumny zależy od tego jakie dane tam przechowujesz, np. jesli masz stronę handlowa, gdzie masz klientow i produkty, lepiej dla obu stworzyc oddzielne tabele, ale np. nie warto dzielic adresy klientow i ich nazwiska na oddzielne tabele.

Jeżeli tabela musi mieć tyle kolumn, to powinieneś postawić na optymalizację tabel.
MalyKazio
No właśnie, tak mi się wydawało, że dzielenie tego nie ma sensu. To polegałoby właśnie mniej więcej na oddzieleniu nazwisk klientów od ich adresów i innych danych. Potem i tak musiałbym to wszystko wyciągnąć z bazy danych i skleić - czy to w zapytaniu za pomocą JOIN, czy też jako oddzielne zapytanie i wyciągnięcie jako osobnego wyniku zapytania.
Nie za bardzo wiem jak można to zoptymalizować. Wyciągam rekordy głównie po nr ID, który jest indeksem i typu auto_increment. Niestety liczba danych zwiększy się, więc chyba niestety i liczbę kolumn będę musiał zwiększyć.
taro
Czy ktoś miał podobny problem?

Aktualnie projektuję bazę i już mam tabelę, która ma około 40 kolumn. Dodam też, że wszystkie dane, które można rozdzielić są przechowywane w oddzielnych tabelach (powtarzające się dane).

Gdzieś udało mi się wyczytać, że rozdzielanie danych może wpłynąć później w przyszłości na czas zapytania (negatywnie).

Danych takich jak:
imie, nazwisko, data urodzenia, adres, pesel, telefon, mail, telefon kom itp to wiadomo, że nie mogę rozdzielić bo nie ma sensu

dodatkowo muszę jeszcze przechowywać uczelnie jakie dana osoba ukończyła (uczelnia, wydział, kierunek, stopień, specjalność, rodzaj studiów zaoczne/dzienne/wieczorowe, rok rozpoczęcia)

Jak widać każde zapamiętanie pełnych danych uczelni powoduje dodatkowe 7 kolumn. Muszę przechowywać 3 uczelnie, więc dochodzi kolejne 21 kolumn + dane itp...

Zastanawiam się, czy stworzyć oddzielną tabelę np UCZELNIE i tam stworzyć te 7 kolumn + dodatkowe, w których będę przechowywał tylko ID użytkownika, do których należą dane wpisy ?

W pewnym stopniu zoptymalizuje to gromadzenie np pustych wpisów jeżeli dana osoba ukończyła 1 uczelnie, a z drugiej strony wymusza "skakanie" po tabelach...

Mógłby ktoś doradzić co z tym zrobić, aby było to optymalne?
thek
Wszystko zależy tylko i wyłącznie od "powtarzalności" danych w rekordzie. Jeśli do jednego rekordu trzeba mieć możliwość przypisania kilku identycznych danych to jest to już relacja jeden do wielu. A jeśli dodatkowo do tych wielu pasuje także wiele rekordów to masz wiele do wielu, co ewidentnie wskazuje Ci na oddzielenie wyników. Przykład "jeden do wielu"? Telefony. Jedna osoba może nie mieć ich wcale, jeden lub kilka (domowy, służbowy, komórkowy), ale tyczą one zawsze tylko tej jednej osoby gdyż nie może jeden telefon być własnością kilku (na upartego domowy mógłby być winksmiley.jpg ). Wiele do wielu? Uczelnia - student. Jeden student może uczyć się na wielu uczelniach, a dodatkowo do jednej uczelni uczęszcza wielu studentów. Myślę, że to obrazowe przykłady. Tak więc jak widzisz, dane typu telefon wcale nie muszą być ściśle związane z kolumną. Wszystko zależy od struktury bazy i pomysłu na nią. To samo z adresem, bo przecież może być stały i tymczasowy. W takich przypadkach można więc dane teoretycznie nierozerwalnie z czymś związane - jeszcze wydzielić. Ale to już zależy naprawdę od tego czy trzeba czy nie. Nie zawsze jest sens.
cojack
Bezsensu! Oczywiście że wszystko można rodzielać, zależy tylko czy robisz to z głową i np:

Tabela Użytkownik:
idUser | userName | userPwd

Tabela DaneUzytkownika
idUsera | Imie | Nazwisko | nrButa | imieMatki | imieOjca | Pesel | Nip

Tabela DaneTeleUzytkownika
idUsera | nrTelefonu

Tabela DaneAdresoweUzytkownika
idUsera | adres | typAdresu (enum [zamieszkania,zameldowania,pobyt tymczasowy...])

Tabela AdresyEmailUzytkownia
idUsera | adresEmail

I co Ty na to? W zależności teraz jak ustawie relacje pomiędzy tabelami takie moi użytkownicy będą mieli możliwości z dodaniem danych, będą mogli mieć wiele adresów email, wiele nr telefonów, wiele adresów różnego typu.

Kto napisał że dzielenie jest złe? B.dobre winksmiley.jpg I teraz rzucasz sobie pkey na idUsera w każdej tabeli z refrencją na tabele uzytkownika, masz od razu btree index. I śmiaga aż hoho, a pobierasz tylko wtedy inne dane gdy Ci są potrzebne. Pamiętajmy sql nie lubi jak ma pare kolumn z czego n-x jest null.
pitbull82
Nurtuje mnie ten sam problem ale z większą ilość kolumn. Chcę stworzyć portal - użytkownik wybiera jako informacje o sobie dane z selectów, do niektórych coś wpisuje, w innych wybiera radio albo checkoxy. Taka ilość danych to około 100 jak nie więcej. Oczywiście w teorii pięknie można to sobie rozbić na tabele - z tym nie ma problemu.

Co jednak z wyszukiwaniem. Jako że wszystkie te dane będą dostępne dla pozostałych userów, musi istnieć wyszukiwanie po dowolnej liczbie danych użytkownika, a już przy 10000 rekordów i kilku joinach wydajność jak sądzę znacząco spadnie. Jak podejść do takiego tematu - mimo wszystko utworzyć kilka tabel czy stworzyć jedną z wielką ilością kolumn.
wookieb
Zagadujesz o temat optymalizacji zapytań wyszukiwania a to jest tak szerokie jak Wisła.
Odpowiednie indeksy i na pewno nie będziesz umożliwiał przeszukiwanie po wszystkich polach. Dodatkowo, jak będziesz mieć naprawdę ogromną ilość użytkowników i jakieś zaawansowane wyszukiwanie pełnotekstowe to wtedy już nie korzystasz z samego MYSQL-a.
buzek
Witam serdecznie,

Postanowiłem napisać tu, by nie powielać tematów...

Trzymam w bazie danych wyniki turniejów tenisowych opartych o drabinke na 32 uczestnikow (http://www.tenis.net.pl/gpw/turniej_wyniki.php?turniej=1125). Do tej pory wszystko trzymałem w jednym rekordzie... 32+16+8+4+2+1 kolumn na id zawodnikow oraz polowe tej sumy na wyniki poszczegolnych meczow...

Chciałbym jednak dać możliwość wprowadzania takich drabinek na 64 uczestnikow, gdzie liczba kolumn wzrosłaby jeszcze o bodajże 96(!) kolumn....

Zrobiłem eksperyment i wstawiłem te same dane do tabeli z kolumnami (id_turnieju, klucz, wartosc), gdzie każdej wielkości drabinkę mógłbym trzymać....

Jednak rozmiar takich 100 turniejów wyniosl ok 1,5mb. Jak się pozniej okazało na InnoDB, zmieniłem na MyIsam, jest już lepiej, ale dalej zajmuje to duzo duzo wiecej kb niż w pierwotnym moim rozwiązaniu.... pytanie w która stronę lepiej iść? nie przejmować się megabajtami?

Turniejów przybywa ok 200-300 rocznie...

Jedyne co znalazłem w necie, co mi nie pomogło to to http://forum.pcformat.pl/MySQL-Jedna-tabel...ymi-ilosciami-t

Co na ten temat myslicie?

Z góry dziękuję za pomoc

esse
imho:

-> w bazie trzymasz jeden rekord dla danego turnieju (w tabeli tournaments)
-> turniej ma wielu uczestników (relacja wiele do wielu, bo uczestnik bierze udział w wielu turniejach - to atrybut pochodny, ale może się przydać do łatwiejszej logiki)
-> turniej ma swój typ (relacja jeden do wielu - turniej ma jeden typ, który współdzieli z innymi) - wręcz w modelowaniu obiektowym sugerowałbym podklasy dla różnych turniejów
-> turniej ma wiele rund (jak to generować - wynika z typu turnieju)
-> każda runda ma wiele meczów
-> no i oczywiście mecz ma wielu uczestników (relacja wiele do wielu)

i teraz w momencie startu turnieju, generujesz pierwszą rundę - z typu meczu wynika ile rund ma być i jak ma wyglądać logika. następnie gdy wszystkie mecze będą zakończone w rundzie, generujesz kolejną rundę (lub kończysz turniej - logika powinna być zawarta w klasie zawierającej typ turnieju). itd.

oczywiście co dokładnie będzie w bazie, a co w kodzie zależy też chociaż od tego jak elastyczny ma być system etc.
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.