![]() |
![]() |
|
Serverske aplikacije i baze podataka PHP, Perl, ASP, ASP .NET, ColdFusion... MySQL, PostgreSQL, MSQL, Oracle... |
![]() |
|
Alatke vezane za temu | Vrste prikaza |
![]() |
#1 |
Veteran
Član od: 3.5.2008.
Lokacija: Beograd
Poruke: 760
Zahvalnice: 81
Zahvaljeno 213 puta na 144 poruka
|
![]()
Jel bi mogao neko, ko se razum u neki fourmski softver, da kaže kako softver tačno dolazi do broja postova koji se prikazuje za korisnika u info boxu levo. Računam da je nemoguće da za svaki post na strani udara bazu da izbroji sve postove tog korisnika. Mora da ima negde keširan taj broj, i da nekako taj keš održava da bude tačan.
Zanima me ovo zbog projekta za faks, a to je pravljenje rudimentarnog forumskog softvera. Post count mi je trenutno najveća misterija. Pretpostavljam da isto važi i za zahvalnice i druge statistike. |
![]() |
![]() |
![]() |
#2 |
Član
Član od: 15.12.2011.
Poruke: 150
Zahvalnice: 27
Zahvaljeno 49 puta na 44 poruka
|
![]()
Mozes jednostavno da cuvas tu vrednost u tabeli sa podacima o korisnicima ili u
nekoj novoj tabeli (user_id, posts_count) i da inkrementujes posle svakog posta koristeci trigger |
![]() |
![]() |
Sledeći korisnik se zahvaljuje korisniku korisnickoime na korisnoj poruci: | ||
ivan90BG (1.8.2015) |
![]() |
#3 |
Veteran
Član od: 3.5.2008.
Lokacija: Beograd
Poruke: 760
Zahvalnice: 81
Zahvaljeno 213 puta na 144 poruka
|
![]()
Da da, trigger mi nije pao na pamet, hvala.
|
![]() |
![]() |
![]() |
#4 |
Deo inventara foruma
Član od: 17.6.2011.
Poruke: 7.302
Zahvalnice: 94
Zahvaljeno 3.312 puta na 1.997 poruka
|
![]()
Sav forumski softver za koji znam koristi posebno polje u tabeli korisnika za čuvanje broja njegovih postova. Kada korisnik napravi novi post taj broj se jednostavno inkrementira. Kada post iz određenih razloga bude obrisan broj se dekrementira.
Kao prva pomoć za slučaj da nešto krene naopako u administrativnom delu obično se dodaje i opcija za ručno pokretanje brojanja postova za sve korisnike tako da broj bude ažuran. Naravno takva operacija ume da bude poprilično zahtevna na velikim forumima pa se ne koristi često. DISCLAIMER: Ja sam bio jedan od developera SMF-a dok ga nisam napustio zbog "kreativnih nesuglasica" sa menadžmentom projekta. |
![]() |
![]() |
![]() |
#5 |
Veteran
Član od: 3.5.2008.
Lokacija: Beograd
Poruke: 760
Zahvalnice: 81
Zahvaljeno 213 puta na 144 poruka
|
![]()
I ja sam imao neku ideju da se broj postova vodi u posebnom polju u bazi, i da je ostavljena negde opcija adminu da ručno pokrene brojanje. Samo što nisam bio smislio način na koji ću da inkrementujem ili dekrementujem broj (na nivou aplikacije), a da ne dođe do nekog data race-a ili šta već. Ali sam zaboravio da postoje trigger-i kojima se to rešava na nivou baze.
A jel znaš šta se radi ako se za neki forum (tj. sobu) postavi da se postovi ne broje (ili broje). Da li se u tom slučaju obavezno pokreće brojanje i jel to može da se radi u trigger-u. |
![]() |
![]() |
![]() |
#6 |
Deo inventara foruma
Član od: 29.1.2008.
Poruke: 20.352
Zahvalnice: 431
Zahvaljeno 3.974 puta na 3.698 poruka
|
![]()
može i count funkcija
|
![]() |
![]() |
![]() |
#7 |
Deo inventara foruma
Član od: 17.6.2011.
Poruke: 7.302
Zahvalnice: 94
Zahvaljeno 3.312 puta na 1.997 poruka
|
![]()
Pa verovatnoća da izazoveš deadlock zbog konkurentnosti kod izmene broja postova korisnika je praktično nikakva jer je korisnik jedini koji može na njega da utiče (osim administracije naravno). Da bi postojala čak i teorijska šansa za tako nešto korisnik mora da bude u stanju da šalje po par stotina poruka u sekundi što je složićeš se praktično nemoguće. A čak i ako se tako nešto dogodi pa neki hakovani nalog krene masivno da spamuje preko botova anti-flood zaštite obično odmah odreaguju posle prvog posta.
Inače, kad te već interesuje ta tematika evo par stvari koje ne bi bilo loše da znaš ako već sa njima nisi upoznat. Pretpostaviću da koristiš MySQL ili MariaDB. InnoDB i MyISAM sami po sebi već poseduje zaštitu od deadlocka u smislu da njegov mehanizam za izvršavanje upita automatski vrši zaključavanje tabela. InnoDB je sposoban da zaključava do nivoa reda (row-level locking) a MyISAM do nivoa tabele (table-level locking). Ako ti ni to nije dovoljno jer imaš jako veliku konkurentnost na klijentskoj strani onda se u takvim situacijama koristi kombinacija transakcija i zaključavanja. Ukoliko hoćeš da napraviš kompromis između zaštite i kompleksnosti sistema onda za UPDATE upit možeš da koristiš i LOW_PRIORITY direktivu koja će se pobrinuti da se update izvrši tek nakon što tabela prijavi da nema upita koji vrše čitanje iz nje. Vodi računa da ovo može da bude mač sa dve oštrice jer ako je konkurentnost prevelika doći ćeš u situaciju da UPDATE upit predugo čeka. Što se trigera tiče, sami po sebi su dobra stvar. Međutim, to je put na Tamnu stranu jer lako vodi u zamku da se fokus biznis logike prebacuje tamo gde mu nije mesto - u bazu. Napravićeš AFTER triger za inkrementiranje broja postova korisnika nakon svakog unosa, to nije sporno. A šta ćeš da radiš kad korisnik ili administracija uklone neki post? Moraćeš da napraviš još jedan trigger. Šta ukoliko u celu priču moraš da ubaciš i neku logiku? Dodaćeš još par trigera. Jel primećuješ šablon? Biznis logiku prebacuješ u bazu. Još jedna loša stvar u vezi MySQL trigera (i skladišnih procedura/funkcija uopšte) - užasno ih je teško debugovati. MSSQL i Oracle imaju dobre alate za tu namenu, MySQL ih nema. Jedini alat na tržištu koji pouzdano radi taj posao je dbForge for MySQL. Isto tako ako dođeš u situaciju da moraš da napraviš izmene u kodu trigera moraćeš prvo da ga obrišeš pa da napraviš novi - ne postoji edit. I na kraju najbitniji argument protiv trigera - migracija. Ako se ikada odlučiš da odradiš migraciju na neku drugu platformu sa trigerima si u startu pečen. PostgreSQL taj deo odrađuje neuporedivo bolje ali situacija je takva da ako rešenje danas ne poseduje podršku za MySQL u startu je osuđeno na propast. Forumski softver je neverovatno komplikovan sistem i super je što si za projekat odabrao tako prakričnu stvar. Ako istraješ naučiš jako puno bitnih stvari o optimizaciji softvera - od optimizovanja koda i upita pa sve do donošenja pravih arhitekturalnih odluka tipa izbora softvera i dizajniranja sistema. Samo da bi iscedio poslednju kap performansi iz koda. Ako zatreba još nešto od informacija slobodno pitaj. |
![]() |
![]() |
Sledećih 3 korisnika se zahvaljuje korisniku Neutrino na korisnoj poruci: | ||
![]() |
#8 |
Deo inventara foruma
Član od: 14.3.2008.
Lokacija: EHCPCGG
Poruke: 12.074
Zahvalnice: 4.305
Zahvaljeno 3.264 puta na 2.259 poruka
|
![]()
Čekaj, Neutrino, dakle u suštini preporučuješ da izbegavamo upotrebu triggera generalno kad god možemo?
|
![]() |
![]() |
![]() |
#9 | |
Deo inventara foruma
Član od: 17.6.2011.
Poruke: 7.302
Zahvalnice: 94
Zahvaljeno 3.312 puta na 1.997 poruka
|
![]() Citat:
Po čemu su onda skladišne procedure i funkcije bolje od trigera kad su isto tako "diskretne"? Po tome što one moraju eksplicitno da se pokrenu za razliku od trigera koji sve rade aurtomatski. |
|
![]() |
![]() |
Sledeći korisnik se zahvaljuje korisniku Neutrino na korisnoj poruci: | ||
doctor (1.8.2015) |
![]() |
#10 |
Veteran
Član od: 3.5.2008.
Lokacija: Beograd
Poruke: 760
Zahvalnice: 81
Zahvaljeno 213 puta na 144 poruka
|
![]()
Znači u redu je da na nivou aplikacije vodim računa o broju postova?
Aplikaciju pišem u Javi i ne radim direktno sa SQL-om nego koristim Spring Data JPA + Hibernate (ORM sistem). Izabrao sam to da skratim vreme razvoja i smanjim sebi muke, jer je ovo samo projekat za faks. Ali mogu da se pišu i specijalni upiti direktno u SQL-u za ovu priliku (čitanja i pisanja jednog polja u bazi). Sad, sledeće pitanje je način za vođenje računa o broju ulogovanih korisnika (za prikaz na index strani foruma) i prikazivanje oznake da li je korisnik ulogovan. Implementirao sam održavanje skupa username-ova ulogovanih korisnika (objekatu memoriji, ubacuje ime se kad se korisnik uloguje, a izbacuje se kad sesija istekne). Ovaj skup je na nivou aplikaciju. Čini mi se da bi trebalo tu da me brine multi thrading, tj. da bi trebalo da se sinronizuje upis. Za neregistrovane korisnike imam samo jedan integer brojač. |
![]() |
![]() |
![]() |
#11 |
Deo inventara foruma
Član od: 17.6.2011.
Poruke: 7.302
Zahvalnice: 94
Zahvaljeno 3.312 puta na 1.997 poruka
|
![]()
Svi "who's online" sistemi tako rade - broje se aktivne (neistekle) sesije koje se osvežavaju pri svakom novom zahtevu.
Što se multithreadinga tiče ne znam koji konkretno metod koristiš ali ne vidim zbog čega bi to trebalo da bude problem. Jednostavno pri svakom zahtevu osvežiš timestamp u sesiji samo za trenutnog korisnika i usput na kraju pokreneš čišćenje isteklih sesija iz memorije. |
![]() |
![]() |
![]() |
#12 |
Veteran
Član od: 3.5.2008.
Lokacija: Beograd
Poruke: 760
Zahvalnice: 81
Zahvaljeno 213 puta na 144 poruka
|
![]()
Sredio sam prikaz "who's online". Prikazuje se i broj registrovanih, neregistrovanih, ukupno i lista username-ova registrovanih koji su online. Za brojanje postova sam rešio sistem, bez trigger-a, samo još da popišem sva mesta u aplikaciji gde se on menja (brisanje i vraćanje posta, brisanje i vraćanje teme).
Rutine za prebrojavanje postova za jednog korisnika i za ceo forum sam za sada napisao kao SQL UPDATE upit (sa ugnježdenim SELECT COUNT) na tabeli korisnika. Nisam siguran da li je to u redu. Da li može da se napravi stored procedure sa iteracijom postova, ili ipak na nivou aplikacije. Za Moderatore: Može slobodno promena naslova teme u "Pitanja o radu forumskog softvera". Poslednja ispravka: ivan90BG (3.8.2015 u 14:07) |
![]() |
![]() |
![]() |
#13 |
Deo inventara foruma
Član od: 17.6.2011.
Poruke: 7.302
Zahvalnice: 94
Zahvaljeno 3.312 puta na 1.997 poruka
|
![]()
Vodi računa samo da MySQL ima užasne performanse kod kompleksnih upita. Kad god možeš razbij kompleksan upit na više prostih.
Što se tvog drugog pitanja tiče, većina softvera koristi klijentsko prebrojavanje. SMF za to recimo koristi tri upita, jedan za učitavanje podataka o korisnicima, drugi za učitavanje podataka o porukama za korisnika (koristi se GROUP BY da bi se rezultati grupisali po korisniku) i naravno jedan za update. |
![]() |
![]() |
![]() |
#14 |
Veteran
Član od: 3.5.2008.
Lokacija: Beograd
Poruke: 760
Zahvalnice: 81
Zahvaljeno 213 puta na 144 poruka
|
![]()
Imam jednu anegdotu sa posla koje sam se setio kad si pomenuo performanse MySQL-a kod kompleksnih upita. U vezi je Magento e commerce sistema (PHP). On ima neki sistem baze podataka, kad se nekom objektu tipa Product ili Basket doda novi atribut nekog tipa on vrednosti koje se upisuju baca u posebnu tabelu koja drži vrednosti svih novih atributa tog tipa za sve entitete, valjda da bi se izbeglo dodavanje kolona u postojeće tabele (ove tabele se posle prepakuju u normalniju konfiguraciju kad sajt ide online). Uglavnom on kada čita entitet iz baze mora da napravi join svih tih tabela, tako da su neki ljudi tokom razvoja na svojim lokalnim instalacijama imali problem jer MySQL ne može da uradi join više od 64 tabele
![]() |
![]() |
![]() |
![]() |
Bookmarks sajtovi |
Alatke vezane za temu | |
Vrste prikaza | |
|
|
![]() |
||||
tema | temu započeo | forum | Odgovora | Poslednja poruka |
Izjave Boli Glava | gorillaz23 | Cvet kompjutera | 31 | 31.10.2007 22:46 |
Broj poruka na ovom forumu... :))) | Patton | Forum o forumu | 33 | 27.11.2005 12:32 |