Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> wybieranie losowo rekordów i wydajność, 2 pytania :)
anskellig
post
Post #1





Grupa: Zarejestrowani
Postów: 12
Pomógł: 0
Dołączył: 6.04.2008

Ostrzeżenie: (0%)
-----


Witam

To mój pierwszy post tutaj, ale zdążyłem zauważyć jak przydatne jest to forum - niejednokrotnie mi pomagało. Ale do rzeczy.

1. Pytanie nr 1: Chcę pobrać losowy rekord z bazy... jak to zrobić? Robię tak:

"SELECT * FROM baza ORDER BY rand() LIMIT 1";

Ale podobno używanie rand() nie jest wydajne.
Może wydajniej byłoby tak:

$pozycja = rand(0,$ilosc_rekordow); // tutaj wcześniej trzeba by dać zapytanie zliczające rekordy
"SELECT * FROM baza LIMIT $pozycja,1";

Która opcja lepsza?

2. Pytanie nr 2: jeśli powiecie, żebym sam sprawdził co będzie wydajniejsze, to jak to zrobić?

$przed = microtime();
$query = "SELECT * FROM baza ORDER BY rand() LIMIT 1";
$result = mysql_query($query);
$po = microtime();
$czas = $po - $przed;

W ten sposób będzie dobrze?

Dzięki za sugestie.
Pozdrawiam

Ten post edytował anskellig 6.04.2008, 21:52:01
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 13)
mike
post
Post #2





Grupa: Przyjaciele php.pl
Postów: 7 494
Pomógł: 302
Dołączył: 31.03.2004

Ostrzeżenie: (0%)
-----


Metoda 1. odpada, jest jak już wspomniałeś bardzo wolna. Metoda 2. jest całkiem niezłym wyjściem ale najszybsza jest ...
... a co się będę powielał (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) Selecting random record from MySQL database table
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #3





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


Fajne, fajne, ale mozna by sie czepic rozkladu prawdopodobienstwa (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) Czesciej beda wybierane rekordy ktore maja przed soba dziure - brakujacych IDkow (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
SongoQ
post
Post #4





Grupa: Przyjaciele php.pl
Postów: 2 923
Pomógł: 9
Dołączył: 25.10.2004
Skąd: Rzeszów - studia / Warszawa - praca

Ostrzeżenie: (0%)
-----


@dr_bonzo Doczytaj dokladnie tu nie chodzi o ID. @mike Ciekawe przyklady podales, chociaz ten COUNT dla bardzo duzej ilosci moze roznie dzialac (wolno)
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #5





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


SongoQ: no rzeczywiscie, w metodzie 3. wszystko jest ok, ale pozostale maja nadal nierowny rozklad (pomijajac ofkorz 1.)
Go to the top of the page
+Quote Post
anskellig
post
Post #6





Grupa: Zarejestrowani
Postów: 12
Pomógł: 0
Dołączył: 6.04.2008

Ostrzeżenie: (0%)
-----


Dzięki za odpowiedzi.

A czy ta 3 metoda (ta najszybsza) nie jest praktycznie taka sama jak moja druga? (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) Ja też używam w niej LIMIT $offset, 1 (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Tylko że mój $offset jest wyliczany przez rand() w PHP. Możliwe więc, że wychodzi podobnie wydajnie (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg) W sumie ja jeszcze dokładam jedno zapytanie zliczające rekordy.
Może w ogóle niepotrzebnie się tym martwię, bo moja tabela nie będzie raczej nigdy większa niż kilka tysięcy rekordów.

A jeszcze co do tej 3 metody...
$offset_result = mysql_query( " SELECT FLOOR(RAND() * COUNT(*)) AS `offset` FROM `table` ");
Co robi to FLOOR(RAND()*COUNT(*)) ? Dlaczego rand()*count(*) ?

Ten post edytował anskellig 7.04.2008, 19:00:57
Go to the top of the page
+Quote Post
guitarnet.pl
post
Post #7





Grupa: Zarejestrowani
Postów: 74
Pomógł: 4
Dołączył: 7.03.2008

Ostrzeżenie: (0%)
-----


nie ma co strzelac do muchy z armaty (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)
po prostu w jezyku ktorego uzywasz do obslugi mysql wygeneruj losowa liczbe z zakresu twoich id np min = 1, max = 9876
dla php uzyj rand() i wynik wstaw w zapytanie SQL wtedy mysql otrzyma dokladne zapytanie a funkcja rand() w php jest szybka!!

jak nie znasz min i max dla twojego ID w tabeli, cachuje je, cachowanie to podstawowa metoda w nowoczesnym programowaniu, odczytuj je np przy kazdej akcji usuwania /dodawania zawartosci tabeli i zapisuj do pliku php w postaci
<?
$min = 1;
$max= 9876;
?>

i include('./cachowany_plik.php');
dziala blyskawicznie!

oczywiscie metode cachowania dobierz do rodzaju twojegfo serwisu najbardziej optymalnie
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #8





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


Tja - keszowanie takiej pierdoly. Juz duzo latwiej przekleic gotowa SQLke i dostosowac do swoich nazw kolumn niz implementowac takie cache.

w sensie ze niepotrzebmie komplikuje aplikacje, i to jest raczej ta armata (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

Ten post edytował dr_bonzo 8.04.2008, 05:25:26
Go to the top of the page
+Quote Post
anskellig
post
Post #9





Grupa: Zarejestrowani
Postów: 12
Pomógł: 0
Dołączył: 6.04.2008

Ostrzeżenie: (0%)
-----


To chyba zostanę przy tej metodzie:

$pozycja = rand(0,$ilosc_rekordow); // tutaj wcześniej trzeba by dać zapytanie zliczające rekordy
"SELECT * FROM baza LIMIT $pozycja,1";

Zamiast cachowania więc, będzie zapytanie zliczające rekordy. Dla tabeli o kilku tys. rekordów chyba nie będzie to obciążeniem. Cache'owanie wydaje mi się jednak tą armatą jak pisze poprzednik (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
guitarnet.pl
post
Post #10





Grupa: Zarejestrowani
Postów: 74
Pomógł: 4
Dołączył: 7.03.2008

Ostrzeżenie: (0%)
-----


ta ostatnia metoda niczym nie rozni sie od mojej, i tak musisz znac min i max id tabeli, a co jak wygenerujesz liczbe losowa spoza zakresu?

cachowanie brzmi skomplikowanie i powaznie ale to powsechnie uzywana praktyka
Go to the top of the page
+Quote Post
Kicok
post
Post #11





Grupa: Zarejestrowani
Postów: 1 033
Pomógł: 125
Dołączył: 17.09.2005
Skąd: Żywiec

Ostrzeżenie: (0%)
-----


Cytat
a co jak wygenerujesz liczbę losowa spoza zakresu?


No właśnie to twój sposób się na tym wykłada. Co jeśli w bazie będę miał takie dane:
Kod
+------+
|  ID  | (...)
+------+
|   1  |
|   2  |
|   5  |
|   7  |
|   8  |


a rand" title="Zobacz w manualu PHP" target="_manual zwróci mi: 3?
Go to the top of the page
+Quote Post
anskellig
post
Post #12





Grupa: Zarejestrowani
Postów: 12
Pomógł: 0
Dołączył: 6.04.2008

Ostrzeżenie: (0%)
-----


Cytat(guitarnet.pl @ 8.04.2008, 14:25:12 ) *
ta ostatnia metoda niczym nie rozni sie od mojej, i tak musisz znac min i max id tabeli, a co jak wygenerujesz liczbe losowa spoza zakresu?

Jeśli zrobię tak:

$pozycja = rand(0,$ilosc_rekordow);
"SELECT * FROM baza LIMIT $pozycja,1";

To rand() nie wylosuje liczby spoza zakresu (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) Wszystko chyba OK. Tylko dodatkowe zapytanie zliczające ilość rekordów trzeba dać.
Go to the top of the page
+Quote Post
guitarnet.pl
post
Post #13





Grupa: Zarejestrowani
Postów: 74
Pomógł: 4
Dołączył: 7.03.2008

Ostrzeżenie: (0%)
-----


racja, nie pomyslalem o braku id z zadanego zakresu, twoja metoda zdecydowanie lepsza
Go to the top of the page
+Quote Post
Sedziwoj
post
Post #14





Grupa: Zarejestrowani
Postów: 793
Pomógł: 32
Dołączył: 23.11.2006
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


Cytat(dr_bonzo @ 7.04.2008, 01:03:35 ) *
SongoQ: no rzeczywiscie, w metodzie 3. wszystko jest ok, ale pozostale maja nadal nierowny rozklad (pomijajac ofkorz 1.)


Wiesz jak chcesz losowo więcej niż jeden, to wybierasz losowo pulę i z niej losowo tyle ile chcesz, wielkość puli też opiera się na zliczaniu krotek i offset więc nie ma różnicy jaki jest rozkład ID w tabeli. Co prawda rozrzut nie będzie duży takich wyborów, ale jak na razie nie widziałem lepszego. (zawsze można dodać dodatkową indeksowaną kolumnę z random i po niej sortować lol wtedy nowe krotki mogą wpadać do starych pul)
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 22.08.2025 - 12:44