Post
#1
|
|
|
Grupa: Zarejestrowani Postów: 6 809 Pomógł: 1828 Dołączył: 11.03.2014 Ostrzeżenie: (0%)
|
Witajcie,
zna ktoś może inny sposób niż zopytmalizowany ORDER BY RAND() poprzez ID>=FLOOR(1+RAND()*MAX(ID)) ? Chodzi o to, że metoda ma mankament przy nieciągłości ID. Przykładowo: ID 126 0 134 0,666666667 136 0,833333333 137 0,916666667 138 1 Jak z tego wynika pierwsze ID wpada w połowę dolnego przedziału. Ostatecznie zastosowałem PHP, ale być może zna ktoś rozwiązanie na poziomie SQL. |
|
|
|
![]() |
Post
#2
|
|
|
Grupa: Moderatorzy Postów: 36 561 Pomógł: 6315 Dołączył: 27.12.2004 |
Najlepszy bylby limit, ale do tego musisz uzyc jeszcze php
- zliczasz liczbę rekordów - na podstawie liczby rekordów losujesz liczbę z zakresu 1:liczba rekordów. Robisz to w php przy pomocy rand() - mając wylosowaną liczbę ($losowa) pobierasz wylosowany rekord ze swojej tabeli przy uzyciu limit SELECT * FROM `tabela` WHERE limit $losowa,1 |
|
|
|
Post
#3
|
|
|
Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%)
|
Podstawowe pytanie: jakiej mniej-więcej wielkości jest pula rekordów spośród których chcesz losować wiersz? Jeżeli jest ona względnie niewielka zwykłe ORDER BY RAND() jest jak najbardziej poprawnym rozwiązaniem. Jeżeli jednak tych rekordów jest sporo skorzystaj z rozwiązania zasugerowanego przez @nospor.
Ten post edytował Crozin 6.08.2014, 10:28:21 |
|
|
|
Post
#4
|
|
|
Grupa: Zarejestrowani Postów: 6 809 Pomógł: 1828 Dołączył: 11.03.2014 Ostrzeżenie: (0%)
|
|
|
|
|
Post
#5
|
|
|
Grupa: Zarejestrowani Postów: 420 Pomógł: 44 Dołączył: 22.10.2008 Ostrzeżenie: (0%)
|
a co jest w $arr wszystkie rekordy z tabeli?
|
|
|
|
Post
#6
|
|
|
Grupa: Moderatorzy Postów: 36 561 Pomógł: 6315 Dołączył: 27.12.2004 |
@trueblue ale w swoim rozwiązaniu musisz pobrac wszystkie rekordy do php co jest bez sensu
|
|
|
|
Post
#7
|
|
|
Grupa: Zarejestrowani Postów: 8 068 Pomógł: 1414 Dołączył: 26.10.2005 Ostrzeżenie: (0%)
|
|
|
|
|
Post
#8
|
|
|
Grupa: Zarejestrowani Postów: 6 809 Pomógł: 1828 Dołączył: 11.03.2014 Ostrzeżenie: (0%)
|
|
|
|
|
Post
#9
|
|
|
Grupa: Moderatorzy Postów: 36 561 Pomógł: 6315 Dołączył: 27.12.2004 |
Pry 50 rekordach order by rand nie powinno mulic i byc wolniejsze od tego co robisz w php.
Ale z ciekawosci można by sprawdzić. ps: tak rozumiem, ze musiales sie tego pozbyc bo ci kazali. Ale to wyglada teraz tak, jakbys jednego "zamulacza" zamienial na drugiego (IMG:style_emoticons/default/wink.gif) ps2: jesli bedziesz robil testy to dorzuc tez moją wersję. Kto wie co moze wyjsc przy tak malej liczbie rekordow (IMG:style_emoticons/default/smile.gif) @Pyton a niby w czym mialo pomoc Twoje zapytanie? Przeciez tam ciagle jest order by RAND |
|
|
|
Post
#10
|
|
|
Grupa: Zarejestrowani Postów: 8 068 Pomógł: 1414 Dołączył: 26.10.2005 Ostrzeżenie: (0%)
|
W tym że pobiera tylko jedną kolumnę ID, która jest kluczem
|
|
|
|
Post
#11
|
|
|
Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%)
|
@trueblue: Jeżeli masz raptem 50 rekordów spośród których chcesz losować to ORDER BY RAND() pewnie będzie najszybszym rozwiązaniem. Masz w ogóle jakieś konkretne powody by myśleć, że to właśnie to zapytanie odpowiedzialne jest za problemy z wydajnością? Czy tylko ktoś zobaczył ten fragment kodu i od razu uznał, że to musi być powodem wszystkich problemów?
|
|
|
|
Post
#12
|
|
|
Grupa: Zarejestrowani Postów: 1 421 Pomógł: 310 Dołączył: 18.04.2012 Ostrzeżenie: (0%)
|
rownie dobrze mozesz zrobic
ale z obserwacji wynika, ze crc32 jest nieco szybsze Ma to taka zalete, ze jesli zapiszesz sobie gdzies current_timestamp, to mozesz odtworzyc kolejnosc. Tak samo jak w ORDER BY Rand(parametr) |
|
|
|
Post
#13
|
|
|
Grupa: Moderatorzy Postów: 36 561 Pomógł: 6315 Dołączył: 27.12.2004 |
@Pyton faktycznie masz racje. Pobranie jednej kolumny dla order by rand jest o niebo szybsze niz wszystkich. Testowalem na 500tys rekordow. Wszystkie losowal w 15 sekund, jedną w pol sekundy
ps: rozwiązanie podane przez mmmmmmm jest bardzo ciekawe i dla 500tys rekordow trwa rowniez ok. pol sekundy i można pobrac od razu wszystkie dane bez joinowania |
|
|
|
Post
#14
|
|
|
Grupa: Zarejestrowani Postów: 6 809 Pomógł: 1828 Dołączył: 11.03.2014 Ostrzeżenie: (0%)
|
1. Moja metoda
2. Nospor ze znikomym opóźnieniem, praktycznie ex aequo 3. ID>=FLOOR(1+RAND()*MAX(ID)) ok. 33% wolniejsze 4. Pyton_000 ok. 57% wolniejsze 5. mmmmmm ok. 62% wolniejsze Crozin, nie z kodu, z logów, ale nie mam pojęcia jakich, nie wierzę, że ze slowlog. P.S. Być może na tysiącach rekordów wynik byłby zupełnie inny. Ten post edytował trueblue 6.08.2014, 11:32:07 |
|
|
|
Post
#15
|
|
|
Grupa: Moderatorzy Postów: 36 561 Pomógł: 6315 Dołączył: 27.12.2004 |
Nom, przy malej liczbie rekordow miejsca 1 i 2 mogly tak sie klasowac. Przy wiekszej bylaby juz znaczaca roznica. No ale jesli faktycznie masz tam tylko 50 rekordow to nie ma co sie szczypac.
|
|
|
|
Post
#16
|
|
|
Grupa: Zarejestrowani Postów: 8 068 Pomógł: 1414 Dołączył: 26.10.2005 Ostrzeżenie: (0%)
|
Jeżeli różnica rzędu 0.03 to taka wielka różnica (IMG:style_emoticons/default/wink.gif)
Olałbym sprawę dla takiej małej ilości rekordów, bo faktycznie wykonywanie dziwactwa zajmie więcej czasu niż samo zapytanie. |
|
|
|
Post
#17
|
|
|
Grupa: Moderatorzy Postów: 36 561 Pomógł: 6315 Dołączył: 27.12.2004 |
@Pyton przy 50 rekordach nie ma co oczekiwac, ze roznice będą większe.
Zas przy 500 tysiacach, twoj skrypt wykonuje sie pol sekundy, moj 0,001s. Zas przy takiej liczbie rekordow (500 tys) rozwiązanie trueblue nie mialoby w ogole sensu. |
|
|
|
Post
#18
|
|
|
Grupa: Zarejestrowani Postów: 6 809 Pomógł: 1828 Dołączył: 11.03.2014 Ostrzeżenie: (0%)
|
Dziękuję wszystkim za zaangażowanie i pomysły.
|
|
|
|
Post
#19
|
|
|
Grupa: Zarejestrowani Postów: 8 068 Pomógł: 1414 Dołączył: 26.10.2005 Ostrzeżenie: (0%)
|
Można jeszcze taką magią:
Minus taki że nie może być dziur. Ten post edytował Pyton_000 6.08.2014, 12:00:22 |
|
|
|
![]() ![]() |
|
Aktualny czas: 24.12.2025 - 22:55 |