Kom ihåg mig?
Home Menu

Menu


Mysql random verkar inte vara tillräckligt bra?

 
Ämnesverktyg Visningsalternativ
Oläst 2015-09-12, 12:47 #11
naak2803 naak2803 är inte uppkopplad
Mycket flitig postare
 
Reg.datum: Jun 2011
Inlägg: 767
naak2803 naak2803 är inte uppkopplad
Mycket flitig postare
 
Reg.datum: Jun 2011
Inlägg: 767
Citat:
Ursprungligen postat av Nerix Visa inlägg
En dålig och ickeskalbar lösning som dessutom introducerar ett nytt problem; cache invalidation. Databasen är designad för att snabbt lösa just sådana här problem.

Enklast är om TS bara postar hela sin query. Hen gör förmodligen någon märklig JOIN vilket ställer till problem.

SELECT * FROM tp_question INNER JOIN tp_exam_tp_question ON tp_question.Id=tp_exam_tp_question.tp_questionsId WHERE tp_examId = 445 ORDER BY RAND() LIMIT 50
naak2803 är inte uppkopplad   Svara med citatSvara med citat
Oläst 2015-09-12, 12:56 #12
Nerix Nerix är inte uppkopplad
Flitig postare
 
Reg.datum: Oct 2010
Inlägg: 398
Nerix Nerix är inte uppkopplad
Flitig postare
 
Reg.datum: Oct 2010
Inlägg: 398
Citat:
Ursprungligen postat av naak2803 Visa inlägg
SELECT * FROM tp_question INNER JOIN tp_exam_tp_question ON tp_question.Id=tp_exam_tp_question.tp_questionsId WHERE tp_examId = 445 ORDER BY RAND() LIMIT 50
Nu vet jag inte exakt hur dina nycklar och data ser ut, så kan bara gissa. Me när du joinar med `tp_exam_tp_question` så dyker `tp_question.Id` förmodligen upp ett flertal gånger. Du väljer sedan slumpmässigt från frågor (tp_question.Id) som finns med fler gånger än andra i tabellen.

Vi kan verifiera min teori genom att du postar resultatet från följande query.

Kod:
SELECT tp_question.Id FROM tp_question INNER JOIN tp_exam_tp_question ON tp_question.Id=tp_exam_tp_question.tp_questionsId WHERE tp_examId = 445 ORDER BY tp_question.Id ASC LIMIT 50
Se till att välja ett `tp_examId` så att du får med så många resultat som möjligt så att vi kan se att duplikat följer med.

Notera att en GROUP BY inte är lösning på din problem.
Nerix är inte uppkopplad   Svara med citatSvara med citat
Oläst 2015-09-13, 22:24 #13
tec tec är inte uppkopplad
Medlem
 
Reg.datum: Mar 2010
Inlägg: 54
tec tec är inte uppkopplad
Medlem
 
Reg.datum: Mar 2010
Inlägg: 54
Citat:
Ursprungligen postat av naak2803 Visa inlägg
Hej,
jag har en quiz-motor med över 1000 frågor.
Men jag tycker inte att SQL-satsen fungerar dåligt och med dåligt menar jag att den inte slumpar tillräckligt slumpmässigt... Har ni några andra förslag?

Kod:
SELECT * FROM dbo.quiz WHERE category = 445 LIMIT 20 ORDER BY RND()
Krav som jag har:
- Slumpa random
– Samma rad ska inte dyka upp flera ggr i samma fråga.
Så pass lite data att du lika gärna kan plocka ut alla rader och kasta om dem utanför Mysql. RAND() är otroligt slö.

Kod:
<?php
$data = mysql_fetch_object("SELECT * FROM dbo.quiz WHERE category = 445");
shuffle($data);
$results = array_slice($data, 0, 20);
tec är inte uppkopplad   Svara med citatSvara med citat
Oläst 2015-09-13, 23:09 #14
Nerix Nerix är inte uppkopplad
Flitig postare
 
Reg.datum: Oct 2010
Inlägg: 398
Nerix Nerix är inte uppkopplad
Flitig postare
 
Reg.datum: Oct 2010
Inlägg: 398
Citat:
Ursprungligen postat av tec Visa inlägg
Så pass lite data att du lika gärna kan plocka ut alla rader och kasta om dem utanför Mysql. RAND() är otroligt slö.

Kod:
<?php
$data = mysql_fetch_object("SELECT * FROM dbo.quiz WHERE category = 445");
shuffle($data);
$results = array_slice($data, 0, 20);
Din lösning är per definition ännu slöare. RAND() räkna alla element innan några väljs ut vilket tar O(n) tid. Din lösning kräver också O(n) läsningar + tiden det tar att hämta och skicka informationen mellan server och klient + bearbetning av datan.
Nerix är inte uppkopplad   Svara med citatSvara med citat
Oläst 2015-09-14, 08:09 #15
coredevs avatar
coredev coredev är inte uppkopplad
Bara ett inlägg till!
 
Reg.datum: Sep 2007
Inlägg: 1 554
coredev coredev är inte uppkopplad
Bara ett inlägg till!
coredevs avatar
 
Reg.datum: Sep 2007
Inlägg: 1 554
Citat:
Ursprungligen postat av Nerix Visa inlägg
En dålig och ickeskalbar lösning som dessutom introducerar ett nytt problem; cache invalidation. Databasen är designad för att snabbt lösa just sådana här problem.
Jag förstår din poäng, men alla lösningar behöver inte vara skalbara. Hur många frågor kan OP förväntas ha?

Min arkitekturella utgångspunkt är att databasen skall göra så lite som möjligt - bättre att den gör det den är bra på och så låter man applikationslagret sköta resten. Enligt mig är OPs fall ett gränsfall, kanske är MySQL:s RAND-funktion bra nog för just detta fallet men i det stora hela är RAND inte designad för att skapa slumpmässiga tal av hög kvalité: "RAND() is not meant to be a perfect random generator. It is a fast way to generate random numbers on demand that is portable between platforms for the same MySQL version."
coredev är inte uppkopplad   Svara med citatSvara med citat
Oläst 2015-09-14, 09:26 #16
Clarence Clarence är inte uppkopplad
Administratör
 
Reg.datum: Jan 2003
Inlägg: 1 974
Clarence Clarence är inte uppkopplad
Administratör
 
Reg.datum: Jan 2003
Inlägg: 1 974
För att illustrera lite hur pass dåliga de dåliga lösningarna faktiskt är. Kört med 7 miljoner ca 100-150 byte rader i en InnoDB tabell på en medelmåttig hårdvara, med en kraftig maskin kan man förvänta sig 20-50% av exekveringstiden:

Exekveringstid ca 15s.
Kod:
SELECT * FROM table ORDER BY RAND() LIMIT 1
Exekveringstid ca 15s. Detta ger inga random-rader men används i vissa, riktigt dåliga, alternativ till ORDER BY RAND().
Kod:
SELECT count(*) FROM table
Exekveringstid 0.02s. Kräver primary key (behöver inte heta id). Ger sämre resultat med större gaps i PK. Måste köras en gång per rad för hyfsad randomness (även om det givetvis går att kombinera i en query). Kan ge kopior varpå man måste ha kod för att hämta fler frågor om man får kopior. För många rader kan det effektiviseras ordentligt genom att lyfta ut id-generation (antingen i en stored procedure eller i kod).
Kod:
SELECT *
FROM table
WHERE id >= FLOOR(1 + RAND() * (SELECT MAX(id) FROM table))
LIMIT 1
Detta är inte de enda alternativen utan bara en illustration till hur enorm skillnad det gör. Problemet med att använda ORDER BY RAND() ligger inte i hur pass exakt RAND() är utan hur pass fruktansvärd prestandan är vid ORDER BY RAND() på något annat än ett VÄLDIGT litet resultset.
Clarence är inte uppkopplad   Svara med citatSvara med citat
Oläst 2015-09-14, 12:01 #17
tec tec är inte uppkopplad
Medlem
 
Reg.datum: Mar 2010
Inlägg: 54
tec tec är inte uppkopplad
Medlem
 
Reg.datum: Mar 2010
Inlägg: 54
Citat:
Ursprungligen postat av Nerix Visa inlägg
Din lösning är per definition ännu slöare. RAND() räkna alla element innan några väljs ut vilket tar O(n) tid. Din lösning kräver också O(n) läsningar + tiden det tar att hämta och skicka informationen mellan server och klient + bearbetning av datan.
Körs totalt på 0.01s, 1000 rader motsvarande quizfrågor. Undviker att använda RAND(), som i sig är slö och som TS hade problem med.
tec är inte uppkopplad   Svara med citatSvara med citat
Oläst 2015-09-14, 15:28 #18
linusoleander linusoleander är inte uppkopplad
Medlem
 
Reg.datum: Feb 2010
Inlägg: 234
linusoleander linusoleander är inte uppkopplad
Medlem
 
Reg.datum: Feb 2010
Inlägg: 234
Citat:
Ursprungligen postat av tec Visa inlägg
Körs totalt på 0.01s, 1000 rader motsvarande quizfrågor. Undviker att använda RAND(), som i sig är slö och som TS hade problem med.
Värt å tillägga är att din lösning inte löser problemet då de verkar som att TS query returnerar dubletter. De är således inget fel på RAND() utan queryn i sig.
linusoleander är inte uppkopplad   Svara med citatSvara med citat
Svara


Aktiva användare som för närvarande tittar på det här ämnet: 1 (0 medlemmar och 1 gäster)
 

Regler för att posta
Du får inte posta nya ämnen
Du får inte posta svar
Du får inte posta bifogade filer
Du får inte redigera dina inlägg

BB-kod är
Smilies är
[IMG]-kod är
HTML-kod är av

Forumhopp


Alla tider är GMT +2. Klockan är nu 20:05.

Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson
 
Copyright © 2017