Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [mysql] wybieranie losowego wpisu
Forum PHP.pl > Forum > Bazy danych > MySQL
Force
Witam

Na początku zaznaczam że szukałem na forum i nic nie znalazłem więc jeżeli było to proszę o linka

Pobieram z bazy danych losowe wpisy takim pytaniem:
"SELECT * FROM obrazki ORDER BY RAND() LIMIT 10"
Niestety przy 400 wpisach pytanie wykonuje się ok 0.2s
Czy jest jakiś szybszy sposób na to?
Cezar708
Cytat
RAND() is not meant to be a perfect random generator, but instead is a fast way to generate ad hoc random numbers which is portable between platforms for the same MySQL version.
(źródło)


więc używanie rand() samo w sobie nie jest efektywne. Nie wiem jaki rodzaj danych masz w tej tabeli ale myślę, że lepszym rozwiązaniem byłoby gdzieś zkacheowanie wszystkich ID do tablicy w pliku PHP i potem z niej na poziomie PHP losować id i dać zapytanie:

  1. SELECT *
  2. FROM obrazki WHERE id_obrazka IN ( 12, 142, 195, 543, 834, 2345 ,.... i tak dalej...


Funkcje losującą identyfikatory ze skeszowanej tablicy PHP można łatwo napisać za pomocą funkcji int rand ( [int $min, int $max] )
Force
Mam mniej więcej taką tabelę
  1. CREATE TABLE `obrazki` (
  2. `pid` int( 11 ) NOT NULL AUTO_INCREMENT ,
  3. `aid` int( 11 ) NOT NULL DEFAULT '0',
  4. `filepath` varchar( 255 ) NOT NULL DEFAULT '',
  5. `filename` varchar( 255 ) NOT NULL DEFAULT '',
  6. `filesize` int( 11 ) NOT NULL DEFAULT '0',
  7. `title` varchar( 255 ) NOT NULL DEFAULT '',
  8. PRIMARY KEY ( `pid` ) ,
  9. KEY `owner_id` ( `owner_id` ) ,
  10. ) ENGINE = MyISAM DEFAULT CHARSET = latin2

Ma ktoś jakiś pomysł jak to zrobić inaczej?
Cytat
Nie wiem jaki rodzaj danych masz w tej tabeli ale myślę, że lepszym rozwiązaniem byłoby gdzieś zkacheowanie wszystkich ID

Czyli mam wybrać wszystkie identyfikatory obrazków?
  1. SELECT pid FORM obrazki


I jeszcze jedno pytanie:
Czy funkcja array_rand zapewnia to, że wybrane elementy tablicy nie będą się powtarzać?
nevt
ja bym to spróbował zrobić na 2 zapytaniach, pierwsze
  1. SELECT COUNT(*) FROM `obrazki`;

zakładając, że w zmiennej $count mamy wynik pierwszego zapytania, budujemy w PHP drugie:
  1. <?php
  2. $random = rand(0, $count -);
  3. $sql = "SELECT * FROM `obrazki` LIMIT $random, 1;";
  4. ?>

dla dużych ilości danych nie widzę wydajniejszej metody... nie wymaga przesyłania dużych ilości danych ani sortowania tablic, nie wymaga zakładania specjalnych indeksów w tabeli z której losujemy... życie byłoby jeszcze prostsze, gdyby klauzula LIMIT w MySQL dopuszczała jako parametr coś innego niż stałą liczbową, wtedy można by to zrobić w jednym zapytaniu.

pozdrawiam.
Force
nevt: Tylko, że ja wyciągam z bazy ponad 10 wpisów a to pytanie: "SELECT * FROM `obrazki` LIMIT $random, 1;" przy 4000 wpisach wykonywało się prawie tyle samo co wyciągnięcie 10 wpisów z pomocą RAND()
Cezar708
Cytat(Force @ 16.01.2008, 21:26:37 ) *
Czyli mam wybrać wszystkie identyfikatory obrazków?
  1. SELECT pid FROM obrazki

tak i zapisz je w jakiejś tablicy. Jeśli dane w tabeli się często nie zmieniają warto by było taką tablicę gdzieś w pliku PHP po prostu zapisać

Cytat(Force @ 16.01.2008, 21:26:37 ) *
I jeszcze jedno pytanie:
Czy funkcja array_rand zapewnia to, że wybrane elementy tablicy nie będą się powtarzać?


W zasadzie to nie zapewnia, ale zawsze możesz sprawdzać, czy dana wartość jest w tablicy (in_array), jest to trochę dłuższe...

Ewentualnie jeśli liczba tych wylosowanych obrazków nie jest krytycznie ważna to możesz posłużyć się statystyką. Czyli w zależności od liczby rekordów losujesz na przykład 12 i robisz zapytanie:

  1. SELECT DISTINCT * -- DISTINCT, żeby rekordy się nie powtarzały
  2. FROM obrazki WHERE pid IN ( (i tu te przykładowe 12 wartości )
  3. LIMIT 10 -- żeby w razie jak wszystkie wartości są różne to aby tylko 10 pierwszych wyników zabrać
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.