Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [zestaw klas PHP5]Cachowanie zapytan db
Forum PHP.pl > Forum > Gotowe rozwiązania > Algorytmy, klasy, funkcje
athabus
Witam, ostatnio postanowilem sie zajac cachowaniem zapytan z bd. I tak pomalutku stworzylem swoja klase do cachowania/odczytywania zapytan z PostgreSQL. Klasa po malych przerobkach bedzie dzialac rowniez z MySQL.

Na poczatek, co by nie byc posadzony o plagiat biggrin.gif od razu przyznam sie ze korzystalem z rozwiazania mike_mecha (http://php.nq.pl/index.php?showtopic=22487&hl=cache) - ale oczywiscie tyko pogladowo biggrin.gif

Na poczatek moze diagram mojego rozwiazania
Diagram klas
(uml znam slabo wiec pewnie sa bledy w diagramie jesli chodzi o oznaczenie relacji)

Co do kodu to znajduje sie on tutaj: (podaje linki bo kodu jest za duzo na wklejanie)
Klasa DB -glowna klasa bazy danych
Db_result - abstrakcyjna klasa wyniku zapytania
Db_Result_orig - wynik zapytania wykonanego z bazy
Db_result_cache - wynik zapytania wykonanego z cachu (lub z bazy z pozniejszym cachowaniem)
GenericException - Rozszerzenie klasy Exception o zapis wyjatkow do loga
PGException - klasa wyjatku bazy danych

Klasy dodatkowo korzystaja z kilku stalych (np. connection string, sciezka do katalogu z cachem itp), ktore
trzymam w osobnym pliku -> gdyby ktos chcial przetestowac na zywo dzialanie klasy to trzeba odpowiednie pliki wygenerowac wraz ze stalymi.

Najwazniejsze cechy moich klas to:
- cachowanie zapytan do pliku tekstowego / odczytywanie zapytan z takiego cachu
- system obslugi wyjatkow z zapisem bledow do logow
- mozliwosc iterowania wyniku - zastsowany interfejs iteratora

Jako ze jestem poczatkujacy prosze o ocene kazdego aspektu, ktory przyjdzie wam do glowy - poczynajac od kodu a na organizacji projektu konczac - kazda rada / wytkniecie bledu mile widziane.

Przykladowe zastosowanie
  1. <?php
  2.  include_once ('db/db.class.php');
  3.  include_once ('const_db.php'); 
  4.  
  5.  $sql='select * from produkty';
  6.  
  7.  try
  8.  {
  9.  $db=Db::getInstance();
  10.  }
  11.  catch (Exception $e)
  12.  {
  13.  echo $e; 
  14. [indent] die()
  15.  }
  16.  
  17.  try
  18.  {
  19. //odczyt zapytania z cachu. Jesli brak cachu dla zapytania to odczyt z bazy
  20. //nastepnie cachowanie jest zapisywane
  21. // 2 parametr mowi ze wynik ma byc jako tablica asocjacyjna, 3 parametr
  22. //mowi ze cache bedzie wazny przez godzine (3600 sekund) - oba parametry sa opcjonalne
  23.  foreach ($db->query_cache($sql, true, 3600) as $row)
  24.  {
  25.  echo $row['nazwa_produktu'] . '<br/>';
  26.  }
  27.  }
  28.  catch (Exception $e)
  29.  {
  30.  //wyswietla pelen opis bledu wraz z zapytaniem i opisem bledu
  31.  //uzywac tylko przy testowaniu - w kodzie produkcyjnym raczej
  32.  //nie powinno sie znalezc gdyz haksior moze poznac strukture bazy
  33.  $e->toScreen();
  34.  }
  35.  
  36.  try
  37.  {
  38.  //przyklad uzycia zapytania bez cachowania (drugi parametr oznacza odczyt numeryczny)
  39.  foreach ($db->query_db($sql,false) as $row)
  40.  {
  41.  echo $row[0] . '<br/>';
  42.  }
  43.  }
  44.  catch (Exception $e)
  45.  {
  46.  echo $e;
  47.  }
  48.  
  49.  //oczywiscie mozna rowniez odczytywac pojedyncze wyniki
  50.  $result=$db->query_cache($sql);
  51.  //odczyt 4 wiersza
  52.  $row=$result->fetch_row(3);
  53.  
  54.  
  55. ?>
dr_bonzo
Przyklad uzycia jest lipny -- co bedzie jak nie powiedzie sie polaczenie?
Wykonasz: $db->query_cache(...), wrzuc wszystko w jeden blok try/catch.

if ($result===null)
to chyba zawsze bedzie false (ale ni ejestem pewien), sprawdzaj is_null()
athabus
Dodałem die() w razie bledu polaczenia. Faktycznie bez sensu bylo biggrin.gif

Wolal bym unikac ogromnych blokow try...catch - podobno nie sa one optymalne jesli chodzi o czas wykonania skryptu... Poza tym (moze zle mysle) - wyjatek wyrzucony w jednym zapytaniu nie koniecznie musi byc krytyczny i moge chciec kontynuowac skrypt.

co do $result===null to musze gdzies doczytac ale wydaje mi sie ze nie robi to roznicy w tym przypadku... chociaz jesli chodzi o testy logiczne z null'em to ciagle mnie php zadziwia blink.gif
dr_bonzo
Cytat
Dodałem die() w razie bledu polaczenia

Tez zle, to user biblioteki ma decydowac czy w przypadku bledu polaczeniazakonczyc skrypt.

Cytat
Wolal bym unikac ogromnych blokow try...catch - podobno nie sa one optymalne jesli chodzi o czas wykonania skryptu

Jaki ogromny -- 20 linii w bloku to malo, poza tym miales blednie zrobione te bloki (pisalem o tym w poprzednim poscie)

  1. <?php
  2.  
  3. $a = null;
  4.  
  5. if ( $a === null )
  6. {
  7. print( '$a === null' ); // OK
  8. }
  9. else
  10. {
  11.  
  12. print( '$a !!!! null' );
  13. }
  14. ?>
athabus
Cytat(dr_bonzo @ 15.06.2006, 19:25 ) *
Tez zle, to user biblioteki ma decydowac czy w przypadku bledu polaczeniazakonczyc skrypt.
Jaki ogromny -- 20 linii w bloku to malo,

Die() dodale w przykladzie po wylapaniu wyjatku polaczenia nie w klasie... nieprecyzyjnie sie wyrazilem (zmiana jest naniesiona w przykladzie uzycia).

Cytat
poza tym miales blednie zrobione te bloki (pisalem o tym w poprzednim poscie)
  1. <?php
  2.  
  3. $a = null;
  4.  
  5. if ( $a === null )
  6. {
  7. print( '$a === null' ); // OK
  8. }
  9. else
  10. {
  11.  
  12. print( '$a !!!! null' );
  13. }
  14. ?>

Tu sie gdzies zgubilem - o jakich blokach mowisz? W ktorym miejscu mam cos takiego? Znalazlem tylko jeden taki przyklad jak podawales w pierwszym poscie w moim kodzie (w klasei Db_result_orig), ale tam wszystko dzialala tak jak powinno. Chodzilo o to, ze wartosc domyslna dla result byla null - co oznaczalo ze nie podano parametru.
mariuszn3
Nie wiem jak jest z Postgre ale przecież w MySQL cachowanie zapytań jest częścią funkcjonalności serwera MySQL i jest domyślnie włączone. Po co więc pisać w php klasę, która by przejmowała tę funkcjonalność? Chodzi o samo zdjęcie obciążenia wynikającego z wywołania zapytania? Jednak czy wtedy sam algorytm cache'owania nie stanie się równorzędnym może nawet trochę gorszym obciążeniem?
ActivePlayer
Cytat
Po co więc pisać w php klasę, która by przejmowała tę funkcjonalność? Chodzi o samo zdjęcie obciążenia wynikającego z wywołania zapytania? Jednak czy wtedy sam algorytm cache'owania nie stanie się równorzędnym może nawet trochę gorszym obciążeniem?

nie zawsze mysql lezy na tej samej maszynie ktorej php, dane tez trzeba pobrać... wszystko zabiera czas.
Cysiaczek
Nie chcę przesadzić, ale muszę z wnioskiem formalnym smile.gif
Dlaczego twoje pliki z klasami ładują jakieś pliki innych klas?
Czy nie byłoby w porządku, gdyby jedna klasa=jeden plik i nic więcej.
Załadować możesz przecież w pliku usera. jeśli boisz się o kolejność deklaracji, to może woaduj includy do jakiejś funkcji. Proste i estetyczne. No może się czepiam...

pozdrawiam
dr_bonzo
Cytat
Tu sie gdzies zgubilem - o jakich blokach mowisz?

BLoki -- bloki try /catch.

A kod z === null odnosil sie do czego innego, ten kod prezentowal ze
$obj === null zwraca TRUE gdy $obj jest NULL.
athabus
@Cysiaczek
Czy chodzi Ci o cos takiego?
  1. <?php
  2. include_once ('const_db.php');
  3. include_once ('db/db_result_orig.class.php');
  4. include_once ('db/db_result_cache.class.php');
  5. include_once ('db/pgException.class.php'); 
  6. class DB
  7. {
  8.  //tresc klasy
  9. }
  10. ?>


Czyli ze klasa DB includuje klasy db result itd?
Robilem to dlatego, ze np. klasa Db "zwraca" wynik jako obiekt db_result. Czy includowanie powinno byc w osobnym pliku (dajmy na to w pliku korzystajacym z Db)? Myslalem ze tak jak jest teraz jest ok bo nie trzeba pamietac o includowaniu pozostalych klas.

@mariuszn3 - nawet nie wiedziale ze mySql cachuje wyniki biggrin.gif Ale mi bardziej chodzi o to, ze np. masz elementy ktore sie rzadko zminiaja (np. opis produktu w sklepie internetowym) - moja klasa przechowuje informacje w cachu domyslnie przez 24 godziny. Jesli ktos w tym czasie bedzie probowal odczytac ten wynik zrobi to znacznie szybciej niz laczac sie z baza. Nawet jesli wynik jest cachowany przez baze to i tak trzeba go pobrac. Musze zrobic dokladne testy na jakiejs bazie sensownej wielkosci ale powinno to dzialac szybciej niz standardowo.

@dr_bonzo - myslalem ze to byl jeden ciag myslowy biggrin.gif Co do blokow try-catch wydaje mi sie ze tak jak sa teraz (po drobnej korekcie z die() ) w przykladzie jest ok (ale tak jak mowilem dopiero zaczynam php wiec moge sie mylic), jedyne co warto by tam poprawic to to, zeby lapac wyjatek PgException zamista standardowego - tyle ze tutaj nie bylo sensu bo i tak nie podajmowale zadnej decyzji w zaleznosci od rodzaju wyjatku. W prawdziwej aplikacji nalezalo by to zmienic.

A i jeszcze jedno - zapomniale o to spytac w pierwszy poscie. Wynik cachowanych zapytan przechowuje w pliku o nazwie 'typ zapytania (assoc/numeric)' . sha1 z zapytania . 'txt' czyli np:

as_asdlkjqasdf02dd2lj3jv09qnajkfa.txt

myslicie ze tak jest poprawnie? Bo w innych przykladach widzialem nazwy plikow nadawane recznie lub zapytanie jako nazwa pliku. Ale w 1 przypadku wydaje mi sie ze jest to niewygodne w uzytkowaniu a w 2 nazwy przy skomplikowanych zapytaniach byly zbyt dlugie. Jestem swiadom ze moje rozwiazanie tez nie jest doskonale ale co o nim myslicie?
mariuszn3
Cytat(athabus @ 16.06.2006, 13:52 ) *
@mariuszn3 - nawet nie wiedziale ze mySql cachuje wyniki biggrin.gif Ale mi bardziej chodzi o to, ze np. masz elementy ktore sie rzadko zminiaja (np. opis produktu w sklepie internetowym) - moja klasa przechowuje informacje w cachu domyslnie przez 24 godziny. Jesli ktos w tym czasie bedzie probowal odczytac ten wynik zrobi to znacznie szybciej niz laczac sie z baza. Nawet jesli wynik jest cachowany przez baze to i tak trzeba go pobrac. Musze zrobic dokladne testy na jakiejs bazie sensownej wielkosci ale powinno to dzialac szybciej niz standardowo.

Myślę, że to może mieć sens tylko wtedy jeśli faktycznie w ogóle przy przejściu całego skryptu unikasz połączenia z bazą.. a nie kiedy unikasz wywołania zapytania przy i tak już nawiązanym połączeniu z bazą. Zwróć uwagę, że rozszerzenia php do łączenia z bazą (mam na myśli mysql czy mysqli, ten ostatni nawet jest napisany poprzez programistów mysql) są napisane z poziomu języka C. Czyli z zasady są one dużo szybsze niż jakiekolwiek próby uzupełniania czy zastępowania ich przez kod php - w momencie jak już masz połączenie z bazą, wszystkie zapytania odbywają się bardzo szybko. Według moich testów szybkość zwrócenia scache'owanej odpowiedzi na zapytanie wacha się w granicach kilku mikrosekund(exclamation.gif). Przykładowo u mnie na Win XP PIV: pierwsze zapytanie 0.5sek.. Późniejsze wywoływanie tego samego zapytania - 0.005 sek. Mam duże wątpliwości czy oddawanie tej funkcjonalności klasie php jest w stanie to przyspieszyć, obawiam się nawet, że już sam fakt kodowania w php klasy cache'ującej sprawi, że wynik będzie gorszy.
Natomiast przykład, który przytoczyłeś, czyli przykładowo rzadko zmieniający się opis produktu, cache'ował bym nie poprzez klasy do cache'owania zapytań do bazy ale przez coś bardziej uniwersalnego. przykładowo poprzez coś takiego jak turck mmcache, którym właśnie możesz cache'ować wyniki często powtarzających się przejść tego samego algorytmu... i też to będzie mega szybsze niż jakaś klasa w php do cache'owania, bo mmcache jest to rozszerzenie napisane w C.
ActivePlayer
Cytat
Przykładowo u mnie na Win XP PIV: pierwsze zapytanie 0.5sek.. Późniejsze wywoływanie tego samego zapytania - 0.005 sek. Mam duże wątpliwości czy oddawanie tej funkcjonalności klasie php jest w stanie to przyspieszyć, obawiam się nawet, że już sam fakt kodowania w php klasy cache'ującej sprawi, że wynik będzie gorszy.

Uruchom Twoje zapytanie 300 razy jednocześnie.
athabus
Zrobile maly test.
Wykonalem 1000 zapytan uzywajac funkcji query_cache() (z cachowaniem) i query_db() (bez cachowania).
Zapytania byly identyczne (select * from tabela), gdzie tabela miala 5 rekordow tylko.

Uzylem nastepujacego testu (athlon barton 2,5 GHz, 512 Ramu, WinXP)
  1. <?php
  2. $start=microtime(true);
  3. include_once ('db/db.class.php');
  4. include_once ('const_db.php'); 
  5. $db=Db::getInstance();
  6. $sql='select * from produkty';
  7. for ($i=0; $i<1000; $i++)
  8. {
  9. $result=$db->query_db($sql); //lub $result=$db->query_cache($sql);
  10. }
  11.  
  12. $end=microtime(true);
  13. echo $end-$start;
  14. ?>


Z gory zaznaczam ze zdaje sobie sprawe ze wynik nie jest do konca miarodajny gdyz raczej rzadko zdarza sie taka sytuacja jak powyzej ale wyniki byly nastepujace (w obu przypadkach nastapilo polaczenie z baza danych)

-> z cachowaniem srednio zapytania zostaly odczytane w 0,2 - 0.25 s
-> bez cachowania 0,6-0,7 s

Czyli różnica jest 3 krotna. Rozwarzajac dalej mysle ze w swiecie realnym roznica moglaby byc wieksza z nastepujacych powodow:
->tak jak mowi AcitvePlayer serwer bd moze byc na innej maszynie (nazwa.pl zdaje sie tak ma)
->Zapytania byly wykonywane na bardzo prostej bazie (5 rekordow - 4 pola) w rzeczywistosci tabele sa znacznie bardziej skomplikowane wiec wydluza sie czas odczytania zapytania + pobrania wyniku
->Trzecia sprawa (tu zupelnie teoretyzuje bo nie mam pojecia jak jest w rzeczywistosci) przy cachowaniu wynik jest od razu jako tablica w przypadku odczytu z bd wynik jest podawany jako dataset i trzeba go obrobic - nie wiem czy to nie wydluza czasu dostepu do bazy danych

W czy na pewno sie z toba zgodze to kwestia nawiazania polaczenia - na tym najwiecej mozna by bylo prawdopodobnie zaoszczedzic - no ale jak sam mowisz w realnych warunkach jest to praktycznie niemozliwe. Na pewno tez mozna wykorzystac bardziej profesjonalne narzedzia napisane w C ktore na 100% zadzialaja szybciej... ale chcialem napisac cos sam biggrin.gif

PS. Czy taki sposob testowania szybkosci dzialania jest w ogole uzasadniony -> tylko to mi przyszlo do glowy biggrin.gif

PS2 . Nie liczylem ze wywiaze sie az taka ciekawa dyskusja - fajnie sie czegos nowego nauczyc.
ActivePlayer
jesli chodzi o nawiązywanie połączenia... przeciez mozna je nawiązywać dopiero jesli dane nie istnieją w cachu i trzeba je pobrać.
athabus
To prawda, ale wyszedlem z zalozenia, ze jeszcze nigdy chyba nie zrobilem strony, ktora moglaby byc cachowana w calosci, takze i tak zawsze to polaczenie sie nawiazuje. Samo polaczenie jest nawiazywane zawsze tylko raz (uzylem singeltona).

Swoja droga mam kolejny pomysl jak udoskonalic ta klase - mozna by dodac narzedzie do rejestrowania czasu wykonania zapytania/zapytan - moze bylo by to pomocne w optymalizacji.

PS. Tak przy okazji sie spytam - na jakiej zasadzie dziala cachowanie w mySQL? Są cachowane zapytania na jakis bardzo krotki czas np 10s itp (to chyba raczej niemozliwe)? Czy moze cache z danej tabeli jest zawsze usuwany po zmianie takiej tabeli?
Czy PostgreSql tez ma taka funkcjonalnosc?
mariuszn3
Zrobiłem parę testów na MySQL. Niestety nie korzystam z PostgreSQL więc nie mogłem przetestować Twojej klasy, natomiast testy oparłem na klasie, którą napisał MikeMech.
Jedną rzecz tylko zmieniłem w jego klasie, przeniosłem ją na rozszerzenie mysqli, bo akurat z tego korzystam i nawet nie mam zainstalowanego rozszerzenia mysql.
Testy robiłem na win XP, PIV 2.4Ghz, 1GB ram, php 5.1.3, MySQL 5.0.18, Apache 2.0.55
Ustawiłem też priorytet procesów apache i mysql na realtime aby jak najmniejszy był wpływ zewnętrznych czynników. Skoncentrowałem się na pojedyńczym wywołaniu skryptu poprzez narzędzie apache benchmark. Myślałem o zrobieniu testów wywołując kilka zapytań na raz ale w odpowiedzi dostawałem, prawie zawsze jakieś nie udane więc zrezygnowałem.

Początek skryptu:
  1. <?php
  2. require_once( 'ResultCached.class.php');
  3. require_once( 'Result.class.php');
  4. require_once( 'DB.class.php');
  5. $objDB = DB::GetInstance( 'localhost' , 'root', '', 'test' );
  6. $count = 100;
  7. ?>

Następnie jest wysyłanych 100 zapytań. Serwer MySQL domyślnie cache'uje zapytania. Tak więc w pierwszym teście zdajemy się na cache mysql a w drugim na cache php:
W pierwszym teście wszystkie zapytania idą do serwera mysql:
  1. <?php
  2. while (--$count) {
  3. $objDB->Query( 'SELECT * FROM test' );
  4. }
  5. ?>

W drugim korzystam z opcjonalnego cache'owania poprzez metodę QueryCached()
  1. <?php
  2. while (--$count) {
  3. $objDB->QueryCached('test', 'SELECT * FROM test' );
  4. }
  5. ?>

Wszystkie testy przeprowadziłem 10 razy i poniżej podaję średnią wartość.
Przeprowadziłem też testy dla dwóch różnych rozmiarów odpowiedzi (40 znaków i ok 20 tysięcy znaków)
Dla zapytania zwracającego ok. 40 znaków
bez cache'a php: 0.283 sek
z cache'em php: 0.311 sek
Dla zapytania zwracającego ok. 20 000 znaków
bez cache'a php: 0.42 sek
z cache'em php: 0.45 sek

Pierwsza refleksja jest taka, że jednak próba cache'owania przez php wychodzi nieco słabiej niż zdawanie się na natywny cache mysql. Jednak trzeba wziąść parę dodatkowych czynników, po pierwsze skrypt MikeMech cache'uje zapytania MySQL poprzez zapis i odczyt danych do pliku na dysk, co z zasady skazuje skrypt na nie najlepszą wydajność. Na pewno te wyniki byłyby znacznie lepsze i całkiem możliwe, żeby przegoniły mysql'owy cache gdyby dane były cache'owane do pamięci ram ale wtedy musimy albo zastosować zewnętrzne rozszerzenie jak mmcache.. albo zrezygnować z myśli o cache'owaniu zapytań pomiędzy wywołaniami.

Twoje wyniki athabus tłumaczę tym, że w Postgre nie ma opcji cache'owania zapytań albo miałeś cache'owanie poprzez Postgre wyłączone (?)

Odnośnie połączenia z bazą, to można sprytnie zrobić aby połączenie z MySQL następowało dopiero tuż przed wykonaniem pierwszego zapytania, wtedy jeśli przy przejściu algorytmu nie jest wywoływane żadne zapytanie mysql, w ogóle serwer mysql nie jest dotykany. Jednak aby to osiągnąć trzeba skorzystać z dóbr magicznej funkcji __autoload().
Przykładowo, w jednym pliku masz klasę MySQL, która jest sterownikiem wywołujacym zapytania na bazie. W innym pliku masz klasę ProjektDAO, której jedynym zadaniem jest komunikacja z klasą MySQL i przez nią wywoływanie zapytań na potrzeby danego projektu. W pliku, w którym jest definicja klasy ProjektDAO zaraz za tą definicją umieszczasz linijkę kodu, czy wywołujesz funkcję nawiązującą połączenie z bazą danych. W praktyce przy zdaniu się na __autoload() plik z ProjektDAO zostanie wincludowany przy pierwszym wywołaniu do tej klasy.. tak więc jeśli nie wywołujesz żadnych zapytań do ProjektDAO połączenie z bazą w ogóle nie następuje.. natomiast jak wywołujesz zapytanie do ProjektDAO automatycznie przy includowaniu pliku jest nawiązywane połączenie.
athabus
mariuszn3Dzieki za przeprowadzenie testow. Mysle ze wyniki z uzyciem mojej klasy bylyby podobne - uzylem podobneg rozwiazania jak mike_mech tyle ze dodalem kilka funkcjonalnosci.
Chetnie porownalbym wyniki na moim kompie uzywajac MySQL'a ale niestety nie mam go zainstalowanego sad.gif (ostatnio korzystam z PG i jakos nie zainstalowalem).
Nie wiem czy PG ma cachowanie wynikow - recznie go w kazdym razie nie instalowalem - uzywam wersji "prosto z pudelka".

Teraz tylko zastanawia mnie w jaki sposob mySQL cachuje wyniki. W pamięci operacyjnej? Jesli tak to musza one byc nietrwale. Na pewno daja spore rezultaty przy czesto wykonywanych zapytaniach, ale przy rzadziej sie powtarzajacych (dajmy na to raz na godzine) ten mechanizm sie nie sprawdzi tak dobrze. (wszystko co tu pisze to moje przemyslenia nie poparte testami). Kwestia teraz proporcji zapytan czesto sie powtarzajacych do tych rzadziej sie powtarzajacych -> duzo niewiadomych biggrin.gif

Wszystko to sklania mnie do napisania dodatkowej klasy do testowania czasow zapytan + dostosowanie jej do mySQL. Fajnie byloby sprawdzic jaki procent zapytan stanowia zapytania cyklicznie sie powtarzajace.

Mysle ze w warunkach "produkcyjnych" moja klasa da pozytywne rezultaty - w ostatecznosci ograniczy obciazenie bazy - ale Twoje testy daja mi duzo do myslenia.

Co do ustalenia polacznenia dopiero przed wywolaniem zapytania korzystajacego z bazy - to swiadomie porzucilem ten pomysl. Sytuacja wygenerowania strony bez zadnego zapytania do bazy (pisze ten sterownik pod katem sklepu internetowego, ktory chce sobie napisac) jest raczej malo prawdopodobna wiec polacznie i tak bedzie trzeba ustanowic.
mariuszn3
Cytat(athabus @ 16.06.2006, 21:56 ) *
Teraz tylko zastanawia mnie w jaki sposob mySQL cachuje wyniki. W pamięci operacyjnej? Jesli tak to musza one byc nietrwale. Na pewno daja spore rezultaty przy czesto wykonywanych zapytaniach, ale przy rzadziej sie powtarzajacych (dajmy na to raz na godzine) ten mechanizm sie nie sprawdzi tak dobrze. (wszystko co tu pisze to moje przemyslenia nie poparte testami). Kwestia teraz proporcji zapytan czesto sie powtarzajacych do tych rzadziej sie powtarzajacych -> duzo niewiadomych biggrin.gif

Na pewno MySQL cache'uje wyniki w pamięci operacyjnej, dzięki temu ma bardzo szybki dostęp dodanych, czemu uważasz, że muszą być one nie trwałe? Zwróć uwagę, że serwer na którym stoi strona restartuje się może kilka razy w roku a dane w pamięci operacyjnej nie są jak atrament sympatyczny, który po godzinie sam znika.
Według mnie pamięć operacyjna to zdecydowanie najlepsze rozwiązanie. Co do tego jak działa od środka, no to nie studiowałem tego.. ale podejrzewam, że ogólna zasada jest prosta. W ustawieniach serwera ustawiasz wielkość cache'u.. w manualu pisze, że domyślnie jest to wartość 0 (!) co na starcie wykluczałoby cache'owanie ale mam wrażenie, że w domyślnym pliku konfiguracyjnym, który wgrywa się wraz z instalacją serwera jest wpisana dodatnia wartość, ja bardzo w swojej konfiguracji nie grzebalem i mam wpisane 8MB. Serwer zapełnia ten cache póki może a jak się okazuje, że zbliża się do limitu wtedy nadpisuje te najstarsze zapytania, to tylko moje przypuszczenie. Wierzę, że jest to bardzo logicznie rozwiązane w końcu nie takie głowy nad tym siedziały.
Z dodatkowych rzeczy, jest ustawienie, które ustala powyżej jakiej wielkości nie cache'ować odpowiedzi (domyślnie 1MB), jak i też możesz ustawić cache'owanie na zawołanie.. ale wtedy każde zapytanie, które życzysz sobie aby MySQL cache'ował musisz zacząć poprzez 'SELECT SQL_CACHE' też można w drugą stronę, ustawić aby cache'ował wszystkie (tak jest domyślnie) a jeśli chcesz uniknąć cache'owania w jakimś zapytaniu zaczynasz zapytanie poprzez 'SELECT SQL_NO_CACHE'.
W manualu też mocno zwracają uwagę, że w przypadku mnogości różnych małych nie powtarzających się zapytań tak naprawdę cache'owanie może bardziej popsuć wydajność niż ją poprawić.. ale to jest logiczne i dotyczy jakiegokolwiek systemu cache'owania... aby cache'owanie się zwróciło zapytania muszą się powtarzać, to się rozumie samo przez sie.
eai
Nie szyfrujesz danych zapisanych w cache. Powinienes zaszyfrowac wartosc zserializowana. A potem odszyfrowac i unserialize tak dla bezpieczenstwa.
pawel_
z tego co widze, to zapomniałeś o jednej małej rzeczy.... co z triggerami w pgsql'u questionmark.gif
alpin19
btw... UML jest baaardzo marny. Polecam szczegółowe zapoznanie się z dokumentacją. W php może i coś takiego by uszło, ale w Javie napewno nie sad.gif

Schemat nie zawiera relacji, procedur, wywołań ani chierarchii...sad.gif
NuLL
Cytat(eai @ 11.08.2006, 14:50:24 ) *
Nie szyfrujesz danych zapisanych w cache. Powinienes zaszyfrowac wartosc zserializowana. A potem odszyfrowac i unserialize tak dla bezpieczenstwa.

Po co questionmark.gif Myslisz ze ktos ma za duzo czasu w zyciu aby przegladac NIEZABEZPIECZONE katalogi z cache questionmark.gif snitch.gif
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.