Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [php] Śledzenie kroków odowiedzającego stronę.
Forum PHP.pl > Forum > PHP
kukix
Witam.

Szykuje mechanizm, kóry będzie śledził kroki odwiedzającego stronę.

Tabele myślałem, żeby zrobić taką:

  1. CREATE TABLE IF NOT EXISTS `statystyki` (
  2. `session_id` varchar(255) COLLATE utf8_polish_ci NOT NULL,
  3. `user_id` int(11) NOT NULL,
  4. `user_ip` varchar(25) COLLATE utf8_polish_ci NOT NULL,
  5. `odwiedzono_szczegoly` varchar(255) COLLATE utf8_polish_ci NOT NULL,
  6. `time` datetime NOT NULL,
  7. `wejscie_ze_strony` varchar(255) COLLATE utf8_polish_ci NOT NULL
  8. ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci;



Pomysł jest taki, żeby po wywołanu każdej strony dodawać wpis do tabeli i tam za każdym razem "id sesj"i, "czas wywołania", "id usera" (jeżeli się zalogował), jeżeli wykryje $_SERVER['HTTP_REFERER'] to również "wejscie_ze_strony" + odwiedzana podstrona.

Mam wątpliwości w jaki sposób dodawać nowe wpisy tak, żeby dwa jednakowe wpisy nie były obok siebie co może wystąpić po odświeżeniu strony.


Czy ktoś ma jakieś sugestie jak taki mechanizm wykonac? Jakieś pomysły?
Sephirus
Dwa jednakowe wpisy z założenia nie mogą się pojawić.

Daj session_id jako PRIMARY (czyli też Unique) to podstawa.

I teraz możesz dodawać nowe rekordy za pomocą klauzuli INSERT ... ON DUPLICATE UPDATE

czyli:

  1. INSERT INTO tabela (session_id,user_id,...,time,wejscie_ze_strony) VALUES ('aaa','1',...,NOW(),'referer') ON DUPLICATE KEY UPDATE user_id = '1', ... , time = NOW();


Innymi słowy działa to tak:

1. wrzuć do bazy dane z danej sesji,
2. jeśli taki klucz (id sesji) już istnieje - zaktualizuj wszystkie pola w rekordzie (poza polem session_id oraz wejscie_ze_strony - aby nie nadpisać oryginalnego wejścia).
3. done smile.gif
kukix
Cytat(Sephirus @ 31.05.2013, 15:53:41 ) *
Dwa jednakowe wpisy z założenia nie mogą się pojawić.

Daj session_id jako PRIMARY (czyli też Unique) to podstawa.

I teraz możesz dodawać nowe rekordy za pomocą klauzuli INSERT ... ON DUPLICATE UPDATE

czyli:

  1. INSERT INTO tabela (session_id,user_id,...,time,wejscie_ze_strony) VALUES ('aaa','1',...,NOW(),'referer') ON DUPLICATE KEY UPDATE user_id = '1', ... , time = NOW();


Innymi słowy działa to tak:

1. wrzuć do bazy dane z danej sesji,
2. jeśli taki klucz (id sesji) już istnieje - zaktualizuj wszystkie pola w rekordzie (poza polem session_id oraz wejscie_ze_strony - aby nie nadpisać oryginalnego wejścia).
3. done smile.gif


Dzieki za obszerną odpowiedź.

Myślałem, jednak tak, żeby każde działanie zapisac w osobnym wpisie w tabeli. Czy nie będzie to wygodniejsze i wydajniejsze? (same inserty)

Czyli dużo wpisów z tym samym SESSION_ID a w adminstracji sobie to ładnie wyświetle i posostuje po dacie.
Po stronie użytkownika będzie tylko INSERT , tak więc powinno w miare szybko dzialac nawet przy dużje liczbie wpisów i będzie to działało szybciej niż UPDATE.

Top czy user odświeżył strone poznam po zmiennej w sesji "OSTATNIA_STRONA" jeżeli będzie taka samam jak obecna to nie robie nowego wpisu.

Statystyki mozn a kasować starsze jak 30 dni, aby baza nie przegrzała się. Co Wy na to?

Analizowałem tą sprawe jeszcze raz i jeżeli będe trzymał wszystko w jednym wpisie w bazie, odpadnie mi mozliwośc no zapisania daty i godziny danej operacji.

Problemme może też byc pole varchar i maksymalna długosć pola 255 znaków. Co jeżeli odwiedzający wykona więcej operacji?
gitbejbe
dobry temat, tez myślę nad czymś takim. Akurat robię spory projekt i z chęcią bym pośledził kogo się da (mam fioła na pkt. bezpieczeństwa;p)

Twój pomysł nie wydaje się być zły... Też myślałbym w tym kierunku aby mieć wgląd w każdy krok - a tego innaczej nie zrobisz nić przez inserty
Można się uprzeć i zrobić to z update. Wtedy myślałbym aby każde pole zrobić jako TEXT. Każdy nowy krok oddzielony byłby jakimś znakiem np spacji albo znakiem nowej linii. Wtedy zaoszczędziłoby się na obszerności bazy. Ale jednak lepsze są raczej inserty - ze względu na szybkość zapisu
Usuwanie starszych niż te np 30 dni rekordów to priorytet, dałbymnawet tak z 14 dni bo baza moment się zapełni ;p
Sephirus
@kukix

Cytat
Myślałem, jednak tak, żeby każde działanie zapisac w osobnym wpisie w tabeli. Czy nie będzie to wygodniejsze i wydajniejsze?


Zgadzam się z Tobą - będzie to też jest niezły pomysł. Co prawda myślałem, że potrzebujesz czegoś jedynie do aktualnego stanu - nie historycznego. Co do samej wydajności to trzeba by to było sprawdzić. Bo jeśli zrobisz to na InnoDB to biorąc pod uwagę fakt, że rekordów w wersji #1 byłoby znacznie mniej niż w wersji #2 to jak dodasz do tego indeksy to te inserty pod koniec tych 30 dni już wcale szybsze nie będą smile.gif Jeszcze jednym minusem jest fakt taki:

Czy chcesz wyświetlać tą aktywność na stronie userom? Czy ma być dostępna tylko w panelu adm. - bo jeśli chcesz to pokazywać odwiedzającym - to musisz robić selecty na ciąglę insertowanej bazie, po dacie itp i z wydajnością to będzie na bakier tongue.gif

Po tym co napisałeś wziąłbym obie metody i "zniszczył" normalizację bazy danych tworząc dwie tabele. Jedną do działań w trybie "rzeczywistym" na update'ach itp opartą o InnoDb (czyszczoną co jakiś czas z rekordów starszych niż powiedzmy 1h (nikt tyle na stronie nie wysiedzi) i drugą do zapisu historycznego - czyli z Twojej metody. Uzyskasz w ten sposób szybką, małą tabelkę do działań bieżących, która ma całkiem szybki zapis/edycję i super szybki odczyt o raz drugą tabelę, którą możesz użyć w panelu adm. aby prześledzić całą ścieżkę. Tabelę drugą możesz zapełniać poprzez wyzwalacz (trigger) tak by nie wysyłać dwóch zapytań do bazy (chyba to najlepsza opcja). Drugą tabelę oprzyj na MyISAM - dużo zapisów (szybsze) - rzadkie odczyty.

Wydaje mi sie, że to rozwiązuje temat i z datą i z czasem i z tym varcharem smile.gif

@gitbejbe

Za mocno kombinujecie - nigdy nie róbcie takich praktyk jak tu opisałeś - w ogóle nie używajcie pola typu TEXT tam gdzie liczy się wydajność smile.gif
kukix
Cytat(Sephirus @ 5.06.2013, 08:52:53 ) *
@kukix

Zgadzam się z Tobą - będzie to też jest niezły pomysł. Co prawda myślałem, że potrzebujesz czegoś jedynie do aktualnego stanu - nie historycznego. Co do samej wydajności to trzeba by to było sprawdzić. Bo jeśli zrobisz to na InnoDB to biorąc pod uwagę fakt, że rekordów w wersji #1 byłoby znacznie mniej niż w wersji #2 to jak dodasz do tego indeksy to te inserty pod koniec tych 30 dni już wcale szybsze nie będą smile.gif Jeszcze jednym minusem jest fakt taki:


Te ostatnie 30 dni będą w sumie cały czas wystepowały gdy skrypt będzie działal jużdłużej niż 30 dni.
Można jednak zrobić inaczej. Dodać druga identyczną tabele do któej kopiować wszystkie dane np o godzinie 24:00. Wtedy dane moze trzymac i pol roku i baza na której zapisuje skrypt nei bedzie zawalona.

Cytat(Sephirus @ 5.06.2013, 08:52:53 ) *
Czy chcesz wyświetlać tą aktywność na stronie userom? Czy ma być dostępna tylko w panelu adm. - bo jeśli chcesz to pokazywać odwiedzającym - to musisz robić selecty na ciąglę insertowanej bazie, po dacie itp i z wydajnością to będzie na bakier tongue.gif

Po tym co napisałeś wziąłbym obie metody i "zniszczył" normalizację bazy danych tworząc dwie tabele. Jedną do działań w trybie "rzeczywistym" na update'ach itp opartą o InnoDb (czyszczoną co jakiś czas z rekordów starszych niż powiedzmy 1h (nikt tyle na stronie nie wysiedzi) i drugą do zapisu historycznego - czyli z Twojej metody. Uzyskasz w ten sposób szybką, małą tabelkę do działań bieżących, która ma całkiem szybki zapis/edycję i super szybki odczyt o raz drugą tabelę, którą możesz użyć w panelu adm. aby prześledzić całą ścieżkę. Tabelę drugą możesz zapełniać poprzez wyzwalacz (trigger) tak by nie wysyłać dwóch zapytań do bazy (chyba to najlepsza opcja). Drugą tabelę oprzyj na MyISAM - dużo zapisów (szybsze) - rzadkie odczyty.

Wydaje mi sie, że to rozwiązuje temat i z datą i z czasem i z tym varcharem smile.gif

@gitbejbe

Troszke za dużo kombinacji z tym update i dodatkowo insertem. Dane nie będą pokazywane odwiedzającym, tyko i wyłącznie w administracji.

Cytat(Sephirus @ 5.06.2013, 08:52:53 ) *
Za mocno kombinujecie - nigdy nie róbcie takich praktyk jak tu opisałeś - w ogóle nie używajcie pola typu TEXT tam gdzie liczy się wydajność smile.gif


To miałem też na myśli, TEXT nie mozna w takich miejscach stosowac, jednak pole VARCHAR może sięszybko skończyć.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.