Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> (za)długi czas wykonania zapytania
devnul
post
Post #1





Grupa: Zarejestrowani
Postów: 1 470
Pomógł: 75
Dołączył: 21.09.2005
Skąd: że znowu

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


Jak w temacie. Mam zapytanie:
  1. SELECT `n`.`news_id`, `t`.`newstext_title`, `t`.`newstext_text`, `n`.`news_publish`,`p`.*
  2. FROM `news` AS `n`
  3. JOIN `newstext` AS `t` ON `n`.`news_id`=`t`.`newstext_parent`
  4. JOIN `news2cat` AS `nc` ON `n`.`news_id`=`nc`.`news2cat_news`
  5. LEFT JOIN `news2photo` AS `np` ON `np`.`news2photo_news`=`n`.`news_id`
  6. LEFT JOIN `photo` AS `p` ON `np`.`news2photo_photo`=`p`.`photo_id`
  7. WHERE `n`.`news_status`='1' AND `n`.`news_publish`<='1198155351' AND (`n`.`news_publishend`>='1198155351' OR `n`.`news_publishend`=0) AND `nc`.`news2cat_category`
  8. IN ('1', '2', '3', '4', '11', '5', '13', '8', '6', '14', '20', '7', '15', '9', '10', '16', '17', '18', '19', '12')
  9. GROUP BY `n`.`news_id`
  10. ORDER BY `n`.`news_publish` DESC LIMIT 0, 10

i wykonuje się ono w granicach 20 sekund co jest nie do przyjęcia. W tabelach news i newstext znajduje się po około 80 tysięcy rekordów w tabeli photo jest około 40 tysięcy wpisów tabela news2photo to około 50 tysięcy rekordów.
Pytanie co zrobić żeby przyspieszyć to zapytanie do jakiegoś znośnego czasu?

Ten post edytował devnul 3.05.2008, 15:54:19


--------------------
Profesjonaliści są przewidywalni...
strzeż się amatorów...
FL4SHB4CK - imprezy, galerie, lokale
Go to the top of the page
+Quote Post
kitol
post
Post #2





Grupa: Zarejestrowani
Postów: 162
Pomógł: 26
Dołączył: 19.01.2007

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


Założyć indeksy (jeżeli ich nie ma) na kolumny po których łaczysz oraz na kolumny które występują w klauzuli WHERE
Go to the top of the page
+Quote Post
devnul
post
Post #3





Grupa: Zarejestrowani
Postów: 1 470
Pomógł: 75
Dołączył: 21.09.2005
Skąd: że znowu

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


są indeksy na wszystkich kolumnach po których łącze i wszystkich które są w WHERE (i paru innych - bo do innych zapytań potrzebowałem)

Ten post edytował devnul 20.12.2007, 14:29:19


--------------------
Profesjonaliści są przewidywalni...
strzeż się amatorów...
FL4SHB4CK - imprezy, galerie, lokale
Go to the top of the page
+Quote Post
Jarod
post
Post #4





Grupa: Zarejestrowani
Postów: 1 190
Pomógł: 27
Dołączył: 23.04.2005

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


Daj przed zapytaniem explain i zobacz co da się jeszcze zrobić.. Tu masz w skrócie napisane co każdy opis oznacza http://0day.pl/index.php/archives/12


--------------------
”Godzina nauki w życiu nowoczesnego apostoła jest godziną modlitwy.”
(św. Josemaría Escrivá, Droga, 335)
Go to the top of the page
+Quote Post
kitol
post
Post #5





Grupa: Zarejestrowani
Postów: 162
Pomógł: 26
Dołączył: 19.01.2007

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


Najlepiej wklej tu tego explaina
Go to the top of the page
+Quote Post
devnul
post
Post #6





Grupa: Zarejestrowani
Postów: 1 470
Pomógł: 75
Dołączył: 21.09.2005
Skąd: że znowu

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


EXPLAIN - dużo to raczej nie daje


--------------------
Profesjonaliści są przewidywalni...
strzeż się amatorów...
FL4SHB4CK - imprezy, galerie, lokale
Go to the top of the page
+Quote Post
php programmer
post
Post #7





Grupa: Zarejestrowani
Postów: 1 045
Pomógł: 5
Dołączył: 8.11.2004
Skąd: trójmiasto

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


Wywal wszystkie JOINY,

zamiast tego zrób na początku jedno zapytanie odpowiadające głownemu zapytaniu ale
pobierające tylko id z głównej tabeli
id zbierasz w jakiejś tabeli php-owej

potem robisz osobna zapytanie dla zapytania głównego
oraz osobne zapytanie odpowiadające kazdemu JOIN
gdzie warunkiem jest id nalezace to tych zebranych w tapeli php-owej

Wyniki kazdego JOINA zapisujesz w tablicy php-owej (oczywiście innej niż ta wyżej,
osobna taliba dla kazdego JOIN), ale w taki sposób,
że indeksami są id table głównej, dzięki czemu można się potem bezpośrednio
odwoływać do danych JOIN-owych

niedawno zastowowałem tego typu rozwiązanie i bardzo pomogło
w beznadziejnej wydawałoby się sytuacji, bo danych było tyle, że
nawet jednego JOINa nie można było dodać

Ten post edytował php programmer 21.12.2007, 08:42:41
Go to the top of the page
+Quote Post
devnul
post
Post #8





Grupa: Zarejestrowani
Postów: 1 470
Pomógł: 75
Dołączył: 21.09.2005
Skąd: że znowu

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


rozwiązanie nie za bardzo bo za dużo tu zależności np rekord znajdujący się w tabeli news nie musi mieć pokrycia w tabeli newstext (skąd mam wiedzieć ile wyciągnąć id z news żeby trafić na 100% na 10 istniejących w tabeli newstext, bo przecierz może być teorytycznie np 1000 rekordów po koleii w news nie mających odpowiednika w newstext).

Jakieś inne pomysły?


--------------------
Profesjonaliści są przewidywalni...
strzeż się amatorów...
FL4SHB4CK - imprezy, galerie, lokale
Go to the top of the page
+Quote Post
php programmer
post
Post #9





Grupa: Zarejestrowani
Postów: 1 045
Pomógł: 5
Dołączył: 8.11.2004
Skąd: trójmiasto

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


Wyciągasz wszystkie id z news, które spełniają warunek głównego zapytania,
brak pokrycia niczemu nie szkodzi, jeśli nie chcesz wyświetlać news bez pokrcia,
sprawdzasz w pętli (czyli złożoność obliczeniowa liniowa)

  1. <?php
  2. $count = count($TablicaNews);
  3.  
  4. for ($i=0;$i<$count;$i++)
  5. if (!isset($TablicaNewsText[$i])) unset($TablicaNews[$i]);
  6. ?>


i tu na przykład widać dlaczego indeksami tablic podrzędnych
są id z głownej elementów tabeli (bezpośrednio się odwołujemy)

PS. Swoją drogą nie warto tworzyć aż tylu powiązanych tabel,
np. wstawianie tekstu newsa do innej tabeli zamiast dać w tej samej

Ten post edytował php programmer 21.12.2007, 08:46:02
Go to the top of the page
+Quote Post
devnul
post
Post #10





Grupa: Zarejestrowani
Postów: 1 470
Pomógł: 75
Dołączył: 21.09.2005
Skąd: że znowu

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


@php programmer: Ty chyba nie doczytałeś tego co napisałem w pierwszym poście w obu tabelach ma po około 80 tysięcy rekordów - niekoniecznie pokrywających się co oznacza wyciągnięcie 2*po 80 tysięcy id z obu tabel i sprawdzenie ich w pętli - na dość mocno obciążonym serwerze takie działanie nie przejdzie z przyzwoitą szybkością.

Rozbicie newsa na 2 tabele było mi potrzebne z pewnych względów o których pisać tutaj nie będę bo nie w tym problem, gdyby tak nie było - wierz mi że te tabele byłyby jedną.

Ten post edytował devnul 21.12.2007, 13:21:13


--------------------
Profesjonaliści są przewidywalni...
strzeż się amatorów...
FL4SHB4CK - imprezy, galerie, lokale
Go to the top of the page
+Quote Post
kitol
post
Post #11





Grupa: Zarejestrowani
Postów: 162
Pomógł: 26
Dołączył: 19.01.2007

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


80 tyś rekordów to nie jest dużo. Przy dobrze ustawionych indeksach powinno śmigać. Bez definicji tabel ciężko coś więcej powiedzieć (explain nie otwiera się). Czy w tabelach masz pole TEXT lub BLOB? Jeżeli tak to wydaje mi się że lepiej jest zrobić oddzielną tablicę zawierającą tylko pole TEXT i jakiś id a resztę informacji trzymać oddzielnie.
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 Aktualny czas: 20.08.2025 - 18:17