Filtrowanie produktów – jak popsuć prostą rzecz

Wstęp

Tym razem będzie krótki wpis na temat filtrowania produktów. Ogólnie rzecz biorąc zagadnienie sprowadza się do prostego wpięcia warunków do funkcji pobierającej listę produktów. Powiedzmy, że pobieranie wygląda następująco:

select * from produkty $where order by id desc limit $start, $liczba 

Do $where wstawiamy warunki nałożone na listę produktów. Pisałem o tym sposobie jakiś czas temu: Zaawansowana wyszukiwarka w php i mysql. Skąd jednak wziąć warunki do $where? Przede wszystkim określamy po czym chcemy filtrować listę produktów. Powiedzmy, że interesuje nas producent, stawka vat oraz nazwa. O ile nazwa będzie polem wprowadzanym „z palca”, to producent i vat aż się proszą o listę wyboru. Wiadomo, vat to kilka pozycji, producenci co kilkadziesiąt-kilkaset (chyba, że sklep jest „megafabryką” pokazywaną w NG). Rozsądek podpowiada pobrać dane z tabeli podatku i tabeli producentów. Kto nie słucha głosu rozsądku, ten robi filtrowanie po użytych wartościach uzyskanych na całej tabeli produktów.

Horror

Tak jest proszę państwa 😉 Bierzemy wartość podatku vat z listy produktów połączonych z: promocjami, kategoriami, producentami, tłumaczeniami, opisami, itd. a na koniec grupujemy po id podatku, żeby na liście nie było powtórzeń. Dzięki temu sprytnemu zabiegowi pokazujemy na liście tylko te elementy, które są powiązane z produktami. Przy małej liczbie produktów sposób nie jest aż taki zły. Niestety powyżej 100 różnych produktów zaczyna się robić nieciekawie, a potem jest już tylko gorzej. Na tyle, że każde zapytanie zajmowało od 10 do 30 sekund. Dlatego też takie rozwiązanie nie powinno nigdy być brane pod uwagę, chyba, że koniecznie musicie wykluczyć z listy wartości bez przypisania.

Prawidłowe rozwiązanie z wykluczeniem elementów bez przypisania

Tworzymy tabelę, w której będzie id podatku/id producenta/itp. oraz liczba przypisań. Liczby ustawiamy zgodnie z tym co jest ustawione w produktach. Jeśli dodajemy produkt, to liczba rośnie o 1, jeśli kasujemy produkt, to liczba maleje o 1, a jeśli edytujemy, to w starym elemencie dajemy -1, a w nowym +1. Tak, wymaga to większego nakładu pracy, ale dzięki temu możemy zrobić coś w rodzaju:

select p.* from podatek as p inner join podatek_liczba as pl on pl.id = p.id and pl.liczba > 0

Po wstawieniu indeksu na kolumny (id,liczba) powinniśmy uzyskać using where przy użyciu EXPLAIN na powyższym zapytaniu.

Uwagi końcowe

Nie chciało mi się szperać po kodzie i szukać wszystkich wywołań, które kierowały w to samo miejsce, więc w funkcji zliczającej po prostu wstawiłem przechwycenie zapytania i przy pomocy preg_match określiłem jakie powinno być prawidłowe zapytanie. Strona przestała zawieszać firefoxa na kilka minut, a ze slow-loga zniknęły wpisy kilkunastosekundowe związane z określaniem list filtrowania. W logu pozostała tylko jedna strasząca (i straszna) rzecz: kategorie z liczbą produktów, ale o tym będzie wpis za jakiś czas.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

*