Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Optymalizacja zaawansowanego zapytania
Forum PHP.pl > Forum > Bazy danych > MySQL
Natalka
Mam pewien problem z zapytaniem, które strasznie zamula mi stronę.


Na stronie chcę pobrać

Wszystkie obrazki z bazy danych które zostały polubione powyżej 3 razy.


Moje zapytanie wygląda tak:
Kod
SELECT * FROM obrazek WHERE id in (SELECT id_obrazek FROM loveit HAVING count(loveit.id) > 3 ) ORDER BY id desc LIMIT $ilosc



Tabela obrazek - zawiera listę wszystkich obrazków

pola w bazie
id - nr id obrazka


Tabela loveit - zawiera listę wszystkich osób które lubią obrazek

pola w bazie
id_obrazek - nr id obrazka


Wiem że problem jest dokładnie tutaj
Kod
WHERE id in (SELECT id_obrazek FROM loveit HAVING count(loveit.id) > 3 )


Bo gdy usunę tę cześć działa bez problemu.

Czy jest ktoś w stanie mi pomóc w jaki sposób mogę to zoptymalizować?
melkorm
Spróbuj tak:
  1. SELECT * FROM obrazek o INNER JOIN loveit l ON o.id=l.id_obrazek GROUP BY l.id_obrazek HAVING count(l.id_obrazek) > 3 ORDER BY o.id DESC LIMIT $ilosc


Podaj też zrzuty struktur tabel, może indeksy da się poprawić.
Tomplus
Być może sprawa nie dot. zapytania,tylko samej bazy danej, może trzeba zmienić mechanizm obsługi bazy gdzie jest wiele zapytać.


I warto też ograniczyć pierwsze pole SELECT o kolumny które będziemy korzystać.
Natalka
Już testuję Twoje zapytanie


/** sprawdzone **/

Działa dużo szbciej, już nie zabija tak strony

Czy można jeszcze coś ulepszyć w mojej bazie danych ?


A czy mógłby ktoś jeszcze podpowiedzieć co takiego źle robiłam? Czemu aż tak bardzo moje zapytanie zamulało stronę?



A Baza wygląda tak:


Kod
CREATE TABLE IF NOT EXISTS `obrazek` (
  `id` int(9) NOT NULL AUTO_INCREMENT,
  `tytul` text NOT NULL,
  `opis` text NOT NULL,
  `skad` text NOT NULL,
  `obrazek` text NOT NULL,
  `obrazekmini` text NOT NULL,
  `user_id` int(9) NOT NULL,
  `raport` int(1) DEFAULT '0',
  `dodanydata` varchar(20) NOT NULL,
  `plikURL` text NOT NULL,
  `typ` enum('obrazek','video') NOT NULL DEFAULT 'obrazek',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin2 AUTO_INCREMENT=2604;



Kod
CREATE TABLE IF NOT EXISTS `loveit` (
  `id` int(9) NOT NULL AUTO_INCREMENT,
  `id_obrazek` int(9) NOT NULL,
  `id_user` int(9) NOT NULL,
  `datadodania` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin2 AUTO_INCREMENT=4450;
melkorm
Załóż indeksy na : user_id ( w obu tabelkach ) , id_obrazek, datadodania i dodanydata (przy okazji powinnaś te dwa pola zmienić na int/timestamp/date/datetime, bo varchar jest tutaj nie na miejscu).

edit:
Cytat
A czy mógłby ktoś jeszcze podpowiedzieć co takiego źle robiłam? Czemu aż tak bardzo moje zapytanie zamulało stronę?


Ponieważ dla każdego rekordu który pobierałaś odbywało się zapytanie
  1. SELECT id_obrazek FROM loveit HAVING count(loveit.id) > 3

które przelatywało za każdym razem całą tabelkę loveit.

I ogólnie IN'y + (sub)COUNTY są obciążające, dla tego jeżeli jest taka możliwość trzeba używać JOIN'ów które są o niebo szybsze.


edit2:
Dlaczego te pola są typu TEXT ? Nie wystarczyłby varchar(255/500) ?
Cytat
`tytul` text NOT NULL,
`skad` text NOT NULL,
`obrazek` text NOT NULL,
`obrazekmini` text NOT NULL,
`plikURL` text NOT NULL,


Jeszcze a propo indeksów możesz założyć na pole typ.
Natalka
Cytat(melkorm @ 15.05.2011, 15:23:49 ) *
Załóż indeksy na : user_id ( w obu tabelkach ) , id_obrazek, datadodania i dodanydata (przy okazji powinnaś te dwa pola zmienić na int/timestamp/date/datetime, bo varchar jest tutaj nie na miejscu).



Hmm..
Głupio mi przyznać bo nigdy nie stosowałam indeksów prócz dla id.

O co w nich chodzi?
Muszę ustawić nazwę klucza (czy ona ma jakiś związek z zapytaniem?)

Czy indeksy przyśpieszają pobieranie danych? Mam też inny duży serwis w którym niestety nie korzystam z indeksów, mimo że działa sprawnie.
A najwyższa pora zmienić swoje przyzwyczajenia i nauczyć się robić coś lepiej smile.gif

Bardzo dziękuje za pomoc,

Pola TEXT już zmienione smile.gif
melkorm
Jest sporo wartościowych tekstów w internecie na temat Indeksów, w skrócie mogę powiedzieć że mówią one jak porządkować dane w tabeli co przyśpiesza ich pobieranie.
Ogólnie przyjmuję się taką zasadę że indeksy zakłada się na pola po których porządkujesz/grupujesz tabelę i na klucze obce( przy silniku InnoDB jest to wymóg).

Btw. Zainteresuj się silnikiem InnoDB i relacjami.

Cytat
Muszę ustawić nazwę klucza (czy ona ma jakiś związek z zapytaniem?)


Nie jest ona ważna.

Cytat
Czy indeksy przyśpieszają pobieranie danych?


Gdybyś z większego serwisu/forum wywaliła indeksy sądzę że by nawet nie ruszył biggrin.gif - czyli tak, przyśpieszają i to czasami bardzo.

P.S. To nie jest zaawansowane zapytanie wink.gif
Natalka
Cytat(melkorm @ 15.05.2011, 15:37:54 ) *
P.S. To nie jest zaawansowane zapytanie wink.gif



Nie dla wszystkich smile.gif łączenie kilku tabel to dla mnie największy problem mimo przestudiowania książki z mysql

Jest to coś czego nie potrafię zrozumieć i sobie z tym nie radzę więc to dla mnie naprawdę trudne zapytanie.

Jeszcze raz wielkie dzięki, muszę w końcu się przysiąść do tego na poważnie by nie zanudzać swoimi problemami


Dzięki za pomoc smile.gif
melkorm
Cytat
Nie dla wszystkich łączenie kilku tabel to dla mnie największy problem mimo przestudiowania książki z mysql

Jest to coś czego nie potrafię zrozumieć i sobie z tym nie radzę więc to dla mnie naprawdę trudne zapytanie.

Ćwiczyć, ćwiczyć wink.gif

Cytat
Jeszcze raz wielkie dzięki, muszę w końcu się przysiąść do tego na poważnie by nie zanudzać swoimi problemami

Spoko, przynajmniej mamy co robić w niedzielne popołudnie biggrin.gif

Cytat
Dzięki za pomoc smile.gif

Nie ma za co smile.gif
Fifi209
Dla autora tematu pozwolę sobie zalinkować do video artów:
uw-team mysql

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.