17. oktober 2011 - 07:47 Der er 8 kommentarer og
1 løsning

Udførelses rækkefølgen i queries, LIMIT

Jeg er blevet rådgivet, sandsynligvis korrekt, om brug af LIMIT, men forklaringen gik på tværs af min egen, sandsynligvis fejlende, logik.  Fordi jeg har lettere ved at gøre noget jeg forstår søger jeg hjælp til forståelse.

Jeg har forstået, fra mit oprindelige SQL kursus for længe siden og fra googling her til morgen, at udførelses rækkefølgen af for eksempel en query med join mellem to tabeller (lad os sige Kunder og Ordrer,) logisk set, er denne: 

Først dannes der, virtuelt, en tabel der kombinerer alle rækker af Kunder med alle rækker af Ordrer.  Hvis Kunder har 5 kolonner og 25 rækker og Ordrer har 3 kolonner og 100 rækker får denne virtuelle tabel 8 kolonner og 2500 rækker. 

Fra denne virtuelle tabel beholdes de rækker der passer med Join klausulen, for eksempel at Kunder.id = Ordrer.kundeId.

Derefter beholdes de rækker der passer med WHERE klausulen, for eksempel de hvor Kunder.id = 253.  Og GROUP BY udføres hvis nødvendigt.

Når man så har de rigtige rækker, stadig med 8 kolonner, så beholdes de kolonner der svarer til SELECT klausulet.

Og til slut ORDER BY.

Men jeg har ikke kunnet finde noget om hvor LIMIT kommer ind.  Min (igen muligvis fejlende) logik siger mig, at LIMIT må komme aller sidst.  Hvis man beder om LIMIT 5 skulle man få de fem første rækker, ikke fem tilfældige rækker.  LIMIT 5 svarer jo til TOP 5 i mssql og andre systemer.  Og maskinen kan vel ikke vide hvilke rækker er de første før den har udført hele queryen og sorteret den efter ORDER BY.

Det modsatte synspunkt er, at når maskinen har fundet et tilstrækkeligt antal rækker, så stoppes videre udførelse.  Et konkret eksempel er dette:  Når en ny bruger vil oprette sig skal det undersøges om det valgte brugernavn allerede er brugt.  Det kan gøres med

if(mysql_num_row(SELECT * FROM table WHERE username = $user)) //afbryd
else //fortsæt. 

Det er naturligvis ligegyldigt om dette username findes 1 eller 10 gange.  Jeg fik så at vide, at hvis jeg indsætter LIMIT 1, så afbrudes søgningen, så snart der er fundet et sådant username. 

Kan en venlig sjæl hjælpe mig med at forstå udførelses rækkefølgen i mysql queries og hvor LIMIT kommer ind?
Avatar billede majbom Novice
17. oktober 2011 - 08:48 #1
jeg må indrømme at jeg ikke ved det, men det giver anledning til lidt tænkeri, når man ser lidt nærmere på det.

men umiddelbart vil jeg mene at det jo må være en del af WHERE clausen, så den sorterer alt andet end den første række fra (hvis LIMIT = 1)
Avatar billede JensPeterSvensson Nybegynder
17. oktober 2011 - 10:30 #2
Vil formode at LIMIT kommer efter ORDER BY, og at ORDER BY defaulter til first in, hvis den ikke erklæres.

Jeg antager at den tester om rækken kan være i resultatet med WHERE klausulen. Hvis rækken kan være i resultatet gives den til ORDER BY klausulen for at indsættes det korrekte sted i resultatet. Og tilsidst efter hver indsætning testes der om LIMIT er opfyldt.

Det ville selvfølgelig kræve, at man gennem læste koden til den pågældende DB motor for at finde ud af hvordan dette faktisk udføres.

Vil også betvivle at de laver en virtuel tabel med alle data fra tabellerne i join for først derefter at trække fra. Det lyder lidt som galimatias, hvis man nu havde tabeller med millioner af rækker. (ufattelig meget memory.)
17. oktober 2011 - 11:11 #3
JensPeterSvensson, sql maskinen laver sikkert ikke hele den virtuelle tabel på en gang, den tager nok første række af tabel1 og sammenligner den med samtlige rækker af tabel2 og så beholder dem der svarer til join klausulen og derefter sammenligner anden række af tabel1 med samtlige rækker i tabel2 o.s.v.  Men hvis en tabel med en million rækker skal joines med en anden tabel med en million rækker, så skal maskinen igennem 1,000,000 * 1,000,000 sammenligninger.  Ikke sandt?  Man har vel endnu ikke lavet computere så intuitive, at maskinen på forhånd ved om en række er værd at kikke efter før den rent faktisk har indlæst rækken.  Da Codds i 1970'erne udviklede de relationelle teorier der nu bruges i Relational Database Management Systems ( http://www.seas.~zives/03f/cis550/codd.pdf ) skrev han udtrykkeligt: "Implementations of systems to support the relational model are not discussed."  De daværende computere kunne nemlig ikke håndtere det med at sammenligne millioner af rækker med millioner af rækker.  Det var først, så vidt jeg ved, i de tidlige 1980'ere, da computere var blevet kraftigere, at Oracle og andre begyndte at udvikle konkrete RDBM systemer.

(Det er pudsigt - engang i midten af 1970'erne faldt jeg tilfældigvis over Codds' tekst og blev totalt betaget af logikken deri.  Først mange år senere blev jeg konfronteret med bestående relational database systemer.)

Dine antagelser om LIMIT synes at falde overens med mine antagelser.  Jeg håber på indlæg fra medlemmer der har faktisk kendskab dertil og er parat til at forklare det på en pædagogisk måde som selv jeg kan følge.
Avatar billede arne_v Ekspert
17. oktober 2011 - 14:09 #4
Jeg tror at du skal skelne skarpt mellem dn logiske operation og hvad databasn kan optimere det til.

Logisk set er LIMIT til aller sidst hvor den smider al andet end de foerste n rakker vaek.

Det er meget muligt at optimizeren ved faktisk udfoersel udfoerer det hele i en stor sammenblanding og derfor stopper med at hente naar den har de foerste n raekker.
17. oktober 2011 - 18:24 #5
arne_v, tak for det indlæg.  (Faktisk håbede jeg på et indlæg fra dig når det blev dag i Rhodes Island.) 

Mens jeg nu sad of prøvede at formulere uddybende spørgsmål om emnet googlede jeg videre, og jeg fandt denne:

http://dev.mysql.com/doc/refman/5.0/en/limit-optimization.html

om 'LIMIT Optimization'.  Det var interessant læsning.  Jeg finder, blandt andet, at 

"If you are selecting only a few rows with LIMIT, MySQL uses indexes in some cases when normally it would prefer to do a full table scan"

og at

"If you use LIMIT row_count with ORDER BY, MySQL ends the sorting as soon as it has found the first row_count rows of the sorted result, rather than sorting the entire result."

Men den tabel hvori maskinen ved index finder nogle få rækker i stedet for at foretage fuld tabel skan må være tabellen med resultaterne af den egentlige søgning ifølge FROM, JOIN ON, WHERE, SELECT klausulerne.  Og det at maskinen i forbindelse med ORDER BY finder resultat nummer 1, 2, 3, 4, og 5 og så smider resten væk uden at bestemme hvilke resultater er nummer 6, 7, o.s.v., må da indebære, at maskinen er nået gennem hele molevitten op til ORDER BY stadet. 

Altså, hvor LIMIT logisk set skulle være allersidst optimerer maskinen det somme tider så LIMIT er næstsidst.  Men en limit klausul begrænser ikke den egentlige søgning, kun præsentationen.

Jeg ville være glad for din (og/eller andres) kritiske kommentarer af dette.
Avatar billede arne_v Ekspert
17. oktober 2011 - 18:42 #6
Jeg tror at noegleordet her er index.

Lad os tage et simpelt eksempel:

SELECT *
FROM ekspertenbrugere ebruger LEFT JOIN ekspertenspoergsmaal espm ON ebruger.id=espm.brugerid
WHERE espm.kategori='MySQL'
ORDER BY espm.dato DESC
LIMIT 5

Hvis der ikke er index paa espm.dato saa skal alle data hentes.

Men hvis der er index paa espm.dato saa er der muligheder.

Pseudo kode:

ix = espm.index(dato)
ptr = ix.last
fnd = 0
while(fnd < 5 and ptr > ix.first) {
    espmrec = espm_table[ptr]
    if (espmrec.kategori = 'MySQL' and ebruger.index(id).contains(espmrec.brugerid) {
        fnd++
        res.add(espmrec)
    }
    ptr--
}
Avatar billede arne_v Ekspert
17. oktober 2011 - 18:43 #7
while(fnd < 5 and ptr >= ix.first) {

men det har ikke betydning for pointen
17. oktober 2011 - 19:47 #8
Jeg kan se hvad du mener.  'Normalt' skal søgningen fuldføres før maskinen kan se hvilke resultater er de fem første og så i præsentationsdelen vise disse.  Men i visse tilfælde, såsom ved ORDER BY på en enkelt kolonne med index, har maskinen muligheder for at vide hvilke resultater der vil være de første og så stoppe når disse er fundet.

Altid fornuftig snak fra din side.  Opret venligst et svar for points.
Avatar billede arne_v Ekspert
18. oktober 2011 - 09:19 #9
svar
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