Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Liczba tematów i postów w forach
peku33
post
Post #1





Grupa: Zarejestrowani
Postów: 65
Pomógł: 5
Dołączył: 22.01.2010

Ostrzeżenie: (0%)
-----


Witajcie. Tworzę forum internetowe i mam problem ze stworzeniem odpowieniego zapytania do bazy.
Mam takie tabele

Forums z kluczem ForumId
Threads z kluczem ThreadId oraz indexem na ThreadId
Posts z kluczem PostId i indexem ThreadId

I teraz moje pytanie - jak do SELECT (..) FROM Forums dodać liczbę postów i tematów w tym forum

Próbowałem LEFT JOIN 2 i 3 tabelka, ale liczba nie była poprawna. Dodam, że każda z tabel ma pole Show, i powinna być zliczana tylko gdy jest ono równe 1
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 3)
thek
post
Post #2





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Coś więcej o strukturze, bo jak dla mnie to powinno być:
Posts z kluczem na Id i ThreadId (chyba warto wiedzieć w jakim temacie jest post)
Threads z kluczem na Id i ForumId (chyba warto wiedzieć w jakim forum jest temat)
Forums z kluczem na Id
Teraz JOIN między tabelami wychodząc od Posts jako głównej i grupowanie po ForumId z tabeli Threads oraz count na odpowiednich Id. Ale to jest MAŁO optymalne bo ilość wywołań tego zapytania będzie OGROMNA. Zrób sobie lepiej jakieś dodatkowe pola związane ze statystyką w tabelach Forums i Threads. W przypadku dodawania lub odejmowania tematów i postów, zwiększaj lub zmniejszaj tu owe dane statystyczne. Inaczej zarżniesz bazę liczeniem w kółko. W takim przypadku rezygnacja z nadmiarowości w bazie ma jak najbardziej uzasadnienie. Jeśli ktoś Ci zacznie pisać bajki o normalizacji bazy to go zapytaj wtedy o wydajność, a się zamknie (IMG:style_emoticons/default/wink.gif)
Go to the top of the page
+Quote Post
bar_bara
post
Post #3





Grupa: Zarejestrowani
Postów: 11
Pomógł: 1
Dołączył: 1.06.2010

Ostrzeżenie: (0%)
-----


Może ten mój szkic Ci coś pomoże:
  1. SELECT t.ThreadId, count(p.PostId) FROM Forums f, Threads t, Posts p WHERE t.ThreadId=p.ThreadId AND t.ForumId=f.id AND f.ForumId = IDszukanego AND t.SHOW=1 AND p.SHOW=1 GROUP BY t.ThreadId

I teraz w skrypcie php odczytać ilość wierszy - to liczba tematów, a następnie zsumować drugą kolumnę - to liczba postów w tym forum.

A jak to będzie wyglądało wydajnościowo to zawsze możesz podpatrzeć przez DESC SELECT...
To Show tu trochę energii pochłonie
Go to the top of the page
+Quote Post
peku33
post
Post #4





Grupa: Zarejestrowani
Postów: 65
Pomógł: 5
Dołączył: 22.01.2010

Ostrzeżenie: (0%)
-----


Nie mogę sobie pozwolić na pobieranie wszystkich wierszy.

Ostatecznie skonstruowałem takie zapytanie:
  1. SELECT F.ForumId, F.Name, COUNT(T.ThreadId) AS ThreadNum, SUM(T.PostNum) AS PostNum, T.ThreadId AS LastThreadId, T.Name AS LastThreadName, MAX(T.PostLastDate) AS PostLastDate, COUNT(T.ThreadId)-SUM(T.ThreadRead) AS UnreadPosts
  2. FROM ForumsForums AS F
  3. LEFT JOIN(
  4. SELECT T.ThreadId, T.ForumId, T.Name, SUM(P.PostNum) AS PostNum, MAX(P.PostLastDate) AS PostLastDate, COUNT(V.ThreadId) AS ThreadRead
  5. FROM ForumsThreads AS T
  6. LEFT JOIN (
  7. SELECT COUNT(PostId) AS PostNum, ThreadId, MAX(Date) AS PostLastDate
  8. FROM ForumsPosts
  9. WHERE Public=1
  10. GROUP BY ThreadId
  11. ) AS P USING ( ThreadId )
  12. LEFT JOIN ForumsThreadViews AS V ON (T.ThreadId=V.ThreadId AND V.UserId='%d' AND V.UnseenPostId = 0)
  13. WHERE Public=1
  14. GROUP BY ThreadId
  15. ORDER BY PostLastDate DESC
  16. ) AS T ON(F.ForumId=T.ForumId)
  17. WHERE F.Public=1 AND F.BoardId='%d'
  18. GROUP BY F.ForumId
  19. ORDER BY Sort ASC


Każda tabela ma PRIMARY na swoje Id (ForumsForums - ForumId) + klucz rodzica i te według których grupuję / sortuje / whereuje

EXPLAIN zapytania wywala:
Kod
1     PRIMARY     F     ref     Public,BoardId     BoardId     2     const     1     Using where; Using temporary; Using filesort
1     PRIMARY     <derived2>     ALL     NULL    NULL    NULL    NULL    4     
2     DERIVED     T     ref     Public     Public     1         3     Using temporary; Using filesort
2     DERIVED     <derived3>     ALL     NULL    NULL    NULL    NULL    4     
2     DERIVED     V     eq_ref     PRIMARY,ThreadId,UserId     PRIMARY     12     xxx.T.ThreadId     1     
3     DERIVED     ForumsPosts     ALL     Public     NULL    NULL    NULL    46     Using where; Using temporary; Using filesort


Jestem rootem na serwerze, mam 16GB ramu do dyspozycji więc mogę zwiększyć jakoś wartości pamięci podręcznej itp.

Jeszcze trochę o typach danych
ForumId, ThreadId - INT
PostId, UserId - BIGINT
Public - BOOL
Date - TIMESTAMP

Teraz pytanie, jak to się zachowa przy 100k postów i 20k tematów. Czy nie zamuli serwera?
Może lepiej ilość postów przechowywać jako pole w tabeli nadrzędnej?
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 24.08.2025 - 07:39