Kom ihåg mig?
Home Menu

Menu


Mysql random verkar inte vara tillräckligt bra?

 
Ämnesverktyg Visningsalternativ
Oläst 2015-09-10, 15:35 #1
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
Question Mysql random verkar inte vara tillräckligt bra?

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.
naak2803 är inte uppkopplad   Svara med citatSvara med citat
Oläst 2015-09-10, 23:37 #2
Cos Cos är inte uppkopplad
Flitig postare
 
Reg.datum: Apr 2007
Inlägg: 307
Cos Cos är inte uppkopplad
Flitig postare
 
Reg.datum: Apr 2007
Inlägg: 307
Skapa en array med med unika IDn att hämta istället kanske? Validera att den innehåller unika värden innan sql frågan ställs.
Så har jag gjort och funkat helt OK.

Dock är jag osäker på vilken metod som mest resurskrävande, men de lär vara hugget som stucket på en mindre skala.
Cos är inte uppkopplad   Svara med citatSvara med citat
Oläst 2015-09-11, 00:46 #3
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
- Slumpa random
– Samma rad ska inte dyka upp flera ggr i samma fråga.
De låter snarare som att din query är lite knasig om samma fråga dyker upp flera gånger då ja tvivlar på att RND-funktionen inte skulle vara uniform.

Kan du posta hela queryn?

Citat:
Ursprungligen postat av Cos Visa inlägg
Skapa en array med med unika IDn att hämta istället kanske? Validera att den innehåller unika värden innan sql frågan ställs.
Så har jag gjort och funkat helt OK.

Dock är jag osäker på vilken metod som mest resurskrävande, men de lär vara hugget som stucket på en mindre skala.
Nej, de är en riktigt långsam lösning.
Nerix är inte uppkopplad   Svara med citatSvara med citat
Oläst 2015-09-11, 08:41 #4
allstars allstars är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Apr 2006
Inlägg: 2 126
allstars allstars är inte uppkopplad
Klarade millennium-buggen
 
Reg.datum: Apr 2006
Inlägg: 2 126
långsam eller inte, så känns den lösningen bättre;

Kod:
SELECT ID FROM dbo.quiz WHERE category = 445 LIMIT 20 ORDER BY RND()
Om du ställer samma fråga flera gånger (i phpmyadmin eller motsvarande), blir det ofta att samma frågor återkommer?

Jag skulle nog ställa en fråga för att hämta alla 20 frågors ID, spara dem i en session och när de behövs hämta all fråge-data.
allstars är inte uppkopplad   Svara med citatSvara med citat
Oläst 2015-09-11, 09:42 #5
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:
Om du ställer samma fråga flera gånger (i phpmyadmin eller motsvarande), blir det ofta att samma frågor återkommer?
Exakt, det är just det som är problemet, inte att den inte slumpar slumpmässigt utan att om man ställer samma fråga flera ggr så är det oftast samma frågor som dyker upp, fast det finns 1000 frågor att välja mellan.
naak2803 är inte uppkopplad   Svara med citatSvara med citat
Oläst 2015-09-11, 09:47 #6
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 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.
Som flera andra redan har varit inne på, gör på följande sätt:
1) Hämta unika fråge-id:n från databasen:
Kod:
SELECT id FROM dbo.quiz WHERE category = 445
2) Slumpa och begränsa dessa i ditt applikationslager (php, asp, jsp, etc).

3) Hämta sedan frågorna via ytterligare en SQL:
Kod:
SELECT column1, column2, etc... FROM dbo.quiz WHERE id in (1, 7, 32, 94, etc...)
Du får visseligen en ytterligare fråga till databasen men resultatet från den kan du enkelt cacha i ditt applikationslager.
coredev är inte uppkopplad   Svara med citatSvara med citat
Oläst 2015-09-11, 14:28 #7
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
Citat:
Ursprungligen postat av naak2803 Visa inlägg
Exakt, det är just det som är problemet, inte att den inte slumpar slumpmässigt utan att om man ställer samma fråga flera ggr så är det oftast samma frågor som dyker upp, fast det finns 1000 frågor att välja mellan.
Förmodligen beror det isåfall antingen på någon cache på SQL-frågan, dock tror jag standardlösningen med inbyggda query cache ska inaktiveras automatiskt vid en RAND(). Alternativt är MySQL en version där RAND() var buggat.

Vidare har du, förutsatt att du använder MySQL av något sånär modernt snitt, inte postat din riktiga query varpå det blir svårt att hjälpa till:
- RND() är ingen inbyggd funktion i MySQL
- LIMIT kan inte läggas innan ORDER BY

Vidare är det väldigt ineffektivt sätt att hämta slumpmässiga rader att köra en SELECT * FROM ... ORDER BY RAND() LIMIT x. Queryn behöver göra en full table scan och skalar därmed inte alls. För att göra den 50 ggr effektivare kan du lösa det med en subquery där du kör en SELECT <primary key> FROM table ORDER BY RAND() LIMIT x varpå du iallalfall bara behöver läsa hela primärnyckeln (oftast från minnet). Men vill du faktiskt göra det effektivt får du titta på riktigt alternativ istället - Googla "order by rand() alternatives" och hitta en metod som fungerar i ditt case.
Clarence är inte uppkopplad   Svara med citatSvara med citat
Oläst 2015-09-11, 14:31 #8
jayzee jayzee är inte uppkopplad
Har WN som tidsfördriv
 
Reg.datum: Aug 2008
Inlägg: 1 089
jayzee jayzee är inte uppkopplad
Har WN som tidsfördriv
 
Reg.datum: Aug 2008
Inlägg: 1 089
Här har du en bra artikel samt förslag på bäst approach: http://akinas.com/pages/en/blog/mysql_random_row/
jayzee är inte uppkopplad   Svara med citatSvara med citat
Oläst 2015-09-11, 15:29 #9
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
Citat:
Ursprungligen postat av jayzee Visa inlägg
Här har du en bra artikel samt förslag på bäst approach: http://akinas.com/pages/en/blog/mysql_random_row/
Bra artikel kan diskuteras.

Hans "snabbaste lösning" är fullkomligt förskräcklig prestanda på när tabellen växer om den är InnoDB, men funkar säkert bra med MyISAM. Varför han har fått så skevt resultat framkommer inte men är det på grund av att han har ett lågt antal rader så bör hela testet ses som helt värdelöst.

Intressant nog verkar han lika ointresserad eller ovetande om det som att en jämförelse blir helt irrelevant om man inte gör den med olika antal rader/mängd data för tidsjämförelsen. Liksom man verkligen MÅSTE ange tabelltyp så fort man skriver en COUNT(*) i en benchmark för att det ska ge något över huvudtaget.

Lösning 2 och 4 kan dock ses som OK kompromisser i de flesta fall, även om man förlorar precision om man har gaps i sin primärnyckel. Och nej, lita inte på artikelns resultat för #2 - den är inte 5 ggr långsammare än #3 utan mycket snabbare - i de allra flesta fall.
Clarence är inte uppkopplad   Svara med citatSvara med citat
Oläst 2015-09-11, 23:39 #10
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 coredev Visa inlägg
Som flera andra redan har varit inne på, gör på följande sätt:
1) Hämta unika fråge-id:n från databasen:
Kod:
SELECT id FROM dbo.quiz WHERE category = 445
2) Slumpa och begränsa dessa i ditt applikationslager (php, asp, jsp, etc).

3) Hämta sedan frågorna via ytterligare en SQL:
Kod:
SELECT column1, column2, etc... FROM dbo.quiz WHERE id in (1, 7, 32, 94, etc...)
Du får visseligen en ytterligare fråga till databasen men resultatet från den kan du enkelt cacha i ditt applikationslager.
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.
Nerix ä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 21:19.

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