Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Dyskusja: optymalizacja baz danych, Zliczanie rekordów z drugiej tabeli
Athlan
post 30.06.2007, 10:49:42
Post #1





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Witam,

Dziś chciałbym podyskutować troszkę na temat optylamizacji zapytań do baz danych.

Ostatnio mam problem z pobraniem ilości komentarzy przypisanych do listy notek na blogu, a że będzie to dość wielki system blogowy oferujący dobudowanie swojej cegiełki w Internecie, zależy mi na maksymalnej optymalizacji, dlatego poświece temu ten oto topick.

Wracając do zliczania komentarzy. Mamy 3 sposoby:

1. Zapisywać ilość komentarzy (notes_comments = notes_comments + 1) przy każdym dodawaniu komentarza do notki, a przy usuwaniu odejmować tą wartość.

2. Zliczać ilość komentarzy zapytaniem, które przelatuje przez tabelą komentarzy licząc je i grupując wg ich ID, ale tylko te, które przynależą do notek wyświetlonych na liście, przykładowo:
  1. <?php
  2. public function getUsed(array $aNotes)
  3. {
  4. $this->_connect();
  5. $oDb = $this->getSource();
  6.  
  7. $sSql = '
  8. SELECT `comment_blog_note` AS `note`, COUNT(`comment_id`) AS `comments`
  9. FROM `comments`
  10. WHERE `comment_blog_note` = ' . implode(' OR `comment_blog_note` = ', $aNotes) . '
  11. GROUP BY `comment_blog_note`';
  12. $rResult = $oDb->Execute($sSql);
  13.  
  14. $aComments = array();
  15.  
  16. while($aRow = mysql_fetch_array($rResult))
  17. {
  18. if(!is_array($aUsedTags[$aRow['note']]))
  19.  $aUsedTags[$aRow['note']] = array();
  20.  
  21. $aComments[$aRow['note']][] = $aRow['comments'];
  22. }
  23.  
  24. return $aComments;
  25. }
  26. ?>

Otrzymujemy tablicę: NOTKA => ILOŚĆ_KOMENTARZY, później możemy połączyć ją w PHP.

3. Dołączmy JOINA i countujemy komentarze przpisane do danej notki:
  1. SELECT n.*, COUNT(c.comment_id) AS count_comments FROM notes AS n
  2. LEFT JOIN comments AS c ON (c.comment_blog_note = n.note_id)
  3. GROUP BY note_id
  4. ORDER BY note_time DESC


-----------------------------------------------------------------------------------------

Wykonując sposób pierwszy, nie mamy doczynienia z żadnym liczeniem. Chciałbym trochę podyskutować na temat sposobu 2 i 3. Doszły mnie słuchy od @cichy'ego i od @hwao, że przy wielkiej ilości rekordów baza może trochę zamulać. Zadaje więc 2 pytania:

Całe sedno sprawy
  1. Baza danych zacznie zamulać w przypadku dużej ilości rekordów przypisanych do notki?
  2. Baza danych zacznie zamulać w przypadku dużej ilości rekordów w tabeli komentarzy?
Jak narazie jestem skłonny jak najbardziej do sposobu nr 1, ale chciałbym omówić dwa pozostałe.

Zapraszam do dyskusji smile.gif Athlan smile.gif


--------------------
Portfolio: Vgroup.pl | athlan.pl | Test.php.pl - sprawdź się z wiedzy o PHP i ułóż własne pytania!
Pomogłem? Kliknij pod postem.
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 8)
AcidBurnt
post 30.06.2007, 11:09:41
Post #2





Grupa: Zarejestrowani
Postów: 215
Pomógł: 1
Dołączył: 13.04.2003
Skąd: z ławki przed blokiem

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


naqjlepiej bedzie zliczac ilosc konetarzy wpisów, dodawajac danycj, poprzez jakiego trigera ktory bedzie po prostu zwiekszal gdzies ta wartosc

i tak baza bedzie sie mulic jesli bedizesz mial duuuuzo rekordów i bedziesz wykonywał operacje count itp
Go to the top of the page
+Quote Post
Athlan
post 30.06.2007, 12:27:00
Post #3





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Przeprowadziłem testy, miałem do dyspozycji:
  • 10 000 notek
  • do każdej notki po 10 komentarzy, czyli 100 000
  • sumarycznie operowałem na 110 000 rekordach
Zapytanie ze sposobu nr 3, operacja z limitem na 1000 rekordów:
  1. SELECT n.*, COUNT(c.comment_id) AS count_comments FROM megatest_notes AS n
  2. LEFT JOIN megatest_comments AS c ON (c.comment_note = n.note_id)
  3. GROUP BY note_id
  4. LIMIT 0, 1000

Cytat
Pokaż rekordy 0 - 999 (1 000 wszystkich, Wykonanie zapytania trwało 0.0111 sekund(y))

Sposób 3 na 2000 rekordów:
Cytat
Pokaż rekordy 0 - 1999 (2 000 wszystkich, Wykonanie zapytania trwało 0.0216 sekund(y))

Sposób 3 na 5000 i 10000 rekordów: phpmyadmin zwraca pustą stronę.

Teraz przetestujemy sposób 1, wybierając id rekordów z notek (załóżmy, że jest to pole ilości komentarzy)

Sposób 1, 100 rekordów:
  1. SELECT note_id FROM `megatest_notes` LIMIT 0, 1000

Cytat
Pokaż rekordy 0 - 99 (100 wszystkich, Wykonanie zapytania trwało 0.0015 sekund(y))

Sposób 1, 500 rekordów:
phpmyadmin zwraca pustą stronę.

Wniosek? Chyba będę używał sposobu nr 3, bo nie przewiduję aż tak wielkiej bazy na jakiej testowałem moje przemyślenia.

Jak się do tego ustosunkujecie? Jakieś rady?

Dzięki za odpowiedzi, Athlan smile.gif


--------------------
Portfolio: Vgroup.pl | athlan.pl | Test.php.pl - sprawdź się z wiedzy o PHP i ułóż własne pytania!
Pomogłem? Kliknij pod postem.
Go to the top of the page
+Quote Post
NuLL
post 30.06.2007, 13:22:40
Post #4





Grupa: Zarejestrowani
Postów: 2 262
Pomógł: 21
Dołączył: 3.05.2004
Skąd: Sopot, Krakow, W-wa

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


A moze tak cache zamiast robic dziwne rzeczy ?


--------------------
Javascript, Coffeescript, Node.js, Mongo, CouchDb, chmury, workery & inne bajery - zycie jest zbyt krotkie aby miec nudna prace :)
Go to the top of the page
+Quote Post
Athlan
post 30.06.2007, 13:39:18
Post #5





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


Cytat
A moze tak cache zamiast robic dziwne rzeczy ?

Oprócz tego co piszę w powyższych postach będzie cache uaktualniane co 5minut lub przy akcji np edycji notki albo usunieciu komenta.

Zaznaczam, że nie mam jednego bloga tylko serwis blogowy smile.gif


--------------------
Portfolio: Vgroup.pl | athlan.pl | Test.php.pl - sprawdź się z wiedzy o PHP i ułóż własne pytania!
Pomogłem? Kliknij pod postem.
Go to the top of the page
+Quote Post
SongoQ
post 1.07.2007, 10:21:51
Post #6





Grupa: Przyjaciele php.pl
Postów: 2 923
Pomógł: 9
Dołączył: 25.10.2004
Skąd: Rzeszów - studia / Warszawa - praca

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


To moze ja sie wypowiem troche w tej kwestii. Podales 3 przyklady wykorzystania, jesli chodzi o optymalne rozwiazanie i ilosc komentarzy do posta to nie wiem jak bys kombinowal to 1 przykad jest najbardziej optymalny - dlaczego? Wyciagasz 1 rekord jako PK z 1 tabeli gdzie masz juz 1 wartosc, opleracje zewnetrznych zlaczen jak i agregacji sa calkowicie pomijane.

Co do przykladu nr 3 warto podkreslic ze na optymalizacje wchodzi kilka czynnikow. 1 to index na pola zlaczeniowe, 2 index na pole uzywane w sortowaniu.

Co do stwierdzenia ze przy duzych danych baza bedzie zamulac to pomysl ma szybciej dzialac? Przeciez LEFT JOIN to odczytanie krotek z jednej tabeli a nastepnie w petli dolanczanie do 2 tabeli a nastepnie agregacja sortowania i inne cuda, wiec co szybciej jest wykonac 10x petle czy powiedzmy 10 mil? Wazne w bazie sa indeksy - to tak jak w ksiazce otwierasz spis tresci i wiesz jaki temat Cie interesuje i jaka strone chesz otworzyc bez czytania kazdej strony.

Co do Twoich testow to wsumie wykonywales na malej ilosci danych.

Jesli chcesz dobrze operowac cache w bazie danych to takie narzedzie jak bind jest Ci pomocne. Mowie tutaj o cache stringa zapytan w bazie. Kiedys o tym juz pisalem, po co sie stosuje prepare i bind.

Co do cache juz w samym php to tez ma sens jesli nawet cache mial by sie oswierzac 1 na 10 zadan.


--------------------
Go to the top of the page
+Quote Post
Athlan
post 1.07.2007, 12:06:58
Post #7





Grupa: Developerzy
Postów: 823
Pomógł: 12
Dołączył: 18.12.2005

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


@SongoQ, dzięki za wypowiedź

Dobrze, że zwróciłeś uwagę na indeksy, to akurat robie już przy samym projektowaniu bazy obmyślając każdy przypadek użycia jakiegokolwiek z pól w ewentualnych featurach. Indeksy mają duży wpływ na szybkość działania baz danych.

Wracając już do mojego problemu. Razem z Bastion'em i Envp rozwiązałem ten problem w bardzo prosty sposób. Połączmy sposoby 1 i 3. Co nam to da? Nie liczymy rekordów za każdym razem, a zapisujemy je w polu. Dlaczego akurat tak?

Załóżmy że zapytanie dodania komentarza nie wypaliło bo cośtam. Nawet jeśli sprawdzałbym, czy zapytanie się powiodło tutaj również mogło coś niewyaplić. Tak czy siak dodaje notes_comments_count = notes_comments_count + 1. Żle! Przy takiej akcji mogę wywołać metodę w modelu która podliczy ile faktycznie mam komentarzy przypisanych do tej notki i (jeżeli wartość się różni) zapisać wynik w pole notes_comments_count.

Myślę, że jest to najlepsze wyjście, podkreślam kiedy warto go użyć:
- przy dodawaniu newsa
- edycji
- usuwaniu
- wszelkim zmianom statusu (aktywny/nieaktywny na stronie)

Pozdrawiam i dzięki za dyskusję, Athlan smile.gif


--------------------
Portfolio: Vgroup.pl | athlan.pl | Test.php.pl - sprawdź się z wiedzy o PHP i ułóż własne pytania!
Pomogłem? Kliknij pod postem.
Go to the top of the page
+Quote Post
dr_bonzo
post 1.07.2007, 12:10:56
Post #8





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

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


Cytat
Załóżmy że zapytanie dodania komentarza nie wypaliło bo cośtam. Nawet jeśli sprawdzałbym, czy zapytanie się powiodło tutaj również mogło coś niewyaplić. Tak czy siak dodaje notes_comments_count = notes_comments_count + 1. Żle! Przy takiej akcji mogę wywołać metodę w modelu która podliczy ile faktycznie mam komentarzy przypisanych do tej notki i (jeżeli wartość się różni) zapisać wynik w pole notes_comments_count.


eee? A transakcje?


--------------------
Nie lubię jednorożców.
Go to the top of the page
+Quote Post
SongoQ
post 1.07.2007, 18:07:52
Post #9





Grupa: Przyjaciele php.pl
Postów: 2 923
Pomógł: 9
Dołączył: 25.10.2004
Skąd: Rzeszów - studia / Warszawa - praca

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


Dokladnie od tego sa transakcje, nie ma takiej mozliwosci ze sie cos wywali tutaj doda a tutaj nie. Baza danych baz transakcji to zwykly zbior danych a tak nie jest. Odnosnie Twojego problemu padla post ze najlepiej triggera zrobic. Przy swoich projektach staram sie wszystkie takie operacje wlasnie na triggerach robic 1 zapytanie do bazy i masz juz mase operacji zalatwionych.


--------------------
Go to the top of the page
+Quote Post

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

 



RSS Wersja Lo-Fi Aktualny czas: 18.07.2025 - 23:16