Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [MySQL][PHP]Architektura rozbudowanego drzewa kategorii a szybkość odpowiedzi z DB
JamalBIG
post
Post #1





Grupa: Zarejestrowani
Postów: 496
Pomógł: 1
Dołączył: 16.01.2008
Skąd: Świnoujście

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


Witam

W jaki sposób rozwiązać problem rozbudowanego drzewa kategorii w skrypcie tak aby zapytania do DB nie trwały zbyt długo i same zapytania były krótkie? Np. serwis allegro ma bardzo rozbudowane drzewo kategorii a mimo tego całość działa płynnie.
Obecnie mam to rozwiązanie dość abstrakcyjnie przez co przy rozbudowanym drzewie kategorii zapytanie trwa bardzo długo.

Obecna struktura tabeli:
id | nazwa | lewa_id | poziom | pozycja | lista
lewa_id - id kategorii nadrzędnej;
poziom - poziom zagłębienia kategorii;
pozycja - pozycja do sortowania przy wyświetlaniu;
lista - lista wszystkich podległych kategorii (np. 23,31,75);

Z góry dzięki za propozycje rozwiązań
Pozdrawiam
Go to the top of the page
+Quote Post
b4rt3kk
post
Post #2





Grupa: Zarejestrowani
Postów: 1 933
Pomógł: 460
Dołączył: 2.04.2010
Skąd: Lublin

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


Cytat(JamalBIG @ 23.03.2015, 15:08:18 ) *
Witam

W jaki sposób rozwiązać problem rozbudowanego drzewa kategorii w skrypcie tak aby zapytania do DB nie trwały zbyt długo i same zapytania były krótkie? Np. serwis allegro ma bardzo rozbudowane drzewo kategorii a mimo tego całość działa płynnie.
Obecnie mam to rozwiązanie dość abstrakcyjnie przez co przy rozbudowanym drzewie kategorii zapytanie trwa bardzo długo.

Obecna struktura tabeli:
id | nazwa | lewa_id | poziom | pozycja | lista
lewa_id - id kategorii nadrzędnej;
poziom - poziom zagłębienia kategorii;
pozycja - pozycja do sortowania przy wyświetlaniu;
lista - lista wszystkich podległych kategorii (np. 23,31,75);

Z góry dzięki za propozycje rozwiązań
Pozdrawiam


To zależy od tego, czy musisz mieć naraz rozwinięte wszystkie kategorie, czy np. dopiero po kliknięciu na daną kategorię. W drugim przypadku sprawa będzie prostsza.
Go to the top of the page
+Quote Post
Forti
post
Post #3





Grupa: Zarejestrowani
Postów: 655
Pomógł: 73
Dołączył: 2.05.2014

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


Category

- id
- title
- parent_id
- level
- root

i teraz masz tak:

- telefony (1, telefony, null, 1, 1)
-- lg (2, lg, 1, 2, 1)
--- coś_tam (5, coś_tam, 2, 3, 1)
-- samsung (3, samsung, 1, 2, 1)
-- sony (4, sony, 1, 2, 1)

- inna (6, inna, null, 1, 2)
itp.

Powinieneś załapać z czasem, Jest jeszcze left | right, ale to już "wyższa szkoła jazdy"

Za kwestie zapytań odpowiada optymalizacja kodu, bazy, indexy a w przypadku np. allegro ilość serwerów (IMG:style_emoticons/default/wink.gif)
Go to the top of the page
+Quote Post
Pyton_000
post
Post #4





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


nested set
Go to the top of the page
+Quote Post
b4rt3kk
post
Post #5





Grupa: Zarejestrowani
Postów: 1 933
Pomógł: 460
Dołączył: 2.04.2010
Skąd: Lublin

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


Aha, polecałbym jeszcze cache. Drzewo kategorii to nie jest coś co często się zmienia.
Go to the top of the page
+Quote Post
JamalBIG
post
Post #6





Grupa: Zarejestrowani
Postów: 496
Pomógł: 1
Dołączył: 16.01.2008
Skąd: Świnoujście

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


Samo wyświtlanie drzewa działa ok, bo wyświetlane są tylko dwa 'poziomy' czyli kategorie i podkategorie ale w jaki sposób 'sklecić' zapytanie do DB aby wyświetlić wszystkie treści które zostały przyporządkowane do kategorii najniższego rzędu - np. w kategorii 'Telefony' mam 200 podkategorii do których jest możliwe dodanie 'treści' - czy zapytanie musi wyglądać tak:
  1. SELECT * FROM ...... WHERE cat_id IN(1,2,3,4,5....., 200)

W takim przypadku zapytanie jest tak długie, że 'serwer się gotuje'
Go to the top of the page
+Quote Post
Forti
post
Post #7





Grupa: Zarejestrowani
Postów: 655
Pomógł: 73
Dołączył: 2.05.2014

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


Masz źle zbudowane baze. Nie masz mieć mole "children" tylko pole "parent" i potem zapytaniem pobierasz wszystkie kategorie które mają parent = ? lub jedno zapytanie o kategorie główne, czyli np. parent = null i leftjoin parent = :id. Rozumiesz? ;>
Go to the top of the page
+Quote Post
b4rt3kk
post
Post #8





Grupa: Zarejestrowani
Postów: 1 933
Pomógł: 460
Dołączył: 2.04.2010
Skąd: Lublin

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


Cytat(JamalBIG @ 23.03.2015, 15:42:55 ) *
Samo wyświtlanie drzewa działa ok, bo wyświetlane są tylko dwa 'poziomy' czyli kategorie i podkategorie ale w jaki sposób 'sklecić' zapytanie do DB aby wyświetlić wszystkie treści które zostały przyporządkowane do kategorii najniższego rzędu - np. w kategorii 'Telefony' mam 200 podkategorii do których jest możliwe dodanie 'treści' - czy zapytanie musi wyglądać tak:
  1. SELECT * FROM ...... WHERE cat_id IN(1,2,3,4,5....., 200)

W takim przypadku zapytanie jest tak długie, że 'serwer się gotuje'


Dodaj LIMIT i paginator.
Go to the top of the page
+Quote Post
JamalBIG
post
Post #9





Grupa: Zarejestrowani
Postów: 496
Pomógł: 1
Dołączył: 16.01.2008
Skąd: Świnoujście

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


Cytat(Forti @ 23.03.2015, 15:56:47 ) *
Masz źle zbudowane baze. Nie masz mieć mole "children" tylko pole "parent" i potem zapytaniem pobierasz wszystkie kategorie które mają parent = ? lub jedno zapytanie o kategorie główne, czyli np. parent = null i leftjoin parent = :id. Rozumiesz? ;>

Możesz podać to na przykładzie? Z paginatorem i limitem bez zmian bo chyba problem leży w długości zapytania do DB...
Go to the top of the page
+Quote Post
Pyton_000
post
Post #10





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


Czy ktoś mnie w ogóle słucha? Do dużych drzew w których modyfikacja jest rzadka a bardzo dużo odczytów najlepiej nadaje się nested set, bo jednym zapytaniem można pobierać różne cuda i to bez skomplikowanych zapytań. Jest trudna w ogólnej obsłudze (dodawanie, usuwanie itp.) ale już wybieranie kategorii jest banalnie proste.
Go to the top of the page
+Quote Post
Forti
post
Post #11





Grupa: Zarejestrowani
Postów: 655
Pomógł: 73
Dołączył: 2.05.2014

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


Co rozumiesz przez duże drzewo? Używałem doctrine tree dla 1800 kategorii z 6 level i bylo to wyciąganie armat na wróbla:P Mysle ze kolega ma mniejsze drzewo
Go to the top of the page
+Quote Post
JamalBIG
post
Post #12





Grupa: Zarejestrowani
Postów: 496
Pomógł: 1
Dołączył: 16.01.2008
Skąd: Świnoujście

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


Cytat(Forti @ 23.03.2015, 18:12:15 ) *
Co rozumiesz przez duże drzewo? Używałem doctrine tree dla 1800 kategorii z 6 level i bylo to wyciąganie armat na wróbla:P Mysle ze kolega ma mniejsze drzewo

Chętnie wyciągnę armaty, biorę pod uwagę najgorsze warianty czli kilka/kilkadziesiąt kategorii i kilka/kilkanaście leveli. Tak jak pisałem, sama obsługa kategorii i tabeli z nimi nie jest problemem, problem jest z zapytaniem do DB kiedy chce wywołać treści przyporządkowane do kategorii ostatniego levelu
Go to the top of the page
+Quote Post
Forti
post
Post #13





Grupa: Zarejestrowani
Postów: 655
Pomógł: 73
Dołączył: 2.05.2014

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


Robisz to zle. Zamiast pobierać IN() itp. To może lepiej pobierz całość i zmapuj w php w pętlach Itp. Po za tym co rozumiesz przez długie zapytania? Samo in() nie jest niczym wolnym czy cos. Leftjoin tak samo. Chcesz optymalizować a mówisz ze chetnie wyciągniesz armaty...
Go to the top of the page
+Quote Post
JamalBIG
post
Post #14





Grupa: Zarejestrowani
Postów: 496
Pomógł: 1
Dołączył: 16.01.2008
Skąd: Świnoujście

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


Cytat(Forti @ 23.03.2015, 21:01:27 ) *
Robisz to zle. Zamiast pobierać IN() itp. To może lepiej pobierz całość i zmapuj w php w pętlach Itp. Po za tym co rozumiesz przez długie zapytania? Samo in() nie jest niczym wolnym czy cos. Leftjoin tak samo. Chcesz optymalizować a mówisz ze chetnie wyciągniesz armaty...

To może źle zrozumiałem 'armaty' (IMG:style_emoticons/default/wink.gif)
Pobieranie całości nie wiem czy jest dobrym pomysłem jeżeli będzie tam kilka tysięcy wpisów przykorządkowanych do konkretnych kategorii...
Go to the top of the page
+Quote Post
b4rt3kk
post
Post #15





Grupa: Zarejestrowani
Postów: 1 933
Pomógł: 460
Dołączył: 2.04.2010
Skąd: Lublin

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


Cytat(JamalBIG @ 23.03.2015, 21:06:43 ) *
To może źle zrozumiałem 'armaty' (IMG:style_emoticons/default/wink.gif)
Pobieranie całości nie wiem czy jest dobrym pomysłem jeżeli będzie tam kilka tysięcy wpisów przykorządkowanych do konkretnych kategorii...


Pobieranie całości to najgorszy pomysł jaki może być.

Jeśli chodzi o pobieranie wyników dorzuć zwyczajnie zwykłego limita:

  1. SELECT * FROM products WHERE id_cat IN (1,2,20) LIMIT 50 OFFSET 0;


Dobrym pomysłem byłoby też założenie indexu na id_cat.

Gdyby to był postgres mógłbyś też zrobić tabele dziedziczące z warunkiem WITH (no ale niestety nie jest).

Zwróć też uwagę jakie kolumny pobierasz, ogranicz się do minimum, tzn. bierz tylko te, które potrzebujesz. Jeśli np. w którejś przechowujesz spory blok tekstu lub nawet obrazek to wiadomo, że pobranie zawartości musi zająć dłuższą chwilę. Więc zamiast SELECT *, zastosuj SELECT col1, col2, itd.
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: 19.09.2025 - 04:57