Avatar billede plbrennet Nybegynder
01. juni 2009 - 20:34 Der er 6 kommentarer

Hvordan vælger man en tilfældig række?

Jeg har en stor tabel med omtrent en lille million rækker i hvorfra jeg gerne vil hive en helt tilfældig række ud. Hvordan gør jeg det? Det er til at vise et tilfældigt link (gemt i en tabel over links) på en webside og da websiden har mange besøgende skal det gå hurtigt med at finde den tilfældige række. Nogen forslag?
Avatar billede ksoren Nybegynder
01. juni 2009 - 20:37 #1
det afhænger af hvilken database det er
Avatar billede acore Ekspert
01. juni 2009 - 20:47 #2
I SQL kan du bruge

SELECT * FROM table ORDER BY RAND() LIMIT 1
Avatar billede jb123 Nybegynder
01. juni 2009 - 21:10 #3
acore's forslag vil simpelthen lægge dit site ned fordi dette query evalueres ved først at generere knap en million tilfældige tal, hvilket er dræbende langsomt, dernæst sortere alle rækkerne efter de genererede tilfældige tal og sidst udvælge netop 1 række. Se f.eks. execution planen for queryet.

Jeg svarede på samme spørgsmål på Kuneco.com (pææænt lækker side med generelt super gode svar, by the way) for ikke så længe siden:
  http://kuneco.com/viewthread/364
(de grønne svar)

Bemærk, at spørgeren her også først har forsøgt med "order by random()", hvilket faktisk er en hyppig fejl. Hvis det skal gå tjept og det hele skal kunne skalere bliver man simpelthen nødt til at kunne finde række gennem et indexeret point query. Alt, der involverer seq scans vil lægge enhver semipopulær side ned.
Avatar billede acore Ekspert
01. juni 2009 - 22:12 #4
Jeg kan sagtens se jb123's argumenter, og jeg havde tydeligvis hverken læst eller forstået spørgsmålet ordentligt.

Hvis alle rækker har et id kan du generere et tilfældigt tal (fx i php) og så vælge den:

$mysql_query("SELECT * FROM tabel WHERE id = '".rand(1, 1000000)."'");

I praksis skal 1000000 erstattes med det eksakte antal rækker.
Avatar billede jb123 Nybegynder
01. juni 2009 - 22:19 #5
Det mener jeg heller ikke vil virke i praksis af to årsager:

  1) det kræver at man kender antallet af rækker. En "count(*) from ..." evalueres i praksis ved et komplet scan (index- eller seq scan). Det kan (bør) man ikke gøre ved hvert eneste query og hvis man vil gøre det periodevist inducerer man unødig kompleksitet i applikationen, unødigt performance drop ved optællingen og nye rækker vil ikke blive udtaget.

  2) det antager, at man ikke sletter rækker fra tabellen for hvis man gør det vil det tilfældige tal kunne ramme en slettet række. Denne antagelse er unødvendig.
Avatar billede acore Ekspert
02. juni 2009 - 23:05 #6
Ad 1) Det var bevidst, at jeg ikke havde lagt en optælling af rækkerne ind. Det bør gøre mere "intelligent". Det fremgår ikke af sammenhængen om antallet kan ændre sig.

Ad 2) Det er jo ikke sikkert, der slettes rækker. Og hvis der gør kunne man bruge max id, og bare lave en ny forespørgsel, hvis der ikke var noget match.

Så jo, det kan virke i praksis. Selv om din løsning måske er mere elegant, så må denne være mindre ressource-krævende, da der ikke skal være en permanent kolonne med de tilfældige tal.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester