Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Zapytanie z 3 tabel - optymalizacja
Forum PHP.pl > Forum > Bazy danych > MySQL
o_d
Mam 3 tabele : products, products_gallery, products_categories

Relacje:
"products" 1 -> wielu "products_gallery"
"products" 1 -> wielu "products_categories"


Chce pobrać wszystkie grafiki produktów, informacje o produkcie z listy produktó∑, któ®e należą do pewnej grupy kategorii.

Moje zapytanie ma postać:

  1. SELECT p.productID, p.prod_title, p.prod_iconS, p.prod_price, p.prod_url, pg.prod_photo_transp, pg.prod_photo_thmb, pg.prod_photo_id
  2. FROM products AS p, products_categories AS pc, products_gallery AS pg
  3. WHERE pc.catID IN (4, 8, 9, 10, 11, 12, 13, 14) AND p.productID=pc.productID AND p.productID=pg.prod_productID AND p.prod_visible='yes' ORDER BY p.prod_date_pub DESC LIMIT 0 , 50



ale to zapytanie trwa prawie 3 sekundy i dodatkowo "wiesza się" przy większej liczbie kategorii (ponad 10 kategorii).

Struktura tabel:
PRODUCTS:
  1. CREATE TABLE IF NOT EXISTS `products` (
  2. `productID` int(11) NOT NULL AUTO_INCREMENT,
  3. `prod_type` smallint(2) DEFAULT NULL,
  4. `prod_title` varchar(100) NOT NULL DEFAULT '',
  5. `prod_desc` text NOT NULL,
  6. `prod_distributor` int(8) NOT NULL,
  7. `prod_producent` varchar(40) DEFAULT NULL,
  8. `prod_url` varchar(300) NOT NULL DEFAULT '',
  9. `prod_iconS` varchar(100) NOT NULL DEFAULT '',
  10. `prod_iconB` varchar(100) NOT NULL DEFAULT '',
  11. `prod_price` decimal(20,2) NOT NULL DEFAULT '0.00',
  12. `prod_default_price` decimal(20,2) NOT NULL,
  13. `prod_currency` varchar(5) NOT NULL,
  14. `prod_colors` text,
  15. `prod_external` text,
  16. `prod_date_pub` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  17. `prod_visible` enum('yes','no') NOT NULL DEFAULT 'yes',
  18. `prod_status` enum('normal','promo') NOT NULL DEFAULT 'normal',
  19. `prod_rating` enum('yes','no') NOT NULL DEFAULT 'yes',
  20. `prod_approved` enum('yes','no') NOT NULL,
  21. `prod_comments` enum('yes','no','logged_in') NOT NULL DEFAULT 'no',
  22. `prod_cdn` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0=do wgrania',
  23. PRIMARY KEY (`productID`),
  24. KEY `prod_distributor` (`prod_distributor`)
  25. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4764 ;


PRODUCTS_GALLERY:
  1. CREATE TABLE IF NOT EXISTS `products_gallery` (
  2. `prod_photo_id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. `prod_color` text NOT NULL,
  4. `prod_photo_filename` varchar(50) DEFAULT NULL,
  5. `prod_photo_thmb` varchar(50) DEFAULT NULL,
  6. `prod_photo_transp` varchar(50) NOT NULL,
  7. `prod_photo_desc` text,
  8. `prod_productID` int(8) UNSIGNED NOT NULL,
  9. `prod_photo_q` int(2) NOT NULL DEFAULT '5' COMMENT '0 - the best',
  10. `prod_photo_order` float DEFAULT '0',
  11. `prod_photo_cdn` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0=do wgrania',
  12. PRIMARY KEY (`prod_photo_id`)
  13. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4957 ;


PRODUCTS_CATEGORIES:
  1. CREATE TABLE IF NOT EXISTS `project_categories` (
  2. `catID` int(5) UNSIGNED NOT NULL,
  3. `proID` int(8) UNSIGNED NOT NULL,
  4. KEY `catID` (`catID`),
  5. KEY `proID` (`proID`)
  6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Jakieś propozycje?
bpskiba
To zapytanie wygląda dobrze.
Problem polega na ilości przesyłanych danych. Samo zapytanie zapewne trwa krótko, ale przesłanie wielu obrazków do aplikacji trwa długo z uwagi na ilość danych i tego nie zmienisz.

Rady: mniej obrazków, ajax, obrazki gorszej jakości...
maly_swd
Klucze sa? Daj explaina z tego zapytania i pokaz strukture bazy
Pilsener
Cytat
To zapytanie wygląda dobrze.
- na pewno mamy na myśli to samo zapytanie? thumbsdownsmileyanim.gif

  1. FROM products AS p, products_categories AS pc, products_gallery AS pg


Iloczyn kartezjański tabel rzadko kiedy bywa wydajny... jeśli masz 3 tabele po 10 rekordów to tak, jakbyś pobierał dane z jednej tabeli 1000 rekordów.

Praktykuje się JOINy i podzapytania.
o_d
zaktualizowałem opis o strukturę tabelek. Co można z tym zrobić? Proszę o pomoc.
alegorn
pilsner:: nie jest to iloczyn kartezjanski, nie potrzeba pisac slowa join by okreslic relacje miedzy tabelami


o_d:: pokaz nam explaina, wtedy bedzie mozna wiecej cos powiedziec.


poza tym - sprawdz co nam tutaj pokazales

p.productID=pc.productID
p.productID=pg.prod_productID

gdzie:
products AS p,
products_categories AS pc,
products_gallery AS pg

przy czym w tabeli products_categories nie ma takiego pola. wiec jesli jest tak jak piszesz - to nie moze dzialac.

brak kluczy na polach ktore laczysz :
products_gallery.prod_productID << tutaj index da ci znaczny wzrost wydajnosci.


wiecej moglbym powiedziec gdy poprawisz/odpowiesz/wkleisz explaina

pytanie, czy uzywasz do czegokolwiek klucza catID ?
Pilsener
Cytat
Chce pobrać wszystkie grafiki produktów, informacje o produkcie z listy produktó∑, któ®e należą do pewnej grupy kategorii.


Zacznijmy od grup kategorii, czyli od początku - stwórz zapytanie, które pobierze ID produktów należących do określonych grup:
  1. SELECT proID FROM products_categories WHERE grupa=? #tutaj Twoje warunki


Teraz trzeba użyć tych ID by pobrać produkty:
  1. SELECT *
  2. FROM
  3. products
  4. WHERE products.productId IN (#tutaj wsadź zapytanie pobierające ID produktów z tabeli z kategoriami)


Teraz trzeba pobrać grafiki:
  1. SELECT products.*,group_concat(products_gallery.prod_photo_filename) AS photos
  2. FROM
  3. products
  4. LEFT JOIN products_gallery ON products_gallery.ID_PRODUKTU = products.productId
  5. WHERE products.productId IN (#tutaj wsadź zapytanie pobierające ID produktów z tabeli z kategoriami)


Tak to widzę na podstawie tego, co napisałeś. Poeksperymentuj z tą strukturą, dodaj indeksy na pola po których szukasz i łączych tabele a powinno śmigać.
o_d
Cytat


Faktycznie podałem niepoprawnąstruktuę tabeli. Oto właściwa:
  1. CREATE TABLE IF NOT EXISTS `products_categories` (
  2. `catID` int(5) UNSIGNED NOT NULL,
  3. `productID` int(8) UNSIGNED NOT NULL
  4. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


Zapytanie działa.

Oto co zwraca mi explain:

Kod
id     select_type     table     type     possible_keys     key     key_len     ref                     rows             Extra
1     SIMPLE         pc         ALL         NULL            NULL        NULL    NULL                    4854     Using where; Using temporary; Using filesort
1     SIMPLE         pg         ALL         NULL            NULL        NULL    NULL                    4911     Using join buffer
1     SIMPLE         p         eq_ref     PRIMARY         PRIMARY         4     fancydot2.pc.productID     1     Using where

bpskiba
Explain wskazuje na brak wykorzystania indeksów podczas wykonywania zapytania. Czyli musisz eksperymentować z indeksami
To jest główny problem.
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.