![]() |
![]() ![]() |
![]() |
![]()
Post
#1
|
|
![]() Grupa: Zarejestrowani Postów: 2 064 Pomógł: 1 Dołączył: 22.01.2003 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Więc po wielu próbach wymyśliliśmy, a raczej scanner wymyslił (i chwała mu za to
![]() [sql:1:b8f8130be6]CREATE TABLE `scan_userfriends` ( `userID` bigint(20) unsigned NOT NULL default '0', `friendID` bigint(20) unsigned NOT NULL default '0' ) TYPE=MyISAM;[/sql:1:b8f8130be6] natomiast problem wyciągania zapytań został rozwiązany następująco w 3 zapytaniach (tutaj dla uzytkownika nr 1): Zapytanie nr1 [sql:1:b8f8130be6]SELECT friendID FROM scan_userFriends WHERE userID = 1[/sql:1:b8f8130be6] po wyciagnieciu ID zapisujemy je do tablicy w php i następnie złączamy do postaci "1,45,85,296,904,10535,..." i wykonujemy kolejne zapytanie [sql:1:b8f8130be6]SELECT friendID FROM scan_userFriends WHERE userID IN(1,45,85,296,904,10535,...) AND friendID <> 1[/sql:1:b8f8130be6] Tera zapisujemy do innej tablicy wyniki tego zapytania (np. "3,1056,4352,9024,10466,14935,66043,...") i wykonujemy zapytanie [sql:1:b8f8130be6]SELECT friendID FROM scan_userFriends WHERE userID IN (3,1056,4352,9024,10466,14935,66043,...) AND userID NOT IN(1,45,85,296,904,10535,...) AND friendID <> 1[/sql:1:b8f8130be6] czyli pobieramy ID, których rodzicem są ID z drugiego zapytania i ale nie z pierwszego zapytania. Działa to bardzo sprawnie nawet na tabelach o bardzo duzej ilości rekordów, ale mimo to pomyślałem o keszowaniu wyników i wymyśliłem taką strukturę tabeli: [sql:1:b8f8130be6]CREATE TABLE `friends_cached` ( `userid` int(11) NOT NULL default '0', `friends` text NOT NULL, `friends_count` int(11) NOT NULL default '0', `cached` varchar(14) NOT NULL default '', PRIMARY KEY (`userid`) ) TYPE=MyISAM;[/sql:1:b8f8130be6] gdzie userid to numer ID użytkownika, friends to numery ID userów rozdzielone przecinkami, friends_count to liczba przyjaciół (żeby za każdym razem nie pobierać z tabeli z powiązaniami), a cached to pole zawierajace czas ostatniego uaktualnienia wyników. Kiedy będzie tabela uaktualniana: a) jeżeli od ostatniego keszowania minęło więcej niz 0,5 - 2 h (nie wiem ....) ![]() c) przy usunięciu użytkownika d) przy jakiejkolwiek innej zmianie, która wpływa na ilość znajomych Ponieważ uaktualnianie może mimo wszystko troche zająć to wymyśliłem takie rozwiązanie: wyświetlamy użytkownikowi strone, że za chwile zostanie przeniesiony na inną, potem przekierowyjemy go przez meta-refresh, a skrypt dalej sie wykonuje i wywołuje funkcję zapisującą dane. Jednocześnie z linkiem przekazujemy czas kiedy nastapiło keszowanie i na następnej stronie sprawdzamy czy w bazie pole "cached" ma taką wartość. Jeżeli tak to OK, jeżeli nie to wyświetlamy, że "prosze czekać" czy cos takiego... Co Wy na to?? Jake macie sugestie co do optymalizacji pierwszych 3 zapytań i w stosunku do keszowania? -------------------- |
|
|
![]()
Post
#2
|
|
![]() Grupa: Zarząd Postów: 3 503 Pomógł: 28 Dołączył: 17.10.2002 Skąd: Wrocław ![]() |
1. Trzeba przenieść[sql:1:b7637fdc89]AND friendID <> 1[/sql:1:b7637fdc89] do wewnątrz [sql:1:b7637fdc89]NOT IN ()[/sql:1:b7637fdc89]
2. Cacheowanie: pamiętaj, że jeśli u mojego przyjaciela zmieni się lista przyjacól, to trzeba by tez zaktualizować cahce mojej listy. -------------------- |
|
|
![]()
Post
#3
|
|
![]() Grupa: Zarząd Postów: 3 503 Pomógł: 28 Dołączył: 17.10.2002 Skąd: Wrocław ![]() |
Aha. Podaj jeszcze pliki add.php i inidex.php
![]() -------------------- |
|
|
![]()
Post
#4
|
|
![]() Grupa: Zarejestrowani Postów: 2 064 Pomógł: 1 Dołączył: 22.01.2003 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Cytat 2. Cacheowanie: pamiętaj, że jeśli u mojego przyjaciela zmieni się lista przyjacól, to trzeba by tez zaktualizować cahce mojej listy.
No właśnie też o tym pomyślałem i przestaje mi sie podobać takie rozwiązanie... Chyba, że po prostu założy się takie rozwiazanie, że odświeża się przy zmianie dane tylko dla użytkownika zmieniajacego, bo zgodnie z założeniami (które zostały wprowadzone juz w życie ![]() Dodawanie rekordów: [php:1:ccb685b3cb]<?php set_time_limit(0); ignore_user_abort(true); mt_srand(); $time=time(); $intMaxRepeat = 5000; $intRepeat = 0; $arrPairs = array(); do { do { $intMyID = mt_rand(1, $intMaxRepeat/5); $intFriendID = mt_rand(1, $intMaxRepeat/5); $blnPairsDuplicated = FALSE; if( isset($arrPairs[$intMyID]) && ($arrPairs[$intMyID]==$intFriendID) ) { $blnPairsDuplicated = TRUE; } else { $arrPairs[$intMyID]=$intFriendID; } } while ( ($intMyID == $intFriendID) && !$blnPairsDuplicated ); $q=mysql_unbuffered_query("INSERT INTO god_userfriends (userID, friendID) VALUES (".$intMyID.",".$intFriendID.")");# or die(mysql_error()); $intRepeat++; } while ( $intRepeat < $intMaxRepeat ); ?>[/php:1:ccb685b3cb] Wyciaganie rekordów: [php:1:ccb685b3cb]<?php set_time_limit(0); function MyImplode( $arrArray ) { if(sizeof($arrArray) > 1) { $strResult = @implode(',', $arrArray); } else { $strResult = $arrArray[0]; } return $strResult; } function Dump( $mixVar ) { echo '<pre>'; var_dump( $mixVar ); echo '</pre><hr />'; } function czas() { $t=explode(" ",microtime()); return($t[1]+$t[0]); } $myid=1; $sql="SELECT COUNT(userID) AS ilosc FROM god_userfriends "; $q=mysql_query($sql) or die(mysql_error()); $ilosc=mysql_result($q,0); # $sql="SELECT friendID FROM god_userfriends WHERE userID = ".$myid; $czas=czas(); $q=mysql_query($sql) or die(mysql_error()); echo sprintf("Czas wykonania pierwszego zapytania: %0.4f sekund<br>",czas()-$czas); while($t=mysql_fetch_array($q)) { $arrMyFriends[]=$t["friendID"]; } $arrMyFriendsSQL=myimplode($arrMyFriends); if(strlen($arrMyFriendsSQL)>=1) { $arrMyFriendsSQL=MyImplode($arrMyFriends); $sql="SELECT friendID FROM god_userFriends WHERE userID IN(".$arrMyFriendsSQL.") AND friendID <> ".$myid; $czas=czas(); $q=mysql_query($sql) or die(mysql_error()); echo sprintf("Czas wykonania drugiego zapytania: %0.4f sekund<br>",czas()-$czas); while($t=@mysql_fetch_array($q)) { $arrMyFriendsFriends[] = $t["friendID"]; } $arrMyFriendsFriendsSQL=MyImplode($arrMyFriendsFriends); if(strlen($arrMyFriendsFriendsSQL)>=1) { $sql="SELECT friendID FROM god_userFriends WHERE userID IN (".$arrMyFriendsFriendsSQL.") AND userID NOT IN(".$arrMyFriendsSQL.") AND friendID <> ".$myid; $czas=czas(); $q=mysql_query($sql) or die(mysql_error()); echo sprintf("Czas wykonania trzeciego zapytania: %0.4f sekund<br>",czas()-$czas); while($t=@mysql_fetch_array($q)) { $arrMyFriendsFriendsFriends[] = $t["friendID"]; } } } echo "<br>Przyjaciół na 1 poziomie: ".count($arrMyFriends)."<br>"; echo "Przyjaciół na 2 poziomie: ".count($arrMyFriendsFriends)."<br>"; echo "Przyjaciół na 3 poziomie: ".count($arrMyFriendsFriendsFriends)."<br>"; echo "Razem masz: "; echo count($arrMyFriends) + count($arrMyFriendsFriends) + count($arrMyFriendsFriendsFriends)." przyjaciół. <br>"; echo "Łączna ilość rekordów: ".$ilosc."<br>"; ?>[/php:1:ccb685b3cb] -------------------- |
|
|
![]()
Post
#5
|
|
![]() Grupa: Zarejestrowani Postów: 2 064 Pomógł: 1 Dołączył: 22.01.2003 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Hmm co do keszowania to wymysliłem troche inaczej: przy każdej zmianie danych (dodanie, usunięcie użytkownika itd) ustawiam dla jego rodzica czas ostatniej aktualizacji na 0, co spowoduje po zalogowaniu odświeżenie danych. Co o tym sądzicie?
-------------------- |
|
|
![]()
Post
#6
|
|
![]() Grupa: Zarząd Postów: 3 503 Pomógł: 28 Dołączył: 17.10.2002 Skąd: Wrocław ![]() |
No to już jepiej, ale powinieens przetrzepać całe drzewko od klienta do ostatniego rodzica rodzica rodzica..
-------------------- |
|
|
![]() ![]() |
![]() |
Wersja Lo-Fi | Aktualny czas: 19.07.2025 - 04:47 |