[MySQL] Inner join problemen

Pagina: 1
Acties:

  • Battle Bunny
  • Registratie: Oktober 2001
  • Laatst online: 02-02 21:41
Hi,

Zojuist heb ik een flinke DB omgezwabbert van Access naar MySQL in de hoop dat dit wat beter en sneller zou werken. Nu heb ik al onwijs veel dingen aangepast maar hier kom ik niet uit:

Ik heb een query:
code:
1
strSQL =  "SELECT * from tBookmarks INNER JOIN (tMessages INNER JOIN tUsers ON tMessages.iPosterID = tUsers.iID ) ON tBookmarks.intMessageID = tMessages.iID WHERE intUserID = " & userID


Maar dat mag niet erg... Hoe kan ik dit nu wel oplossen? Ik heb al veel geprobeerd, maar ik kom er echt niet uit |:(

  • whoami
  • Registratie: December 2000
  • Laatst online: 19:34
Probeer eerst eens die query naar normale mensentaal te vertalen, en zet hem dan om naar een query die MySQL wel accepteert.

https://fgheysels.github.io/


  • Battle Bunny
  • Registratie: Oktober 2001
  • Laatst online: 02-02 21:41
Dat wil ik wel, maar dat lukt dus niet. Ik weet ook niet wat hier mis aan is. Voor zover ik weet mag ik gewoon tables joinen (dit mag met de MS Access driver in elk geval wel).

  • GarBaGe
  • Registratie: December 1999
  • Laatst online: 13:42
Simpel: de tabellen op 1 hoop vegen in de FROM-clause en vervolgens de INNER JOIN constraints toevoegen aan je WHERE-clause.
En dan kan de geneste INNER JOIN constructie in de /dev/null

Ryzen9 5900X; 16GB DDR4-3200 ; RTX-4080S ; 7TB SSD


  • GarBaGe
  • Registratie: December 1999
  • Laatst online: 13:42
Battle_Bunny schreef op 31 oktober 2002 @ 15:45:
Dat wil ik wel, maar dat lukt dus niet. Ik weet ook niet wat hier mis aan is. Voor zover ik weet mag ik gewoon tables joinen (dit mag met de MS Access driver in elk geval wel).
MySQL ondersteunt wel INNER JOINs, maar geen geneste INNER JOINs

Ryzen9 5900X; 16GB DDR4-3200 ; RTX-4080S ; 7TB SSD


  • Battle Bunny
  • Registratie: Oktober 2001
  • Laatst online: 02-02 21:41
MySQL ondersteunt wel INNER JOINs, maar geen geneste INNER JOINs
Kijk, en DAT is nu juist het probleem. Ik ken alleen maar 'Inner joinen'

  • GarBaGe
  • Registratie: December 1999
  • Laatst online: 13:42
Battle_Bunny schreef op 31 oktober 2002 @ 15:51:
[...]

Kijk, en DAT is nu juist het probleem. Ik ken alleen maar 'Inner joinen'
OK, let op:
Ik zei:
"de tabellen op 1 hoop vegen in de FROM-clause en vervolgens de INNER JOIN constraints toevoegen aan je WHERE-clause."

Je tabellen zijn:
tBookmarks
tMessages
tUsers

Je INNER JOIN constraints zijn:
tMessages.iPosterID = tUsers.iID
tBookmarks.intMessageID = tMessages.iID


Nieuwe query:
SELECT *
from tBookmarks, tMessages, tUsers
WHERE tMessages.iPosterID = tUsers.iID
AND tBookmarks.intMessageID = tMessages.iID
AND intUserID = " & userID

Oftewel: tabellen in de FROM-clause en INNER JOIN constraints toegevoegd aan de WHERE-clause

Ryzen9 5900X; 16GB DDR4-3200 ; RTX-4080S ; 7TB SSD


  • cameodski
  • Registratie: Augustus 2002
  • Laatst online: 06-11-2023
GarBaGe schreef op 31 oktober 2002 @ 15:57:
Nieuwe query:
SELECT *
from tBookmarks, tMessages, tUsers
WHERE tMessages.iPosterID = tUsers.iID
AND tBookmarks.intMessageID = tMessages.iID
AND intUserID = " & userID

Oftewel: tabellen in de FROM-clause en INNER JOIN constraints toegevoegd aan de WHERE-clause
Volgens mij kan MySQL ook gewoon overweg met INNER JOIN en dan krijg je dus de volgende query:
code:
1
2
3
4
5
SELECT *
FROM tBookmarks
INNER JOIN tMessages ON tBookmarks.intMessageID = tMessages.iID
INNER JOIN tUsers ON tMessages.iPosterID = tUsers.iID 
WHERE intUserID = .....

Never underestimate the power of


  • whoami
  • Registratie: December 2000
  • Laatst online: 19:34
Maar de syntax van GarBaGe is (imho dan) veel mooier en duidelijker.

https://fgheysels.github.io/


  • Battle Bunny
  • Registratie: Oktober 2001
  • Laatst online: 02-02 21:41
Grmbl :)

Die van jullie doen het wel (ik had zelf ook al iets gelijks, maar die werkte om de een of andere manier niet).

Thanks. Is er trouwens nog een snelheids verschil tussen de GarBaGe versie en die van cameodski?

  • cameodski
  • Registratie: Augustus 2002
  • Laatst online: 06-11-2023
whoami schreef op 31 oktober 2002 @ 16:39:
Maar de syntax van GarBaGe is (imho dan) veel mooier en duidelijker.
Daar ben ik het dus niet mee eens, maar die discussie is al vaker gevoerd, dus als je het niet erg vindt, gaan we dat niet opnieuw doen. :)

Never underestimate the power of


  • whoami
  • Registratie: December 2000
  • Laatst online: 19:34
cameodski schreef op 31 oktober 2002 @ 16:43:
[...]

Daar ben ik het dus niet mee eens, maar die discussie is al vaker gevoerd, dus als je het niet erg vindt, gaan we dat niet opnieuw doen. :)


Daar was ik ook niet op uit.
Des goûts et des couleurs, on ne se discute pas.

https://fgheysels.github.io/


  • Nielsz
  • Registratie: Maart 2001
  • Niet online
Ze zijn allebei traag (ok, trager ;) ) omdat ze '*' gebruiken. Verder zou ik voor de eerste gaan, omdat joins over het algemeen trager zijn.

  • cameodski
  • Registratie: Augustus 2002
  • Laatst online: 06-11-2023
Nielsz schreef op 31 oktober 2002 @ 16:44:
Ze zijn allebei traag (ok, trager ;) ) omdat ze '*' gebruiken. Verder zou ik voor de eerste gaan, omdat joins over het algemeen trager zijn.
joins trager?? Waar haal je die wijsheid vandaan. MS heeft in MSSQL juist heel erg zijn best gedaan om vooral het join keyword zo veel mogelijk te optimaliseren. Hoe dat bij MySQL zit, weet ik eerlijk gezegd niet, maar ik vermoed dat de optimizer er uiteindelijk exact dezelfde query van maakt, dus veel verschil zal er hoogstwaarschijnlijk niet in zitten.

Never underestimate the power of


  • Nielsz
  • Registratie: Maart 2001
  • Niet online
cameodski schreef op 31 oktober 2002 @ 16:47:
[...]

joins trager?? Waar haal je die wijsheid vandaan. MS heeft in MSSQL juist heel erg zijn best gedaan om vooral het join keyword zo veel mogelijk te optimaliseren. Hoe dat bij MySQL zit, weet ik eerlijk gezegd niet, maar ik vermoed dat de optimizer er uiteindelijk exact dezelfde query van maakt, dus veel verschil zal er hoogstwaarschijnlijk niet in zitten.
Ik had het dan ook over MySQL ;) MySQL is optimized (schrijf je dat zo?) voor simpele queries, en niet voor joins.

  • cameodski
  • Registratie: Augustus 2002
  • Laatst online: 06-11-2023
Nielsz schreef op 31 oktober 2002 @ 16:49:
Ik had het dan ook over MySQL ;) MySQL is optimized (schrijf je dat zo?) voor simpele queries, en niet voor joins.
Probleem is alleen dat het exact dezelfde query is, maar dan anders geschreven. Een beetje optimizer zorgt ervoor dat er uiteindelijk hetzelfde gebeurt. Er zou dus alleen verschil in het optimizen mogen zitten, maar over hoeveel nanoseconden hebben we het dan? :)

Never underestimate the power of


  • Nielsz
  • Registratie: Maart 2001
  • Niet online
cameodski schreef op 31 oktober 2002 @ 16:52:
[...]

Probleem is alleen dat het exact dezelfde query is, maar dan anders geschreven. Een beetje optimizer zorgt ervoor dat er uiteindelijk hetzelfde gebeurt. Er zou dus alleen verschil in het optimizen mogen zitten, maar over hoeveel nanoseconden hebben we het dan? :)
Wie beweert dat MySQL meer dan een 'beetje' optimizer heeft? :)
Maar ik heb geen tijd (en zin ;) ) om een test te doen. Iemand zin in? :)

Verwijderd

Nielsz schreef op 31 oktober 2002 @ 16:44:
Ze zijn allebei traag (ok, trager ;) ) omdat ze '*' gebruiken. Verder zou ik voor de eerste gaan, omdat joins over het algemeen trager zijn.
De bewering dat joins trager zijn dan het gebruik van T-SQL kan ik met zekerheid weerleggen. De joins m.b.v. T-SQL zijn namelijk Equi-joins wat overeenkomt met de inner join van Ansi-SQL. Dat de optimizer in het ene geval wat langer nodig heeft om de query te optimizen, zal voor menselijk begrip niet merkbaar zijn.

Informatie over wat de optimizer uitvoert tijdens een select *, is meer dan genoeg literatuur over te vinden. zoek maar op google bijvoorbeeld op Sybase books en tuning, je kunt daar een en ander nalezen over de werking van de optimizer.

Geïnteresseerden kunnen zich de performance en Tuning Guide volume 1 t/m 3 doornemen.
http://sybooks.sybase.com/asg1250e.html

  • Nielsz
  • Registratie: Maart 2001
  • Niet online
Verwijderd schreef op 01 november 2002 @ 08:29:
[...]


De bewering dat joins trager zijn dan het gebruik van T-SQL kan ik met zekerheid weerleggen. De joins m.b.v. T-SQL zijn namelijk Equi-joins wat overeenkomt met de inner join van Ansi-SQL. Dat de optimizer in het ene geval wat langer nodig heeft om de query te optimizen, zal voor menselijk begrip niet merkbaar zijn.
Bedoel je daarmee dat het in de ene Join trager is dan in de andere? (Waarbij de joins dezelfde structuur hebben) En gaat dit over _alle_ sql's (wat ik me niet kan voorstellen), of over Mysql of iets anders?
Informatie over wat de optimizer uitvoert tijdens een select *, is meer dan genoeg literatuur over te vinden. zoek maar op google bijvoorbeeld op Sybase books en tuning, je kunt daar een en ander nalezen over de werking van de optimizer.

Geïnteresseerden kunnen zich de performance en Tuning Guide volume 1 t/m 3 doornemen.
http://sybooks.sybase.com/asg1250e.html
Ik baseerde mijn text op een performance test van D2k. Misschien heeft hij er nog wat over te melden ;)

Verwijderd

Nielsz schreef op 01 november 2002 @ 09:33:
[...]

Bedoel je daarmee dat het in de ene Join trager is dan in de andere? (Waarbij de joins dezelfde structuur hebben) En gaat dit over _alle_ sql's (wat ik me niet kan voorstellen), of over Mysql of iets anders?

[...]

Ik baseerde mijn text op een performance test van D2k. Misschien heeft hij er nog wat over te melden ;)
Nee, in het geval van Ansi-join en T-SQL zou het normalerwijs niets uit mogen maken. Echter, de manier waarop je de where clausule samenstelt, beperkt wel de zoekpaden die de optimizer beschouwt in eniger mate!

Lees vooral hoofdstuk 17 van de Performance en Tuning Guide Volume 2 van Sybase eens aandachtig door. (Link heb ik in eerdere response al gegeven) Dan weet je hoogstwaarschijnlijk wat ik bedoel en kun je verrassingen voorkomen. (Zie vooral gedeelte onder join transitive closure)

[ Voor 0% gewijzigd door Verwijderd op 01-11-2002 10:44 . Reden: Foutje bedankt ]


  • D2k
  • Registratie: Januari 2001
  • Laatst online: 29-08 22:51

D2k

Nielsz schreef op 01 november 2002 @ 09:33:
[...]
Ik baseerde mijn text op een performance test van D2k. Misschien heeft hij er nog wat over te melden ;)

dat was een test die bewees dat select * trager was dan het opgeven van alle tabellen ;)

Doet iets met Cloud (MS/IBM)


  • Nielsz
  • Registratie: Maart 2001
  • Niet online
En dat is exactly wat ik ook bedoel ;)

  • cameodski
  • Registratie: Augustus 2002
  • Laatst online: 06-11-2023
Nielsz schreef op 01 november 2002 @ 18:34:
En dat is exactly wat ik ook bedoel ;)
Oh, ik dacht dat we het over het verschil in snelheid tussen het wel en niet gebruiken van het keyword join hadden?
En niet over het verschil tussen select * en select veldnamen.

Never underestimate the power of


Verwijderd

cameodski schreef op 01 november 2002 @ 23:33:
[...]

Oh, ik dacht dat we het over het verschil in snelheid tussen het wel en niet gebruiken van het keyword join hadden?
En niet over het verschil tussen select * en select veldnamen.
Ik ben het volledig met Cameodski eens. Over het al dan niet gebruiken van select * hebben we het al eens over gehad in een eerder topic en ik wil nu niet in herhalingen gaan vallen.

Vergeef me dat ik niet altijd even sterk ben om een en ander duidelijk te maken. Het op papier zetten van dergelijke argumenten is niet mijn sterkste kant en ik kan me levendig voorstellen dat ik soms verwarring schep :?

Het al dan niet gebruiken van het woord JOIN, het zou helemaal niets mogen uitmaken voor de optimizer qua snelheid. Het zoekpad dat de optimizer voorstelt zal exact gelijk moeten zijn. De vraag die dan blijft, is dat inderdaad zo, niet?

Wel, hier komt het antwoord voor Sybase, Oracle en MSSQL.
In zowel Sybase, Oracle en MSSQL (gebaseerd op Sybase) maakt het niets uit of je al dan niet gebruik maakt van JOIN. (Wacht even met verdere reacties, please ik ga hier eerst wat dieper op in) Het gebruik van het woord JOIN (of juist niet gebruiken ervan) heeft alleen te maken met de opmaak van de query. Dat de een een voorstander is van het gebruik van JOIN en een ander dit liever vermijdt is slechts een kwestie van smaak. De optimizer zal tot exact hetzelfde resultaat komen qua zoekpad (en dus ook qua snelheid).

Met name in stored procedures, triggers e.d. compileert de optimizer maar eenmaal de code en slaat het door hem voorgeslagen zoekpad op. Dit zoekpad zal de optimizer altijd opnieuw gebruiken zodra de stored procedure /trigger opnieuw wordt aangeroepen (tenzij ik de procedure/trigger opnieuw aanmaak of hercompileer!). Voor het bepalen van het zoekpad zal dan geen tijd meer verloren gaan en daar het zoekpad in beide gevallen exact hetzelfde is, zal het helemaal niets uitmaken in snelheid.

De vraag die dan blijft, hoe zit het dan met ad hoc queries? Is daar een verschil merkbaar? Ik zal een poging ondernemen (forgive me, indien ik niet iedereen overtuigen kan)

Ik ben al jaren actief als Technisch DB ontwerper voor een grote multi-user omgeving (meer dan 300 concurrent users) en heb me met name gespecialiseerd in het tunen van queries die een botleneck vormen in performance en kan melden dat zowel de volgorde van doorlopen van tabellen die gebruikt zijn in de join, als ook de gebruikte indexen een exacte kopie van elkaar zijn (als we het hebben over wel / niet JOIN gebruik).

Echter...., er zijn uitzonderingen!!! Tja, jammer maar helaas, maar het is nu niet anders. De optimizer is door mensen in elkaar gezet en zal nooit ofte nimmer in staat zijn in alle gevallen tot hetzelfde pad komen. (Heeft niets te maken met al dan niet gebruiken van JOIN)

(Een en ander hangt ook nog af van de statistics, maar zal dit niet nader toelichten, want daar is genoeg literatuur over te vinden en het heeft ook niets te maken met het al dan niet gebruik van JOIN)

Zo is er onder andere een tekortkoming in de (Sybase in ieder geval) optimizer wat betreft triggers. Ik zal maar een voorbeeld geven om dit te verduidelijken.

Stel ik wil in een trigger van een tabel, iets updaten in tabel b (om wat voor reden dan ook)

Voorbeeld 1
update b
set ditte = 1
where exists(select 1 from inserted where inserted.id = b.id)

Voorbeeld 2
update b
set ditte = 1
from inserted, b --Dit werkt onder Sybase
where b.id = inserted.id

In de meeste gevallen zal de optimizer exact hetzelfde zoekpad bepalen, echter... dat is helaas niet in 100% van de gevallen zo. Voorbeeld 1 zal in geval van de Sybase optimizer (en hoogstwaarschijnlijk ook andere RDBMS) wel eens problemen op kunnen leveren in een multi-user omgeving (om het maar een beetje complexer te maken dan het al is), er wordt soms om onverklaarbare redenen een tijdelijke Exclusive Table lock(!!!!) gelegd voor het vinden van geschikte rijen (die hij wordt opgeheven zodra de rijen gevonden zijn en begint met de update).

Voordat er mensen commentaar geven dat dit te maken heeft met het gebruik van exists, helaas dit heeft niets met exists te maken, want bij een select statement met exists komt hij in beide gevallen wel tot hetzelfde zoekpad.

Voor degene die query 1 uitvoert zal dit niet merkbaar zijn (tenzij er gewacht moet worden totdat de exclusive Table lock genomen kan worden), maar voor andere gebruikers die ook data van die tabel willen lezen, gedurende de transactie wel degelijk (Zij worden geblokt)

Zoals ik al eerder aangaf, lees eerst eens met name hoofdstuk 17 door van de Performance en Tuning guide (Volume 2) van Sybase door op de link die ik eerder reeds heb gegeven, dan wordt een en ander duidelijk. De meeste RDBMS werken op het Cost-based principe. En als je je dan toch eenmaal aan het verdiepen bent in de mysteries van de optimizer, dan raad ik aan ook eens de rest van de 3 volumes door te lezen, er zal een hele wereld voor je open gaan.

  • Nielsz
  • Registratie: Maart 2001
  • Niet online
leuk/interessant stukkie :)
Ik wil me idd nog eens gaan verdiepenin de werking van een SQL server. Misschien is dit wel een mooi moment :)
Pagina: 1