[php/mysql] Random een grote lijst uit database halen

Pagina: 1
Acties:
  • 124 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Gerwin
  • Registratie: Juli 2001
  • Laatst online: 08-06 20:10

Gerwin

Ik ben er klaar voor!

Topicstarter
Het volgende is het geval. Ik heb een 5 tal tabellen in een mysql database staan. Deze tabellen staan in een soort van boomstructeur met elkaar gekoppeld. In de totale database komen zo met een meer op alles koppeling op ruim 1 miljoen rijen. In de grootste tabel staan ruim 30.000 records.

Ik wil uit het gehaal nu random (RAND()) een selectie doen. Tot nu deed ik dit heel simpel via de RAND funcitie in mysql, maar dit begint resources te vergen, daarbij er toch elke 2-3 seconden een dergelijke selectie naar de database gestuurd wordt. (tijden van 2-3 seconden execute tijd is geen uitzondering).

Hoe kan je dmv een betere selectie deze data toch random uit de database halen?

Ik heb geprobeerd:

1. Koppelingen maken en dan uiteindelijk RAND()

2. alle tabellen left join doen aan elkaar en dan RAND()

3. via een JOIN waarin een subquery gedaan word

SELECT ROUND( RAND( ) * (
SELECT MAX( id )
FROM linx ) ) AS id
) AS r2

en dan onderaan in WHERE een id >= r2.id

hier krijg ik echter maar steeds 1 record terug en moet dus voor meerdere (soms honderden honderd maal een selectie op die manier doen

4 Maximale bepalen en per php een aantal getallen krijgen (bijvoorbeeld 100 of 200) en die allemaal opnemen in WHERE. Dus WHERE id=101 OR id =3211 OR id = 121 etc.

Wat is de beste optie,zijn er misschien nog andere?

Station van Gerwin Prins op Apple Music


Acties:
  • 0 Henk 'm!

  • ripexx
  • Registratie: Juli 2002
  • Laatst online: 17:49

ripexx

bibs

Wat bedoel je in dit geval met random uit 5 tabellen. Zeker als er een boom is, gaat het dan om 5 uit de totale mogelijk dataset (1 miljoen records) om een random selectie uit de hoofdtabel. Verder begrijk ik niet wat je bedoeld met een grote lijst. Wil je de ene keer 10 records en de andere keer 10.000 records terug hebben? En wat betreft je laatste query, je kan ook IN gebruiken.
SQL:
1
2
3
4
5
6
7
8
9
10
SELECT veld 
FROM iets 
WHERE ietsanders = 101
     OR ietsanders = 103 
     OR ietsanders = 104 
     OR ietsanders = 106;

SELECT veld 
FROM iets 
WHERE ietsanders IN (101, 103, 104, 106);

buit is binnen sukkel


Acties:
  • 0 Henk 'm!

  • Gerwin
  • Registratie: Juli 2001
  • Laatst online: 08-06 20:10

Gerwin

Ik ben er klaar voor!

Topicstarter
Ik heb bijvoorbeeld de volgende tabellen (er zijn er meer maar dit is het idee):

Hoofdtabel
hoofd-id INT
hoofd-tekst

koppeltabel 1
koppel1-id
hoofd-id

data tabel 1
koppel1-id
data1

koppeltabel 2
koppel2-id
hoofd-id

data tabel 2
koppel2-id
data2

overige
hoofd-id
overigetekst

rest
hoofd-id
resttekst

In alle tabellen zijn de gelijke velden aan elkaar gekoppeld.

Ik wil uit de gehele database (dus alle mogelijke combinaties die er dan zijn) een selectie hebben zegge 200 rows random. Eentje zou ook kunnen, maar dan moet ik dus 200 query's sturen. Ik had liever andere mogelijkheid gehad.

Er is als ik hoofdid=1 doe niet zeker hoeveel (als er al) records terugkomen.

Station van Gerwin Prins op Apple Music


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
lama. niet goed gelezen ;)

[ Voor 84% gewijzigd door Michali op 21-10-2006 13:51 ]

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Ik snap nog niet wat je precies wilt eigenlijk.

Maar als je een relatief klein aantal random waarden uit een grote set wilt hebben en je id's zijn altijd in een gesloten reeks ( Dus er missen er geen ) dan kan je denk het best in php al de id's random genereren en dan gewoon selecteren door SELECT * FROM bla where id in ( .... ).

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Varienaja
  • Registratie: Februari 2001
  • Laatst online: 14-06 16:43

Varienaja

Wie dit leest is gek.

Ik heb ook zo'n soort probleem gehad, sterker nog: als een item eenmaal geselecteerd was mocht dat later niet nog eens gebeuren.

Anyway, de procedure is als volgt:
Maak een lijst van alle ID's.
Selecteer random items uit die lijst.
Selecteer de bijbehorende records uit de database.

Omdat een lijst met alle id's nogal groot kan worden kan je ook hopen dat alle id's aansluiten. In dat geval hoef je alleen de max(id) te weten.

Als je het allemaal in sql wilt oplossen moet je volgens mij (en ik heb lang gezocht) in alle gevallen rekening houden met een full table scan.

[ Voor 14% gewijzigd door Varienaja op 21-10-2006 14:31 ]

Siditamentis astuentis pactum.


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Varienaja schreef op zaterdag 21 oktober 2006 @ 14:30:
Ik heb ook zo'n soort probleem gehad, sterker nog: als een item eenmaal geselecteerd was mocht dat later niet nog eens gebeuren.

Anyway, de procedure is als volgt:
Maak een lijst van alle ID's.
Selecteer random items uit die lijst.
Selecteer de bijbehorende records uit de database.

Omdat een lijst met alle id's nogal groot kan worden kan je ook hopen dat alle id's aansluiten. In dat geval hoef je alleen de max(id) te weten.

Als je het allemaal in sql wilt oplossen moet je volgens mij (en ik heb lang gezocht) in alle gevallen rekening houden met een full table scan.
Als je het volledig in SQL wilt doen kom je denk idd niet om een full table scan heen. Met 1 miljoen records kan dat natuurlijk nogal lang gaan duren.

Ik zou gewoon eerst een query doen om MAX( id ) op te vragen en dan random een waarde tussen de 0...MAX( id ) selecteren ( eventueel meteen meerdere tegelijk ). Als je dan niet genoeg ( of geen ) records terug krijgt doe je het gewoon nogmaals.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Gerwin
  • Registratie: Juli 2001
  • Laatst online: 08-06 20:10

Gerwin

Ik ben er klaar voor!

Topicstarter
Dat met die MAX(id) leek me ook de beste, en dan op basis daarvan een record pakken uit de hoofdtabel en vervolgens daar alle subtabellen aanplakken met join. Echter kom ik dan nu op een execute time uit van 0,05 secs, omdat ik random een lijst van 100 of 200 wil hebben moet ik vervolgens wel 100-200 query's sturen allemaal met dezelfde query om telkens een random te krijgen.

Station van Gerwin Prins op Apple Music


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Je kan toch ook random 100-200 id's pakken en dan
SQL:
1
2
3
4
5
SELECT ...
FROM Table t
INNER JOIN Table2 t2
    ON t.id = t2.id
WHERE t.id IN( 1, 2, 3, 4, 5 ... )

Dan kijk je of je genoeg response krijgt en als dat niet zo is dan doe je het eventueel nog een keer. Bij de 2e keer kan je natuurlijk controleren of je dat random id al de vorige keer gebruikt hebt.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • StevenK
  • Registratie: Februari 2001
  • Laatst online: 19:39
Als jij elke 2,3 seconden en random over zoveel regels wilt doen, dan zit er volgens mij iets mis in je datamodel.

Ik zou, zoals hierboven al aangegeven, zorgen dat die records waarover jij een random wilt doen, allemaal een uniek opvolgend nummer hebben en dan met een
code:
1
select * where id in (<reeks van random id's)

die dingen ophalen.

Mijn gevoel zegt me dat het verstandig is om naast je databasemodel een aparte platte tabel te maken en daaruit die selectie te doen, dat zal veel sneller zijn dan steeds weer opnieuw die enorme join uit te voeren.

Was advocaat maar vindt het juridische nog steeds leuk


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
De vraag is idd wat de reden is dat je dit wilt doen. Mischien is er wel een andere mooiere en snellere oplossing voor

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”

Pagina: 1