Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Zapytanie z 3 tabel - optymalizacja
o_d
post 31.05.2012, 15:10:16
Post #1





Grupa: Zarejestrowani
Postów: 11
Pomógł: 0
Dołączył: 7.12.2007

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


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?

Ten post edytował o_d 1.06.2012, 10:35:59
Go to the top of the page
+Quote Post
bpskiba
post 31.05.2012, 15:44:14
Post #2





Grupa: Zarejestrowani
Postów: 340
Pomógł: 49
Dołączył: 3.07.2009
Skąd: Rzeszów

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


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...

Ten post edytował bpskiba 31.05.2012, 15:45:22
Go to the top of the page
+Quote Post
maly_swd
post 31.05.2012, 16:52:29
Post #3





Grupa: Zarejestrowani
Postów: 744
Pomógł: 118
Dołączył: 14.02.2009
Skąd: poziome

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


Klucze sa? Daj explaina z tego zapytania i pokaz strukture bazy

Ten post edytował maly_swd 31.05.2012, 16:52:45


--------------------
śmieszne obrazki
Kryzys: Ser jem spleśniały, wino piję stare i samochód mam bez dachu..
Go to the top of the page
+Quote Post
Pilsener
post 31.05.2012, 22:49:27
Post #4





Grupa: Zarejestrowani
Postów: 1 590
Pomógł: 185
Dołączył: 19.04.2006
Skąd: Gdańsk

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


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.
Go to the top of the page
+Quote Post
o_d
post 1.06.2012, 10:36:53
Post #5





Grupa: Zarejestrowani
Postów: 11
Pomógł: 0
Dołączył: 7.12.2007

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


zaktualizowałem opis o strukturę tabelek. Co można z tym zrobić? Proszę o pomoc.
Go to the top of the page
+Quote Post
alegorn
post 1.06.2012, 12:00:09
Post #6





Grupa: Zarejestrowani
Postów: 341
Pomógł: 40
Dołączył: 23.06.2009

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


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 ?
Go to the top of the page
+Quote Post
Pilsener
post 1.06.2012, 14:23:10
Post #7





Grupa: Zarejestrowani
Postów: 1 590
Pomógł: 185
Dołączył: 19.04.2006
Skąd: Gdańsk

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


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ć.
Go to the top of the page
+Quote Post
o_d
post 1.06.2012, 14:23:23
Post #8





Grupa: Zarejestrowani
Postów: 11
Pomógł: 0
Dołączył: 7.12.2007

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


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

Go to the top of the page
+Quote Post
bpskiba
post 1.06.2012, 21:14:15
Post #9





Grupa: Zarejestrowani
Postów: 340
Pomógł: 49
Dołączył: 3.07.2009
Skąd: Rzeszów

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


Explain wskazuje na brak wykorzystania indeksów podczas wykonywania zapytania. Czyli musisz eksperymentować z indeksami
To jest główny problem.

Ten post edytował bpskiba 1.06.2012, 21:25:43
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: 12.06.2025 - 12:52