Subqueries - goed idee?

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Kris Peeters

Kris Peeters

26/01/2012 17:20:21
Quote Anchor link
Subqueries maken het gemakkelijk om lastige queries te maken. De vraag is: moet je subqueries proberen te vermijden? Zorgen die voor veel vertraging / veel verbinding / ...?

----

Even een voorbeeldje en wat uitleg, om de nuttigheid te illustreren.
Stel, je hebt een tabel (klassement) met punten van voetbalploegen. 1 record per ploeg - 1 record bevat het totaal aantal punten van 1 ploeg.

En dan wil je uit de top 10 (bv. uit 24 ploegen in het totaal) willekeurig drie ploegen selecteren.

Mocht je een tabel hebben waarin de top 10 staat, al in volgorde, was het gemakkelijk:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
SELECT ploeg, punten
FROM top_10_in_volgorde
ORDER BY RAND()
LIMIT 3


Maar die tabel heb je uiteraard niet. Je hebt een tabel met 24 ploegen, niet in volgorde van punten.
Wat echter leuk is, is dat het resultaat van een select-query op zich ook een tabel is. Je kunt die ook gebruiken als subquery.

De tabel top_10_in_volgorde kunnen we zo vormen:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
SELECT ploeg, punten
FROM klassement
ORDER BY punten DESC
LIMIT 10


Samen maakt dat dus:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
SELECT ploeg, punten
FROM
  (SELECT ploeg, punten
  FROM klassement
  ORDER BY punten DESC
  LIMIT 10) AS top_10_in_volgorde
ORDER BY RAND()
LIMIT 3


Simpel he.

----

Dus ja ... proberen te vermijden, of niet?
Graag geargumenteerd/gedocumenteerd.
Gewijzigd op 26/01/2012 17:21:08 door Kris Peeters
 
PHP hulp

PHP hulp

16/11/2019 22:08:57
 
Jacco Brandt

Jacco Brandt

26/01/2012 17:27:40
Quote Anchor link
Je moet juist zoveel mogelijk subqueries gebruiken, dit verminderd het aantal keer dat je een aanvraag naar de database moet sturen.

Wat je wél moet vermijden is ORDER BY RAND(). Dit is zeer inefficient, en kun je beter door PHP later doen.
 
Noppes Homeland

Noppes Homeland

26/01/2012 18:36:04
Quote Anchor link
Quote:
Je moet juist zoveel mogelijk subqueries gebruiken, dit verminderd het aantal keer dat je een aanvraag naar de database moet sturen.

Daar moet je wat genuanceerder in zijn en wat betreft het ORDER BY RAND() ook. Je geeft nu een verkeerd beeld af in mijn ogen.


Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT   a.id
,     b.naam
FROM     (SELECT id
          FROM   flop) a
INNER JOIN (SELECT naam,ida
            FROM  flup) b
        ON a.id = b.ida

SELECT   a.id
,     b.naam
FROM     flop a
INNER JOIN flup b
        ON a.id = b.ida

Jij suggeerd dus, dat de eerste query de gewenste is en dat je de tweede query maar beter achterwege kan laten. Vandaar dat ik schrijf dat je genuanceerde moet zijn, in de hoop dat je begrijpt waar het hier om draait.

En wat betreft het gegeven voorbeeld, zal ik als volgt aanpakken:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
create view toptienvw as
SELECT ploeg, punten
  FROM klassement
  ORDER BY punten DESC
  LIMIT 10

create view randdrievantoptienfvw as  
select ploeg
,      punten
from   toptienvw
order by
       rand()

dan heb je ook nog iets aan de subquery, dat is dan 2 vliegen in 1 klap.

Het ligt er maar helemaal aan wat er al aan gegevens aanwezig is, en wat er dan eventueel nog opgehaald moet worden om tot het gewenste resultaat te komen.

Als je de toptienvw geggevens al hebt, dan heb je waarschijnlijk ook al de rand van 3, gezien de toegepaste script logica.

Als je de toptienvw gegevens niet nodig hebt maar alleen de rand 3 van toptienvw dan haal je die gegevens zo efficient mogelijk op.

Let wel: er is in feite niets tegen op subqueries mits deze goed sq slim geimplementeerd worden. En je past subqueries - zoals dit voorbeeld -:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9

SELECT ploeg, punten
FROM
  (SELECT ploeg, punten
  FROM klassement
  ORDER BY punten DESC
  LIMIT 10) AS top_10_in_volgorde
ORDER BY RAND()
LIMIT 3

pas toe als het echt niet anders kan, wat nu dus het geval is.
 
Ger van Steenderen
Tutorial mod

Ger van Steenderen

26/01/2012 19:07:35
Quote Anchor link
Is dit (zoals jacco al zegt) niet beter in php te doen? Dus de top tien ophalen met de query en dan daar een random op los te laten?
 
Aad B

Aad B

26/01/2012 20:05:16
Quote Anchor link
@Ger: Dubbel werk en dus per definitie niet beter. a) Je haalt teveel data op en b) dat ga je dan weer processen in een andere omgeving. Veel en soms heel erg veel data ophalen en processen in array's is de meest gemaakte ontwikkelfout in php. Over het algemeen komt dat door een gebrek aan SQL kennis en het performance kennis van MySQL. Subqueries zijn prima en kunnen volop toegepast worden. Heb je te maken met veel data (tienduizenden records) ga dan na hoe je query plan is en probeer dat te optimaliseren ipv te processen in php. Ontwerp indexen waar nodig en zorg dus altijd dat er indexed (unique) scans, index range scans zijn en zorg voor de juiste primairy en foreign keys zodat joins efficient afgehandeld worden! Al eens een query plan gechecked? http://dev.mysql.com/doc/refman/5.0/en/explain.html
Gewijzigd op 26/01/2012 20:09:36 door Aad B
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.