Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Jak pobrać (szybko) 12 losowych rekordów z tabeli?
Walian
post
Post #1





Grupa: Zarejestrowani
Postów: 124
Pomógł: 1
Dołączył: 13.07.2009

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


Zna ktoś jakiś szybki sposób na wybranie 12 losowych rekordów z tabeli, która może mieć nawet kilka milionów wierszy? Do tego biorąc pod uwagę, że będzie bardzo często odczytywana.

Najpierw próbowałem tego:
http://blog.desmart.com/2008/03/12/sposob-...-tablicy-mysql/
ale losuje mi 12 rekordów, tyle, że następujących po sobie jeden po drugim, czyli tak naprawdę losuje miejsce startowe, skąd ma pobrać kolejne rekordy. Nie umiem tego przerobić tak by wybrało 12 zupełnie przypadkowych rekordów.

Pomyślałem więc, że wylosuję w PHP ok. 50 liczb, i używając ich zadam zapytanie:
  1. SELECT * FROM tabela WHERE pole_id IN (liczba1,liczba2...)

Ale to mi nie daje gwarancji, że wybierze dokładnie 12 rekordów, bo przecież niektóre o podanych ID mogą nie istnieć. W sumie mogę tak wybierać rekordy aż uzyskam dokładnie 12 (bo to mała liczba) ale może zna ktoś jakiś lepszy sposób?
Go to the top of the page
+Quote Post
2 Stron V   1 2 >  
Start new topic
Odpowiedzi (1 - 19)
luki100011
post
Post #2





Grupa: Zarejestrowani
Postów: 243
Pomógł: 20
Dołączył: 20.04.2004
Skąd: Wielkopolska

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



Kod
SELECT * FROM tabela ORDER BY RAND() LIMIT 12
Go to the top of the page
+Quote Post
nospor
post
Post #3





Grupa: Moderatorzy
Postów: 36 561
Pomógł: 6315
Dołączył: 27.12.2004




@luki100011 zanim udzielisz jakze pomocnej odpowiedzi, przeczytaj najpierw co autor napisał...

W linku co podal metoda ta też jest podana. Jest też podane tam rownież dlaczego nalezy jej nie uzywac. Przeczytaj, wiedza ta moze ci sie przyda w przyszlosci
Go to the top of the page
+Quote Post
phpion
post
Post #4





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Może więc w PHP losuj 12 + X liczb, gdzie X to odpowiedni "zapas" jeśli danego artykuły by nie było. Następnie wybierasz rekordy z warunkiem IN (wylosowane_liczby) LIMIT 12. Jeśli dobierzesz odpowiednią wartość X (odpowiednio duża jeśli jest duże prawdopodobieństwo trafienia na "dziurę") to będziesz miał naprawdę pecha jeśli zapytanie nie zwróci Ci faktycznie 12 rekordów.
Go to the top of the page
+Quote Post
Mchl
post
Post #5





Grupa: Zarejestrowani
Postów: 855
Pomógł: 145
Dołączył: 17.07.2008
Skąd: High Memory Area

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


http://www.slideshare.net/billkarwin/sql-a...rns-strike-back

Od slajdu 141. Solution #4 całkiem sprytne.
Go to the top of the page
+Quote Post
nospor
post
Post #6





Grupa: Moderatorzy
Postów: 36 561
Pomógł: 6315
Dołączył: 27.12.2004




@Mchl Twoje rozwiązanie również pobiera 1 rekord.
Go to the top of the page
+Quote Post
phpion
post
Post #7





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




@Mchl:
Zgadza się, jest to dość sprytne rozwiązanie, ale w tym przypadku chyba nie do końca przypadnie autorowi do gustu. Jego minusem będzie to, że wybierze rekordy po kolei od zadanego (wylosowanego) punktu startowego.

@nospor:
Można przecież nadać ograniczenie, że liczba rekordów = rzeczywista liczba rekordów - limit i wtedy można pobrać X "losowych" rekordów.

Ten post edytował phpion 22.04.2010, 13:06:57
Go to the top of the page
+Quote Post
Mchl
post
Post #8





Grupa: Zarejestrowani
Postów: 855
Pomógł: 145
Dołączył: 17.07.2008
Skąd: High Memory Area

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


Jak zostosuje je dosłownie w takiej postaci jak przedstawiona to na pewno.
Ale kto mu broni wylosować 12 offsetów i złożyć przez UNION zapytanie 12 SELECTów?
Go to the top of the page
+Quote Post
phpion
post
Post #9





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




No tak, ale dochodzi tutaj kwestia liczby wykonanych zapytań oraz możliwość powstawania powtórzeń w wylosowanych rekordach.
Go to the top of the page
+Quote Post
nospor
post
Post #10





Grupa: Moderatorzy
Postów: 36 561
Pomógł: 6315
Dołączył: 27.12.2004




Cytat
Ale kto mu broni wylosować 12 offsetów i złożyć przez UNION zapytanie 12 SELECTów?
Ba.... nikt mu nie zabroni. Ale to mogl zrobic juz na samym początku przy rozwiązaniu ktore sam podał. A weź pobierz 12 losowych rekordów bez union i bez 12 zapytan.... (IMG:style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
Mchl
post
Post #11





Grupa: Zarejestrowani
Postów: 855
Pomógł: 145
Dołączył: 17.07.2008
Skąd: High Memory Area

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


Kod
SELECT COUNT(*) FROM test.t_option;

> 2000000


Kod
SELECT SQL_NO_CACHE * FROM test.t_option ORDER BY RAND() LIMIT 1;

2.1342s

Kod
SELECT SQL_NO_CACHE * FROM test.t_option LIMIT 1 OFFSET 653143;

0.3164s

Ten post edytował Mchl 22.04.2010, 13:16:05
Go to the top of the page
+Quote Post
nospor
post
Post #12





Grupa: Moderatorzy
Postów: 36 561
Pomógł: 6315
Dołączył: 27.12.2004




No i czemu te zestawienie ma sluzyc? Przeciez to oczywiste. Ba... nawet jest podane w pierwszym linku w pierwszym poscie. Jak to ma sie do 12 losowych rekordów bez UNION i bez 12 zapytan? (IMG:style_emoticons/default/smile.gif)
Go to the top of the page
+Quote Post
Mchl
post
Post #13





Grupa: Zarejestrowani
Postów: 855
Pomógł: 145
Dołączył: 17.07.2008
Skąd: High Memory Area

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


Ale dlaczego bez UNION? Skąd taki wymóg?
Go to the top of the page
+Quote Post
nospor
post
Post #14





Grupa: Moderatorzy
Postów: 36 561
Pomógł: 6315
Dołączył: 27.12.2004




oj... zmieniasz te fronty.. tu mi jakies wyniki, tu jakies zapytania i za kazdym razem unikasz odpowiedzi na pytanie (IMG:style_emoticons/default/winksmiley.jpg)

Cytat
Ale dlaczego bez UNION? Skąd taki wymóg?
zaden wymog. Wyjasniam ci jedynie ze UNION to on juz mogl uzyc na samym poczatku przy zapytaniu co podal. Zapytal sie jednak jak mozna to zrobic inaczej, a ty w odpowiedzi podales swoje zapytanie, inne, które tez pobiera jeden rekord.
Go to the top of the page
+Quote Post
phpion
post
Post #15





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Swoją drogą: czy przypadkiem rozwiązanie z IN (1, 2, 3) nie będzie przypadkiem szybsze? Przyznam, że wynik dla drugiego zapytania (0.3164s) jakoś szczególnie mnie nie powalił swą szybkością. Czy mógłbyś wykonać zapytanie z kilkoma identyfikatorami w IN?
Go to the top of the page
+Quote Post
nospor
post
Post #16





Grupa: Moderatorzy
Postów: 36 561
Pomógł: 6315
Dołączył: 27.12.2004




@phpion ale przeciez dla IN musisz podac np. konkretne ID. A o dziurach nie slyszal? (IMG:style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
phpion
post
Post #17





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Cytat(nospor @ 22.04.2010, 14:22:45 ) *
@phpion ale przeciez dla IN musisz podac np. konkretne ID. A o dziurach nie slyszal? (IMG:style_emoticons/default/winksmiley.jpg)

Cytat(phpion @ 22.04.2010, 13:07:52 ) *
Może więc w PHP losuj 12 + X liczb, gdzie X to odpowiedni "zapas" jeśli danego artykuły by nie było. Następnie wybierasz rekordy z warunkiem IN (wylosowane_liczby) LIMIT 12. Jeśli dobierzesz odpowiednią wartość X (odpowiednio duża jeśli jest duże prawdopodobieństwo trafienia na "dziurę") to będziesz miał naprawdę pecha jeśli zapytanie nie zwróci Ci faktycznie 12 rekordów.

(IMG:style_emoticons/default/party.gif)
Go to the top of the page
+Quote Post
nospor
post
Post #18





Grupa: Moderatorzy
Postów: 36 561
Pomógł: 6315
Dołączył: 27.12.2004




ps: tak, czytalem twoje poprzednie posty o prawdopodobienstwu - nie podoba mi sie ta teoria (IMG:style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
phpion
post
Post #19





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




No mi generalnie również nie do końca bo zawsze może się zdarzyć przypadek, gdy zapytanie zwróci 0 rekordów (wylosujemy same "dziury"). Jednak wybieranie rekordów po PK powinno być zdecydowanie szybsze niż wycinanie danego fragmentu ze zbioru - stąd moja prośba do Mchl o wykonanie zapytania i podanie wyniku.
Go to the top of the page
+Quote Post
Mchl
post
Post #20





Grupa: Zarejestrowani
Postów: 855
Pomógł: 145
Dołączył: 17.07.2008
Skąd: High Memory Area

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


Wszystkie metody opierające się na losowaniu wartości klucza głównego zakłądają, że klucz główny jest ciągły.
Jeśli nie jest, to na przykład zapytanie podane w linku w pierwszym poście, raz na jakiś czas zwróci 0 wierszy. Czy to dopuszczalne? Pewnie jak się ma tego świadomość i dobrze obsłuży to tak.

Jeżeli wywołanie pierwszego zapytania tyle razy żeby uzyskać dokładnie 12 wierszy będzie w 99,99% szybsze niż wywołanie 12 razy rozwiązania podanego przeze mnie, to chyba wiadomo jaki jest wybór.

@phpion: niestety akurat ta tabela nie ma klucza głównego auto_increment, więc trudno byłoby zrobić porównanie. Niewątpliwie jednak, wybieranie po PK będzie szybsze. Pytanie tylko, jak często losując wartość PK trafiamy na wartość rzeczywiście istniejącą.

Ten post edytował Mchl 22.04.2010, 13:30:32
Go to the top of the page
+Quote Post

2 Stron V   1 2 >
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.12.2025 - 16:36