![]() |
![]() |
![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 73 Pomógł: 0 Dołączył: 13.02.2006 Skąd: Warszawa Ostrzeżenie: (0%) ![]() ![]() |
Witam,
Jestem bardziej programistą Javy, jak PHP, dlatego nie jest pewien jaki sposób pisania kodu jest najbardziej wydajny. Załóżmy, że mam obiekt komentarz, który w konstruktorze łączy się z bazą danych i pobiera z niej wszystkie wartości odnośnie danego komentarza, typu np. id_komentarz, tresc, autor no i id_artykul, czy id artykulu w bazie do którgo komentarz się odnosi. I teraz, aby wydajnie pobierać dalsze informację odnośnie tego artykułu z poziomu klasy komentarz, mam jako pole pustą zmienną, która jest inicjalizowana raz, kiedy na obiekcie pola komentarz wywoła się metoda chcąca pobrać dodatkowe info odnośnie komentarza, np. getArticleTitle();. Inicjalizacja czyli wywołanie konstruktora z parametrem id, który łączy się z bazą danych i pobiera dane artykułu. Zastanawiam się tylko, czy to jest dobre rozwiązanie pod względem wydajności i bezpieczeństwa. Dzięki za wszelkie opinie |
|
|
![]() |
![]()
Post
#2
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
1. Takiej metody jak Comment::getArticleTitle() w ogóle nie powinno* być. Możesz utworzyć Comment::getArticle(), która zwróci obiekt artykułu powiązanego z danym komentarzem, a ten z kolei może udostępniać metodę Article::getTitle().
2. Generalnie próbujesz utworzyć ORMa - może warto by zapoznać się z już istniejącymi? Doctrine2 czerpie garściami z Hibernate, którego może już znasz - nie powinieneś mieć problemów ze zrozumieniem jego działania. Zresztą może po prostu warto użyć owego Doctrine (czy też innego ORMa) zamiast pisać od podstaw własnego? 3. Takie "późne pobranie" danych dot. artykułu, dopiero w momencie gdy są rzeczywiście potrzebne (tutaj: przy wywołaniu metody Comment::getArticle()) nazwa się Lazy Loading - i jest to świetne rozwiązanie gdy np. pobieramy 50 komentarzy przyporządkowanych do różnych artykułów, ale tylko w przypadku jednego komentarza chcemy uzyskać dostęp do artykułu powiązanego z nim. * Jeżeli już, to powinna być tzw. metodą-proxy, tj.: Jednak w tym przypadku stworzenie takiej metody wydaje się być kompletnie bezpodstawne i niepotrzebne. Ten post edytował Crozin 25.11.2010, 17:51:40 |
|
|
![]()
Post
#3
|
|
Grupa: Zarejestrowani Postów: 73 Pomógł: 0 Dołączył: 13.02.2006 Skąd: Warszawa Ostrzeżenie: (0%) ![]() ![]() |
Rozumiem, jest jeszcze jedna możliwa opcja - "ściągnięcie sobie potrzebnych danych sql'owym joinem i zapisanie jako pola obiektu komentarza". W tym przypadku, zamiast tworzyć cały obiekt Artykuł (który będzie musiał pobrać z bazy wiele niepotrzebnych z punktu widzenia komentarza danych), tworzymy tylko kilka pól w klasie Comment i na nich zapisujemy potrzebne dane artykułu.
Który sposób jest wydajniejszy w przypadku gdy, chcemy dla komentarza znać tylko tytuł artykułu ? Czy złożone zapytania sqlowe pobierające z kilku tabel są bardzo mało wydajne ? |
|
|
![]()
Post
#4
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
Nie, danych dot. artykułu nie powinieneś pakować bezpośrednio do obiektu komentarza - w końcu to komentarz, nie artykuł. Możesz oczywiście pobrać część danych dot. artykułu (np. tylko jego tytuł), ale nawet wtedy powinieneś dla artykułu utworzyć nowy obiekt.
Cytat Czy złożone zapytania sqlowe pobierające z kilku tabel są bardzo mało wydajne ? To zależy. Zapytania z JOINami są oczywiście bardziej obciążające, ale z reguły są lżejsze niż N zapytań. W końcu JOINy to esencja relacyjnych baz danych.
|
|
|
![]()
Post
#5
|
|
Grupa: Zarejestrowani Postów: 73 Pomógł: 0 Dołączył: 13.02.2006 Skąd: Warszawa Ostrzeżenie: (0%) ![]() ![]() |
Mam kolejne pytanie, również związane z wydajnością.
Otóż użytkownicy, za różne działania otrzymują punkty (m.in.) za komentowanie. Aby obliczyć aktualny stan punktów trzeba pobrać dane z kilku tabel. I teraz chciałbym wyświetlać kilku użytkowników o największej liczbie punktów. Najprostszym rozwiązaniem byłoby utworzenie obiektów wszystkich użytkowników ( w konstruktorze są obliczane punkty) i sprawdzenie który ma najwięcej. Jednak stworzenie obiektów dla kilkudziesięciu tysięcy użytkowników za każdym nowym odświeżeniem strony nie jest zbyt wydajne. Drugim sposobem jest stworzenie w tabeli user komorki punkty i napisanie skryput, ktory bedzie co jakis czas, np 15 min tworzyl te wszystkie obiekty obliczal punkty i wpisywal je do konkretnej komorki. Dzieki temu, gdy pozniej bedziemy chcieli wyswietlic najbardziej aktywnych, wystarczy, iz pobierzemy z tabeli ta jedna komorke z punktami. Ma to wg was sens ? |
|
|
![]()
Post
#6
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
Nie ma.
Skoro punkty są przyznawane przy jakiś akcjach: dodanie komentarza, dodanie materiału, dodanie aktualności, dodanie galerii itp. i odejmowane w momencie gdy na przykład moderator usunie komentarz to po prostu po dodaniu komentarza zwiększasz użytkownikowi ilość punktów. Przy usunięciu zmniejszasz: Jeżeli ilość przyznawanych punktów ma być zawsze stała dla danego zasobu i jesteś pewien, że nie będziesz w niedalekiej przyszłości zmieniał tej wartości sensownym wydaje się utworzenie wyzwalacza, który zajmie się drugim zapytaniem:
PS. Tutaj akurat w przykładzie MySQL, ale każdy liczący się RDBMS również ma takie funkcje delikatnie różniące się swoją składnią. Ten post edytował Crozin 3.12.2010, 15:58:47 |
|
|
![]()
Post
#7
|
|
![]() Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
Ale kombinujesz... Ja bym to zrobił tak:
1. Dodał dodatkową kolumnę do tabeli użytkowników przechowującą punkty. 2. Napisał triggery, które będą aktualizowały tą wartość w momencie np. dodawania artykułów (czegoś, za co są punkty). 3. Pobierał z bazy dane odpowiednio posortowane i na ich podstawie tworzył obiekty w PHP. |
|
|
![]()
Post
#8
|
|
Grupa: Zarejestrowani Postów: 200 Pomógł: 38 Dołączył: 1.12.2010 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
Jak dla mnie optymalnym rozwiązaniem będzie stworzenie dodatkowej kolumny z punktami i odswierzanie jej tylko wtedy kiedy zachodzi zmiana - tak jak piszesz, np. dodanie nowego komentarza. Wtedy nie będziesz musiał obciążać systemu co 15 minut liczeniem, oraz będziesz miał w miarę aktualne dane w kolumnie. Możesz też np. raz na dzień w nocy przeprowadzać synchronizację punktów robiąc obliczenie dla wszystkich użytkowników.
-------------------- Warsztat: NetBeans 7.2 Beta, PHP, MySQL, PostgreSQL, Symfony (<=1.4), Diem, Java, Sieci neuronowe
|
|
|
![]()
Post
#9
|
|
Grupa: Zarejestrowani Postów: 49 Pomógł: 4 Dołączył: 16.07.2008 Skąd: Gdańsk Ostrzeżenie: (0%) ![]() ![]() |
Tak naprawdę, to "optymalność" rozwiązania zależy tylko i wyłącznie od potrzeb. Bo optymalnie, pod kątem ewentualnych statystyk/rankingów, byłoby stworzenie oddzielnej tabeli z kolumnami o przykładowych nazwach: user_id, points_count, action_type gdzie action_type to typ zdarzenia, za które przyznano punkty. W ten sposób można pobrać nie tylko sumaryczną ilość punktów danego użytkownika ale też ilość punktów za daną aktywność. No ale chyba trochę odbiegłem od tematu.
Cytat Najprostszym rozwiązaniem byłoby utworzenie obiektów wszystkich użytkowników ( w konstruktorze są obliczane punkty) i sprawdzenie który ma najwięcej. Pod żadnym pozorem tego nie rób. Za pomocą jednego zapytania sql jesteś w stanie znaleźć id użytkownika z największą ilością punktów i tylko dla niego potem utworzyć obiekt. -------------------- devFactor
|
|
|
![]() ![]() |
![]() |
Aktualny czas: 20.08.2025 - 14:54 |