Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Problem z zapytaniem i brak pomysłu na jego optymalizacje...
sniver
post
Post #1





Grupa: Zarejestrowani
Postów: 159
Pomógł: 5
Dołączył: 31.08.2007

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


Najchętniej to w takim momentach był zrobił to: (IMG:style_emoticons/default/sciana.gif)

Mam zapytanie i baze, niby wszystko ok, ale wykonuje sie troche długo bo baza produktów troche w EroBAY urosła...

Zapytanie jest z wyszukiwarki, a konkretnie przyporządkowuje kategorie produktów względem znalezionych w bazie danych...

Oto query:

  1. SELECT
  2. `c`.`CAT_Id` AS `id`,
  3. `c`.`PARENT_Id` AS `parent`,
  4. `c`.`CAT_Name` AS `name`,
  5. `c`.`CAT_Url` AS `url`,
  6. (
  7. SELECT
  8. COUNT(1)
  9. FROM
  10. `products` AS `p`
  11. JOIN `productsdescription` AS `pd` ON (`pd`.`PRD_Id` = `p`.`PRD_Id`)
  12. WHERE
  13. (`p`.`CAT_Id` IN (
  14. SELECT
  15. `c2`.`CAT_Id`
  16. FROM
  17. `categories` AS `c2`
  18. WHERE
  19. (
  20. (`c2`.`CAT_Id` = `c`.`CAT_Id`)
  21. OR (`c2`.`CAT_Ip` LIKE CONCAT(`c`.`CAT_Id`,'.%'))
  22. )
  23. AND (
  24. (`c2`.`CAT_Active` = 1)
  25. AND (`c2`.`CAT_Counter` > 0)
  26. )
  27. )
  28. )
  29. AND (MATCH(`pd`.`PRD_Name`, `pd`.`PRD_Description`) AGAINST ('kostium' IN BOOLEAN MODE))
  30. ) AS `licznik`
  31.  
  32. FROM
  33. `categories` AS `c`
  34.  
  35. WHERE
  36. (
  37. (`c`.`CAT_Active` = 1)
  38. AND (`c`.`CAT_Counter` > 0)
  39. )
  40. AND (
  41. (`c`.`CAT_Id` = 61)
  42. OR (`c`.`PARENT_Id` = 61)
  43. OR (`c`.`CAT_Ip` LIKE CONCAT(`c`.`CAT_Id`,'.%'))
  44. OR (`c`.`PARENT_Id` = 3)
  45. )
  46.  
  47. GROUP BY `c`.`CAT_Id`
  48.  
  49. HAVING
  50. (`licznik` > 0)
  51.  
  52. ORDER BY `c`.`PARENT_Id` ASC, `c`.`CAT_Sort` ASC


Problem znajduje się w subzapytaniu zwracającym wartość licznik, a konkretnie w kolejnym zagnierzdzeniu które wpisuje do IN podkategorie..

Może ktoś ma jakiś fajny pomysł jak to ugryźć...
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 4)
Noidea
post
Post #2





Grupa: Zarejestrowani
Postów: 226
Pomógł: 61
Dołączył: 20.08.2010

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


Z tego co widzę to drzewko kategorii jest zrobione w "sprytny" sposób przez zapisanie ID w stringu ( "2.34.232.3422" ). Nazwanie kolumny CAT_Ip i oddzielanie liczb kropkami nie sprawia, że rozwiązanie jest bardziej profesjonalne, równie dobrze można oddzielać je przecinkami.
Taką strukturę stosują ludzie, którym bardziej zależy na łatwości zapisania zapytania ( WHERE ip LIKE id + '.%' ) niż na wydajności - czyli masz to co chciałeś (IMG:style_emoticons/default/smile.gif)

Najlepsze rozwiązanie to google -> mysql category tree, przeanalizować kilka rozwiązań, wybrać najlepsze, przerobić strukturę bazy.


Rozwiązania doraźne:
Widzę, że w podzapytaniu zakładasz, że CAT_Id jest zawsze na początku CAT_Ip. Może da się to wykorzystać, wstawić jakąś dodatkową kolumnę do tabeli categories z powtórzonymi danymi, zamienić skorelowane podzapytanie na JOINa, cokolwiek. Tylko najpierw muszę wiedzieć co jest w kolumnie CAT_Ip. A dokładnie to ID której kategorii jest na samym początku.
Go to the top of the page
+Quote Post
sniver
post
Post #3





Grupa: Zarejestrowani
Postów: 159
Pomógł: 5
Dołączył: 31.08.2007

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


CAT_Ip to tz. IP kategorii :-)
w takim formacie jak to napisałeś ;>

właśnie pomyślałem o tym że do każdej kategorii mogę dodać pole (jak wspomniałeś) i tam zapisać wszystkie dzieci i dzieci, dzieci jakiejś kategorii

Przeanalizowałem kilka metod na robienie drzewa IP. Powyższa metoda została wykorzystana na www.erobay.pl - więc wiadome do czego to ma być.
W/g waszego doświadczenia jaka struktura drzewa kategorii może być najbardziej optymalna?

Ten post edytował sniver 29.09.2010, 11:28:00
Go to the top of the page
+Quote Post
Pilsener
post
Post #4





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

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


Cytat
Taką strukturę stosują ludzie, którym bardziej zależy na łatwości zapisania zapytania ( WHERE ip LIKE id + '.%' ) niż na wydajności
- nie sądzę. Pokaż mi bardziej wydajną metodę pozwalającą pobierać, przenosić, usuwać wybrane gałęzie. Poza tym pola "IP" czy depth dodawane są pomocniczo właśnie w tym celu.

Proponuję zrobić explain i utworzyć odpowiednie indeksy, powinno pomóc. Jeżeli problemem jest rozmiar drzewa to można je podzielić na kilka mniejszych.

P.S. > Możesz też poeksperymentować z modelem nested set, ale jak patrzę na te pętle w zapytaniach to nie wiem, czy to będzie wygodne i wydajne...
Go to the top of the page
+Quote Post
sniver
post
Post #5





Grupa: Zarejestrowani
Postów: 159
Pomógł: 5
Dołączył: 31.08.2007

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


Dodałem dodatkowe pole. Pole o dzwięcznej nazwie "Collection" - a konkretnie CAT_Collection, czyli zbiór :-)

Każda z kategorii ma swoje dzieci (a dzieci mają dzieci). System każdorazowo musi odpytywać bazę o to które to dzieci należą do danej kategorii, w tym fragmencie:

  1. [...]
  2. (`p`.`CAT_Id` IN (
  3. SELECT
  4. `c2`.`CAT_Id`
  5. FROM
  6. `categories` AS `c2`
  7. WHERE
  8. (
  9. (`c2`.`CAT_Id` = `c`.`CAT_Id`)
  10. OR (`c2`.`CAT_Ip` LIKE CONCAT(`c`.`CAT_Id`,'.%'))
  11. )
  12. AND (
  13. (`c2`.`CAT_Active` = 1)
  14. AND (`c2`.`CAT_Counter` > 0)
  15. )
  16. )
  17. )
  18.  
  19. [...]


Powyższe rozwiązanie zamieniłem na dodanie informacji o spisie kategorii do pola: 'CAT_Collection', a w nim informacje w stylu 5, 94, 115, 116

Teraz gotowy zbiór potomków wpisuję do tego warunku i wygląda tak: (`p`.`CAT_Id` IN (`c`.`CAT_Collection`)) - różnica w działaniu? Piorunująca :]
Czy to dobre czy nie - dam znać za tydzień jak przybędzie odwiedzających i baza produktów sie zwiększy na EroBAY.pl :-)

Ten post edytował sniver 1.10.2010, 12:20:30
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 24.08.2025 - 12:54