![]() |
![]() |
![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 229 Pomógł: 34 Dołączył: 7.12.2008 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Witam,
mam problem natury algorytmicznej. Piszę aktualnie skrypt, w którym użytkownicy się zapisać do poszczególnych kanałów, a w tych z kolei pojawiają się co jakiś czas systemowe wiadomości. Wiadomości wyświetlają się w sidebarze, ale przy dopisaniu się do kanału można wybrać również opcję wysyłania wiadomości mailem. Dostępne są możliwości wysyłki natychmiastowej, raportu raz w tygodniu, albo brak e-maili. Nie ma problemu z wysyłką natychmiastową i brakiem e-maili. Zaciąłem się jednak przy wysyłce maili raz na tydzień. Jak wiadomo różni użytkownicy mogą się zapisać do różnych kanałów, a więc każdy dostanie inne wiadomości w swoim mailu. Moje pytanie więc, jak pobrać te dane z bazy? Schemat jest następujący: user: - id channel - id - name message: - id - title - content - channel_id channel_user: - id - channel_id - user_id Można oczywiście pobrać najpierw użytkowników, a później dla każdego usera w pętli for pobrać odpowiednie wiadomości. Nie chciałbym jednak robić tego w ten sposób. Macie może jakieś inne pomysły? Pozdrawiam Marcin |
|
|
![]() |
![]()
Post
#2
|
|
Grupa: Moderatorzy Postów: 4 362 Pomógł: 714 Dołączył: 12.02.2009 Skąd: Jak się położę tak leżę :D ![]() |
Order by najpierw po u.id. Będziesz wysyłał do jednego usera X maili, gdzie X to liczba kanałów do jakich się zapisał? To się załatwia jednym mailem zbierającym wszystkie kategorie wiadomości stąd struktura początkowa jaką podałem jest taka a nie inna... To do usera są przyporządkowane kanały, a nie na odwrót. Stąd wydzieliłem jako dwie osobne struktury user-kanał i kanał-wiadomości. Taki podział sprawia, że w mailu w pętli wybieram usera i sprawdzam jakie kanały subskrybował. Wtedy ze struktury kanałów wybieram przypisane do tegoż kanału wiadomości. Poza tym po stronie PHP mam więcej do kontroli w Twoim wariancie, ponieważ muszę kontrolować strukturę userów oraz kategorii. Bo przecież nie wrzucam tego jak leci, ale muszę to jakoś sensownie opakować. To co podałeś ma sens gdy maila tworzymy "in-line", mieszając php z html. Jeśli już myślisz o sensownej strukturze obiektowej, to przecież do widoku nie wyślesz tego co podałeś, bo widok dostanie mnóstwo nadmiarowej informacji, którą jeszcze będzie musiał obrabiać. Inna sprawa, że wrzucanie warunku łączenia do where jest najgorszym możliwym rozwiązaniem. Robisz bowiem najpierw iloczyn kartezjański wszystkich możliwości, które potem redukujesz warunkiem.
EDIT: zulu ma rację... To co Ty proponujesz Wykrywacz to identyczne rozwiązanie z tym co opisałem w swoim pierwszym poście. Jednak to można optymalizować. I wariant optymalizacyjny podałem w swoim kolejnym poście. Liczba zwróconych rekordów zmniejsza Ci się wielokrotnie. Inna sprawa polega na tym, że skrypt w Podanym przez Ciebie i mój pierwszy wariant są bezsensowne na hostingu, gdzie są limity. 30 sekund czasu skryptu + limit maili na godzinę wymusza porcjowanie wyników. To się robi poprzez wrzucenie do zapytania LIMIT, a jak rozpoznasz kiedy go włożyć? Nie wiesz bowiem ile rekordów należy pobrać by nie podzieliło nam w połowie kategorii danego usera czy maili. Może się zdarzyć tak bowiem, że wybrany limit wybierze tylko 4 wiadomości z pierwszej kategorii jakiegoś usera, zaś reszta poszła by drugim w kolejnym porcjowaniu. Bezpieczniej zrobić... Grupowanie kategorii po userze i group_concat numeru kanału lub jego nazwy (IMG:style_emoticons/default/smile.gif) Mamy redukcję rekordów poprzez pominięcie niepotrzebnych w takiej sytuacji łączeń. Otrzymujemy zamiast user x kategoria x 10 rekordów w najbardziej i najlepiej optymalizowanym przypadku user + unikalne_kategorie x 10 (IMG:style_emoticons/default/smile.gif) Wrzućmy liczby... 1500 userów, 10 kategorii, z których średnio liczac userzy wybierają po 2. Wariant1: (uśredniłem tu tę dwójkę) 1500 x 2 x 10 = 30000 rekordów Wariant2: (pójdę najmniej korzystnym wariantem, czyli unikalne kategorie stworzą wybranie wszystkich możliwych, a więc 10) 1500 + 10 x 10 = 1600 W przypadku gdy userzy zaczną wybierać po kilka kategorii, nie ząś tylko 2 masz do obrobienia w pętlach 15000 x uśredniona_liczba_kategorii_na_użytkownika dla wariantu1. W wariancie2 nawet zwiększenie liczby wiadomości do z 10 do 20 sprawi śmiesznie niskie zwiększenie liczby operacji (ze 100 do 200). By ilość przekroczyła 3000 rekordów obrabianych musielibyśmy zwiększyć przykładowo liczbę kategorii do 30, a liczbę wiadomości do 50 na kategorię lub 30 wiadomości przy pełnym wykorzystaniu 50 kategorii. To zaś jest niemal nierealne. Przy tych zmienionych parametrach wariant1 obrabiał by już setki tysięcy rekordów. To jest potęga dobrze przemyślanego algorytmu pod kątem wydajnościowym (IMG:style_emoticons/default/smile.gif) W pierwszym przypadku na php jest duży nacisk przy selekcji tego na userów oraz kategorie oraz mamy możliwość wysłania maili kilku do jednego usera przy porcjowaniu danych. W drugim przypadku na php też jest nacisk przy obróbce danych, ale ilość przebiegów pętli jest znacząco zredukowana i całość jest odporna na stosowanie LIMIT (jeśli zastosujemy grupowanie). Trochę inne będą operacje po stronie php też. Zamiast pętli pojawi się kilka operacji na tablicach. |
|
|
![]() ![]() |
![]() |
Aktualny czas: 7.10.2025 - 22:33 |