Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Optymalizacja zbyt długiego zapytania SQL
northwest
post 30.12.2014, 10:59:09
Post #1





Grupa: Zarejestrowani
Postów: 788
Pomógł: 1
Dołączył: 17.09.2004

Ostrzeżenie: (10%)
X----


Witam serdecznie,
Mam problem z zapytaniem:
  1.  
  2. SELECT COUNT(id) AS ile FROM produkty WHERE ilosc > 0 AND enable = '1' AND stan = '1' AND ( kategoria = '521115' OR kategoria = '521269' OR kategoria = '522991' OR kategoria = '523008' OR kategoria = '523009' OR kategoria = '523010' OR kategoria = '523025' OR kategoria = '523026' OR kategoria = '523027' OR kategoria = '522993' OR kategoria = '522992' OR kategoria = '522962' OR kategoria = '522963' OR kategoria = '522961' OR kategoria = '522960' OR kategoria = '522959' OR kategoria = '522958' OR kategoria = '521268' OR kategoria = '523011' OR kategoria = '523012' OR kategoria = '523013' OR kategoria = '523022' OR kategoria = '523023' OR kategoria = '523024' OR kategoria = '523029' OR kategoria = '523030' OR kategoria = '523031' OR kategoria = '523032' OR kategoria = '523034' OR kategoria = '523035' OR kategoria = '522929' OR kategoria = '521267' OR kategoria = '522965' OR kategoria = '523014' OR kategoria = '523015' OR kategoria = '523016' OR kategoria = '523017' OR kategoria = '523018' OR kategoria = '523019' OR kategoria = '523020' OR kategoria = '523021' OR kategoria = '523028' OR kategoria = '521266' OR kategoria = '523036' OR kategoria = '522981' OR kategoria = '522946' OR kategoria = '522945' OR kategoria = '522926' OR kategoria = '521265' OR kategoria = '523033' OR kategoria = '522950' OR kategoria = '522949' OR kategoria = '522948' OR kategoria = '522947' OR kategoria = '522944' OR kategoria = '522943' OR kategoria = '522942' OR kategoria = '522941' OR kategoria = '521260' OR kategoria = '522966' OR kategoria = '522967' OR kategoria = '522979' OR kategoria = '522968' OR kategoria = '522957' OR kategoria = '522956' OR kategoria = '522955' OR kategoria = '521259' OR kategoria = '522970' OR kategoria = '522971' OR kategoria = '522972' OR kategoria = '522973' OR kategoria = '522974' OR kategoria = '522975' OR kategoria = '522976' OR kategoria = '522977' OR kategoria = '522969' OR kategoria = '522954' OR kategoria = '522978' OR kategoria = '521257' OR kategoria = '522924' OR kategoria = '522923' OR kategoria = '522922' OR kategoria = '522913' OR kategoria = '522912' OR kategoria = '522911' OR kategoria = '522900' OR kategoria = '521258' OR kategoria = '522921' OR kategoria = '522920' OR kategoria = '522918' OR kategoria = '522919' OR kategoria = '522917' OR kategoria = '522916' OR kategoria = '522915' OR kategoria = '522914' OR kategoria = '522899' OR kategoria = '522898' OR kategoria = '522897' OR kategoria = '522895' OR kategoria = '522896' OR kategoria = '522894' OR kategoria = '522893' OR kategoria = '522892' OR kategoria = '522891' OR kategoria = '522890' OR kategoria = '522889' OR kategoria = '521261' OR kategoria = '522964' OR kategoria = '522909' OR kategoria = '522908' OR kategoria = '522907' OR kategoria = '522906'.....
  3.  


Kiedyś to zapytanie działało poprawnie, jednak od jakiegoś czasu przestało.... Według serwerowni "zapytanie jest zbyt długie i wykonuje się 10 sekund".

Czy ma ktoś może jakiś pomysł jak to zoptymalizować?

Bardzo proszę o pomoc,
Northwest
Go to the top of the page
+Quote Post
Turson
post 30.12.2014, 11:00:51
Post #2





Grupa: Zarejestrowani
Postów: 4 291
Pomógł: 829
Dołączył: 14.02.2009
Skąd: łódź

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


WHERE kategoria IN(1,2,3) itd.
Go to the top of the page
+Quote Post
northwest
post 30.12.2014, 11:03:08
Post #3





Grupa: Zarejestrowani
Postów: 788
Pomógł: 1
Dołączył: 17.09.2004

Ostrzeżenie: (10%)
X----


czyli coś takiego:

  1.  
  2. SELECT COUNT(id) AS ile FROM produkty WHERE ilosc > 0 AND enable = '1' AND stan = '1' AND kategoria IN (521115, 521269, 52299, 523008, 523009, 523025.....)
  3.  


questionmark.gifsmile.gif
Go to the top of the page
+Quote Post
SpiritCode
post 30.12.2014, 11:03:20
Post #4





Grupa: Zarejestrowani
Postów: 167
Pomógł: 35
Dołączył: 29.12.2014
Skąd: Otwock

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


Jak rozumiem to są jakieś wybrane kategorie tak?
Jesli nie zrób SELECT-WHERE=SELECT
Druga opcja to zamienić te wszystkie OR na IN ARRAY

Wtedy zamiast tego nawiasu masz:
  1. kategoria IN ('521115', '521269' [..])


Druga opcja. Jeśli te kategorie są w jakiejś tabeli i spełniają jakiś wspólny warunek możesz zrobić:
  1. kategoria IN (SELECT kolumna FROM tabela WHERE warunek)


Np. te numerki to dajmy na to id z tabeli kategorie i muszą spełniać warunek spelnia = 1
  1. kategoria IN (SELECT id FROM kategorie WHERE spelnia = 1)

Wygodniejsze bo unikasz dodatkowego ręcznego dopisywania jak dojdzie nowa kategoria

Ten post edytował SpiritCode 30.12.2014, 11:07:30
Go to the top of the page
+Quote Post
Turson
post 30.12.2014, 11:06:56
Post #5





Grupa: Zarejestrowani
Postów: 4 291
Pomógł: 829
Dołączył: 14.02.2009
Skąd: łódź

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


Cytat(northwest @ 30.12.2014, 11:03:08 ) *
czyli coś takiego:

  1.  
  2. SELECT COUNT(id) AS ile FROM produkty WHERE ilosc > 0 AND enable = '1' AND stan = '1' AND kategoria IN (521115, 521269, 52299, 523008, 523009, 523025.....)
  3.  


questionmark.gifsmile.gif

Tak. Indeksy na `kategoria` tez mogą pomóc.
Go to the top of the page
+Quote Post
northwest
post 30.12.2014, 11:33:11
Post #6





Grupa: Zarejestrowani
Postów: 788
Pomógł: 1
Dołączył: 17.09.2004

Ostrzeżenie: (10%)
X----


tak, to są numery ID poszczególnych kategorii które wybrał użytkownik....

Przepraszam za głupie pytanie, ale które z powyższych zapytań będzie najbardziej optymalne?;-)

tabela z danymi wygląda tak:


  1. CREATE TABLE IF NOT EXISTS `produkty` (
  2. `f_id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. `nazwa` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  4. `kategoria` bigint(20) DEFAULT NULL,
  5. `cena` double NOT NULL,
  6. `opis` text COLLATE utf8_unicode_ci,
  7. `enable` char(1) COLLATE utf8_unicode_ci NOT NULL,
  8. `ilosc` int(11) NOT NULL,
  9. `stan` int(11) NOT NULL,
  10. UNIQUE KEY `id` (`f_id `),
  11. FULLTEXT KEY `nazwa` (`nazwa`,`dostepnosc`)
  12. ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1057359 ;
Go to the top of the page
+Quote Post
SpiritCode
post 30.12.2014, 11:58:30
Post #7





Grupa: Zarejestrowani
Postów: 167
Pomógł: 35
Dołączył: 29.12.2014
Skąd: Otwock

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


Skoro mówisz, ze to wybrane kategorie przez użytkownika to bez wątpienia metoda IN (id, id, id [..]).

Metodę z drugim select którą Ci przedstawiłem warto używać jeśli masz np. Kategorie podzielone na kilka grup i każda z nich ma swoją grupę zaznaczoną. Wtedy jeśli szukasz kategorii z danej grupy Dajesz tego SELECT'a z warunkiem na grupę i pobierasz tylko te smile.gif
Go to the top of the page
+Quote Post
northwest
post 30.12.2014, 12:34:39
Post #8





Grupa: Zarejestrowani
Postów: 788
Pomógł: 1
Dołączył: 17.09.2004

Ostrzeżenie: (10%)
X----


Dziękuję za pomoc :-)

Mam jeszcze jedno pytanie, tą listę kategorii generuje sobie takim "dzikim" kodem:


  1.  
  2. $sssss = null;
  3. $qwex = null;
  4. $tablicaA = $ms->query_select("SELECT id, title, parent_id FROM drzewko_kategorii WHERE parent_id = '" .($zmienna_z_get) . "';");
  5. if (isset($tablicaA)) {
  6. $sssss .= " kategoria IN (";
  7. foreach ($tablicaA as $wynA => $warttA) {
  8. if ($warttA[parent_id] != "0") {
  9. $qwex = 1;
  10. $sssss .= " $warttA[id] , ";
  11.  
  12. $tablicaA1 = $ms->query_select("SELECT id, title, parent_id FROM drzewko_kategorii WHERE parent_id = '$warttA[id]';");
  13. foreach ($tablicaA1 as $wynA1 => $warttA1) {
  14. $sssss .= " $warttA1[id] , ";
  15.  
  16.  
  17. $tablicaA2 = $ms->query_select("SELECT id, title, parent_id FROM drzewko_kategorii WHERE parent_id = '$warttA1[id]';");
  18. foreach ($tablicaA2 as $wynA2 => $warttA2) {
  19. $sssss .= " $warttA2[id] , ";
  20.  
  21.  
  22. $tablicaA3 = $ms->query_select("SELECT id, title, parent_id FROM drzewko_kategorii WHERE parent_id = '$warttA2[id]';");
  23. foreach ($tablicaA3 as $wynA3 => $warttA3) {
  24. $sssss .= " $warttA3[id] , ";
  25.  
  26.  
  27. $tablicaA4 = $ms->query_select("SELECT id, title, parent_id FROM drzewko_kategorii WHERE parent_id = '$warttA3[id]';");
  28. foreach ($tablicaA4 as $wynA4 => $warttA4) {
  29. $sssss .= " $warttA4[id] , ";
  30.  
  31. $tablicaA5 = $ms->query_select("SELECT id, title, parent_id FROM drzewko_kategorii WHERE parent_id = '$warttA4[id]';");
  32. foreach ($tablicaA5 as $wynA5 => $warttA5) {
  33. $sssss .= " $warttA5[id] , ";
  34.  
  35.  
  36. $tablicaA6 = $ms->query_select("SELECT id, title, parent_id FROM drzewko_kategorii WHERE parent_id = '$warttA5[id]';");
  37. foreach ($tablicaA6 as $wynA6 => $warttA6) {
  38. $sssss .= " $warttA6[id] , ";
  39. }
  40. }
  41. }
  42. }
  43. }
  44. }
  45. }
  46.  



tabela wygląda następująco:
  1.  
  2. CREATE TABLE IF NOT EXISTS `drzewko_kategorii` (
  3. `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  4. `parent_id` bigint(20) UNSIGNED NOT NULL,
  5. `position` bigint(20) UNSIGNED NOT NULL,
  6. `left` bigint(20) UNSIGNED NOT NULL,
  7. `right` bigint(20) UNSIGNED NOT NULL,
  8. `level` bigint(20) UNSIGNED NOT NULL,
  9. `title` text COLLATE utf8_unicode_ci,
  10. `type` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  11. PRIMARY KEY (`id`)
  12. ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=10000 ;
  13.  



Dałoby się to jakoś poprawić?
Przez ten kawałek kodu skrypt mega długo się generuje sad.gif
Go to the top of the page
+Quote Post
SpiritCode
post 30.12.2014, 13:11:46
Post #9





Grupa: Zarejestrowani
Postów: 167
Pomógł: 35
Dołączył: 29.12.2014
Skąd: Otwock

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


Ależ oczywiście wink.gif

Pytanie tylko czy chcesz pobrać wszystkie kategorie w górę czy w dół?
Dzięci czy rodziców?

dla wszystkich rodziców danej kategorii
  1. SELECT a.id, a.title, a.parent_id FROM drzewko_kategorii a,
  2. (SELECT b.id, b.title, b.parent_id FROM drzewko_kategorii b,
  3. (SELECT c.id, c.title, c.parent_id FROM drzewko_kategorii c WHERE c.id = {$id}) AS foo
  4. WHERE b.id = foo.parent_id OR b.id = foo.id)
  5. AS foo2
  6. WHERE a.id = foo2.parent_id OR a.id = foo2.id
  7. GROUP BY a.id


dla wszystkich dzieci:
  1. SELECT a.id, a.title, a.parent_id FROM drzewko_kategorii a,
  2. (SELECT b.id FROM drzewko_kategorii b,
  3. (SELECT id FROM drzewko_kategorii c WHERE c.id = {$id}) AS foo
  4. WHERE b.parent_id = foo.id OR b.id = foo.id )
  5. AS foo2
  6. WHERE a.parent_id = foo2.id OR a.id = foo2.id
  7. GROUP BY a.id


Sprawdź czy działają biggrin.gif zamiast {$id} podajesz id kategorii dla której szukasz kategorii w górę lub w dół

edit: poprawka pierwszego zapytania. Brakło pól

Ten post edytował SpiritCode 30.12.2014, 13:13:29
Go to the top of the page
+Quote Post
northwest
post 30.12.2014, 13:48:18
Post #10





Grupa: Zarejestrowani
Postów: 788
Pomógł: 1
Dołączył: 17.09.2004

Ostrzeżenie: (10%)
X----


dziękuje, działa smile.gif

chociaż chyba jednak nie do końca ;-)

Jeśli jestem na "najwyższym poziomie" danej kategorii - to nie wyświetla produktów (zastosowałem 2 zapytanie)....
Dopiero jak wybiorę jakiś konkretny parent - do której są przyporządkowane produkty - to się pokazują....


Chciałbym żeby w momencie gdy mam coś takiego:
1. kategoria główna
2. podkategoria
3. grupa
4. podgrupa

To po kliknięciu KATEGORIA GŁÓWNA - widzę wszystkie produkty z poziomu 1,2,3,4. Po kliknięciu na GRUPA - widzę produkty z poziomu 3 i 4.... smile.gif

Nie wiem czy jasno to opsiałem?smile.gif
Go to the top of the page
+Quote Post
SpiritCode
post 30.12.2014, 13:51:23
Post #11





Grupa: Zarejestrowani
Postów: 167
Pomógł: 35
Dołączył: 29.12.2014
Skąd: Otwock

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


To łączysz zapytania.
Zaciągnij sobie wszystkie dzieci dla interesującej Cię kategorii. Za pomocą wyciągniętych z nich ID wyszukaj produkty które takie ID mają
Go to the top of the page
+Quote Post
northwest
post 30.12.2014, 13:53:24
Post #12





Grupa: Zarejestrowani
Postów: 788
Pomógł: 1
Dołączył: 17.09.2004

Ostrzeżenie: (10%)
X----


tzn mam zapytanie które generuje mi najpierw te kategoria IN (......) i potem dodaje je to, co wygeneruje się w zapytaniu kategorii do produktów:
select * from produkty where enable = 1 and kategoriaIN(....) i właśnie na najwyższym poziomie nie wyświetla mi produktów - tylko na niższych... smile.gif
Go to the top of the page
+Quote Post
SpiritCode
post 30.12.2014, 14:00:34
Post #13





Grupa: Zarejestrowani
Postów: 167
Pomógł: 35
Dołączył: 29.12.2014
Skąd: Otwock

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


Nie no zapytania które Ci podałem zwracają Ci kategorie od tych co podałeś w dół oraz w górę, łącznie z tą wybrana kategorią smile.gif

edit: czyli tak biggrin.gif ale to mam rozumieć, że nie chcesz wyświetlać produktów z tych kategorii których szukasz dzieci lub rodziców?

Ten post edytował SpiritCode 30.12.2014, 14:02:46
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: 13.06.2024 - 11:49