![]() |
![]() |
![]()
Post
#1
|
|
![]() Grupa: Zarejestrowani Postów: 286 Pomógł: 12 Dołączył: 23.11.2006 Skąd: WL Ostrzeżenie: (0%) ![]() ![]() |
Mam pewien problem z wylosowaniem wyników z bazy.
Próbuje wylosować 3 wyniki obok obecnie przeglądanego filmiku ale przy tym zapytaniu wyżej filmiki nonstop się powtarzają nie wiem jak to zrobić zmienna $video jest to id obecnie przeglądanego filmiku Z góry dziękuje za pomoc Dobra znalazłem już odpowiedź
Tylko że jest drugi problem z użyciem order by rand() przy kilku set tysiącach rekordów zapytanie może się wykonywać kilkanascie sekund tak wyczytałem. A to mnie nie ustawia ponieważ nie chcę zmulać bazy danych. Zna ktoś bardziej optymalne metody? |
|
|
![]() |
![]()
Post
#2
|
|
![]() Grupa: Zarejestrowani Postów: 12 Pomógł: 0 Dołączył: 15.06.2008 Skąd: Kołaczyce Ostrzeżenie: (0%) ![]() ![]() |
Wyciąg łączną liczbę filmików z bazy danych, wygeneruj dowolną liczbę z przedziału 0,$liczbafilmów i wrzuć do zapytania zamiast order by rand(),
Kod $podobnesql = "SELECT id, nazwa, obraz, nick, views FROM filmiki WHERE idkategori='$idcat' and id<>'$video' LIMIT $losowaliczba,4"; Gdzie $losowaliczba to wygenerowana liczba. Jaka różnica w stosunku do rand? Taka, że pierwszy filmik będzie losowy, a następne trzy, takie, jakie następują po pierwszym, zależnie od sortowania. Troszkę więcej kombinacji, ale przy tych kilkuset tysiącach rekordów, zysk jest. Funkcja rand() musi przeszukać wszystkie rekordy z tabeli, zanim zwróci Ci te cztery pożądane. Korzystając klauzuli LIMIT, od razu mówimy, czego chcemy. -------------------- :)
|
|
|
![]()
Post
#3
|
|
![]() Grupa: Zarejestrowani Postów: 286 Pomógł: 12 Dołączył: 23.11.2006 Skąd: WL Ostrzeżenie: (0%) ![]() ![]() |
Problem jest w tym że funkcja rand kopiuje do tymczasowej tabeli i nadaje wartości z czego wybiera jeden za długo to trwa przy większej ilości rekordów a mi zależy na optymalnym skrypcie. Twoja odpowiedź nie rozwiązuje mojego problemu ponieważ muszą to być przypadkowe rekordy niezalezne od niczego.
Ten post edytował szmerak 12.12.2010, 10:13:11 |
|
|
![]()
Post
#4
|
|
![]() Grupa: Zarejestrowani Postów: 2 958 Pomógł: 574 Dołączył: 23.09.2008 Skąd: wiesz, że tu jestem? Ostrzeżenie: (0%) ![]() ![]() |
|
|
|
![]()
Post
#5
|
|
![]() Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
@CuteOne:
Gratulacje. Powielasz ORDER BY RAND(), a do tego dodajesz DISTINCT. Brakuje jeszcze jakiegoś iloczynu kartezjańskiego i będzie wypas. @szmerak: Zastosuj ideę ~bartek124, lepszego rozwiązania nie znajdziesz. Jeśli chcesz otrzymać np. 3 rekordy zupełnie losowe to pobierz łączną liczbę rekordów w tabeli, a następnie wylosuj 3 liczby z przedziału 0..n (albo n-1). Następnie wykonaj 3 zapytania w stylu podanym przez ~bartek124 łącząc je w jeden zbiór wyniku poprzez UNION. |
|
|
![]()
Post
#6
|
|
Grupa: Zarejestrowani Postów: 200 Pomógł: 38 Dołączył: 1.12.2010 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
Metoda sprawdzona jako około 10% szybsza od naturalnego losowania przez rand mimo wykonania subquery. Odpowiedź dostosowałem do przykładu wyżej:
Dzięki temu, że tablica tymczasowa generowana przez ORDER BY RAND() posiada tylko dwie kolumny czyli id i wartość losową po której odbędzie się sortowanie zachodzi znacznie szybciej, niż dla całej przepisanej tablicy, którą trzeba posortować. Mimo, że jest to użycie subquery wyciągające losowe id dla miliona wygenerowanych przeze mnie losowych rekordów uzyskuje 10% szybszy czas wykonania. Jednak wciąż nie jest to rozwiązanie wystarczające. Powiem tylko że wyciąganie ilości elementów i później losowanie 3 z zakresu 0 do $max jest bezsensowne niestety... Jaka pewność, że połowa elementów nie została usunięta wewnątrz? Wtedy między wyznaczonym zakresem będzie luka, która może zostać wylosowana i przekazana do bazy danych. -------------------- Warsztat: NetBeans 7.2 Beta, PHP, MySQL, PostgreSQL, Symfony (<=1.4), Diem, Java, Sieci neuronowe
|
|
|
![]()
Post
#7
|
|
Grupa: Zarejestrowani Postów: 226 Pomógł: 61 Dołączył: 20.08.2010 Ostrzeżenie: (0%) ![]() ![]() |
Cytat Powiem tylko że wyciąganie ilości elementów i później losowanie 3 z zakresu 0 do $max jest bezsensowne niestety... Jaka pewność, że połowa elementów nie została usunięta wewnątrz? Wtedy między wyznaczonym zakresem będzie luka, która może zostać wylosowana i przekazana do bazy danych. Nie chodzi o losowanie liczb z zakresu MIN_ID..MAX_ID, tylko z zakresu 0..NUM_ROWS-1 (gdzie NUM_ROWS to liczba wierszy spełniających warunki) i wstawienie do zapytania:
-------------------- |
|
|
![]()
Post
#8
|
|
Grupa: Zarejestrowani Postów: 200 Pomógł: 38 Dołączył: 1.12.2010 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
Nie chodzi o losowanie liczb z zakresu MIN_ID..MAX_ID, tylko z zakresu 0..NUM_ROWS-1 (gdzie NUM_ROWS to liczba wierszy spełniających warunki) i wstawienie do zapytania:
Wybacz, mój błąd. Zrozumiałem, że polecacie wyciąganie ostatniego ID i losowanie od 1 do tego maksa. -------------------- Warsztat: NetBeans 7.2 Beta, PHP, MySQL, PostgreSQL, Symfony (<=1.4), Diem, Java, Sieci neuronowe
|
|
|
![]() ![]() |
![]() |
Wersja Lo-Fi | Aktualny czas: 19.07.2025 - 19:36 |