Archief - SQL: JOINS zijn trager dan gewoon véél queries?

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

sneax

Legacy Member
Ik wist tot voor kort nog niet van JOIN in SQL, dankzij die post die hier een tijdje geleden stond dus wel, en ik ben er vandaag ff mee bezig geweest om de 98 queries op de main page van Ravengames.com te verminderen naar véél minder hehe ;)

Nu, vroeger queryiede ik cat_type, om daar te selecteren welke news_id's ik moest hebben, en dan pér news_id ging ik met nóg een query de data van die newspost ophalen.

Als ik dus 100 newsposts zou laten zien heb ik 101 queries. Met JOIN moet dit niet. Maar nu is het probleem eenvoudig weg dat het met een join 44secs duurt tot de query voldaan is (zelfs met LIMIT 20 ) en dat de 98 queries op de main page nu maar een fractie van een seconde duurt.

Wat moet ik dan doen? Dbase design zélf is eigenlijk wél goed dus daar moet ge het ni op steken, ik kan het alleen ni optimaal benutten blijkbaar.

De twee situaties in de praktijk:
- NU (98 queries):
Eerst
SELECT type_id FROM cat_type WHERE type = 'news' AND ( cat_type.cat_id = '2' OR cat_type.cat_id = '3' OR (...) ) ORDER BY type_id DESC LIMIT 20
-> stel u bij (...) nen hoop OR cat_id = 'x' voor, daar selecteer ik de categorieën

Nadien doe ik voor élke gevonden type_id (dus alle newsposts die in één van die categorieën) zitten nog een keer een query om de eigenlijke data van die newspost te vinden.

- MET JOIN (1 query)
SELECT news.* FROM news LEFT JOIN cat_type ON ( news.id = cat_type.type_id ) AND cat_type.type = 'news' AND (cat_type.cat_id = '1' OR (...)) ORDER BY news.date DESC LIMIT 20

Het verschil is dat ik hier ORDER doe op datum (aangezien dat aanvankelijk ook de bedoeling was, maar niet mogelijk als je verschillende queries gebruikt).

Het verschil tss LEFT JOIN, INNER JOIN, RIGHT JOIN etc... weetek wel ni mss ligt het daaraan?

Waarom het niet zo 'eenvoudig' is, is omdat ik newsposts (en andere 'items' zoals pages en images) in verschillende categorieën wil kunnen steken. Anders zou ge uiteraard gewoon up cat_id veld in uw news table kunnen steken.

Wat ik mij kan voorstellen waardoor het foutloopt is dat mijn news_id's in de table news wel uniek zijn maar mijn 'type_id' in de table cat_type is dat dus niet (aangezien er meerdere categorieen per newspost kunnen zijn).

`SeriOUs

Legacy Member
voorbeelden zouden handig zijn.
Want voor nieuws op te halen heb je toch niet veel nodig.

sneax

Legacy Member
Blijkbaar is RIGHT JOIN véél sneller - ik zal maar moeten googlen om het verschil te vinden want op mysql.com is het mij wa té ingewikkeld voorgesteld.

`SeriOUs

Legacy Member
normaal gaat het niet zo veel sneller zijn, tenzij je gigantische tabellen hebt.
Je moet het natuurlijk wel juist gebruiken, anders ga je mss niet alle data ophalen die je wilt...

sneax

Legacy Member
Volgens mij lukt het met RIGHT JOIN veel beter, ik heb via Google info gevonden waarop duidelijk uitgelegd staat wat het verschil is en ik begrijp het nu wel.

Volgens mij zijn die JOIN's wel sneller aangezien er bijna 4000 posts in de database zitten. En als ze niet sneller zijn, zijn ze gewoon véél handiger ;)

Trouwens, is het écht slecht om zoveel queries te hebben op één pagina? (78 nu :/) Als ik dit aantal zou willen verminderen zou ik de PHP code véél pagina-afhankelijker moeten maken en véél minder herbruikbaar. Voor de moment zie ik toch geen enkele vertraging, zo erg zal het dus niet zijn? Moest ik die pagina's gewoon aan één stuk in PHP schrijven zou ik het mss kunnen doen in euh ... 8 queries (met een aantal JOINs dan). Is dit écht van belang?

`SeriOUs

Legacy Member
Volgens mij schort er toch wat aan uw database structuur, want ik kan er niet volledig aan uit...

'Normaal zou zijn':
Code:
 SELECT TOP 20 * FROM nieuws
 INNER JOIN categorie ON nieuws.catid = categorie.id
 WHERE nieuws.id = '1'
 ORDER BY nieuws.datum DESC
En dan meerdere tabellen voor images en pages ed. die op dezelfde manier werken.

sneax

Legacy Member
Ja maar het is hier niet 'normaal'. Het is ook geen 'normale' news site zoals een blog ofzo.

Er is de mogelijkheid om news in MEEDERE categorieën te steken, nadien kunt ge ook news uit de database halen en bv. kiezen om alleen news in category 1 3 en 4 te tonen.

De praktische toepassing op de website: op ravengames.com worden ALLE categorieën getoont. Op bv. sof2.ravengames.com worden maar 2 categorieën getoont, namelijk de category 'sof2' en de category 'general ravengames.com'.

Daarom is er een dbase structuur met een 'tussentabel' zodat ge meerdere categorieën aan één item zou kunnen linken. De bedoeling van mijn JOIN hier, is om dus deze 'link' table met de news data table te joinen. Welke categorieën ik wil wordt geselecteerd uit de tabel met de 'links' en de eigenlijke news data komt dus uit die news table.

Bij uw voorbeeld kunt ge maar 1 category aan een newsitem toewijzen, wat te simplistisch is om te dienen voor ravengames.com, en waarom een CMS als phpNuke en allerhande dus ook simpelweg niet volstaan. Of mss ben ik wel verkeerd en kan het tóch simpeler? ... Dunno.

EdMeister

Legacy Member
sneax zei:
Volgens mij lukt het met RIGHT JOIN veel beter, ik heb via Google info gevonden waarop duidelijk uitgelegd staat wat het verschil is en ik begrijp het nu wel.
Normaal is een inner join nochtans veel sneller is dan een outer join. Dus als jij RIGHT JOIN gebruikt, zit je met een outer join en zou dat dus in principe trager moeten zijn. Outer joins zijn enkel nuttig als je met NULL-velden te maken hebt en ik denk niet dat dit bij jou het geval is.

sneax

Legacy Member
Yup het is ongeveer 10 keer sneller om INNER JOIN ipv RIGHT JOIN te gebruiken, ik snap trouwens ook waarom. Zalig. Twerkt.

killgore

Legacy Member
dunno wrom je zei dat right join's sneller waren hoor:
RIGHT JOIN works analogously to LEFT JOIN
Van mysql zelf, het is enkel zo dat ergens de rol van bep. tabellen wordt omgewisseld, maar dat zou in principe zeker en vast geen zware snelheidsverschillen mogen opleveren (bij goed/juist gebruik van beiden, je zal vaak genoeg een left ipv right gebruiken).
Ik dacht dat INNER JOIN gewoon meer overeenkwam met de gewone , operator en where-clausules (niet qua snelheid wrsch, maar qua gebruik).

sneax

Legacy Member
killgore zei:
dunno wrom je zei dat right join's sneller waren hoor:
Van mysql zelf, het is enkel zo dat ergens de rol van bep. tabellen wordt omgewisseld, maar dat zou in principe zeker en vast geen zware snelheidsverschillen mogen opleveren (bij goed/juist gebruik van beiden, je zal vaak genoeg een left ipv right gebruiken).
Ik dacht dat INNER JOIN gewoon meer overeenkwam met de gewone , operator en where-clausules (niet qua snelheid wrsch, maar qua gebruik).

Er is wel degelijk een groot verschil.
Bij RIGHT JOINs gaat ge 'selecteren' op de table die ge JOINt en DAN pas zal hij de andere erbij halen en daar geld uw WHERE clause dan voor. Als ge LEFT JOIN pakt, gaat hij eerst alle news items uit de eerste table nemen volgens de WHERE clause en dan kijken naar de table die ge JOINT of die query er bij moet zijn of niet volgens de ON clause.

Het praktisch verschil bij mij is:
Bij RIGHT JOIN gaat mysql dit doen:
Checked alle newsposts (ongeveer 4000) en gaat voor elke newsposts kijken in cat_type of die in één van de categories zit die in het result moeten zitten of niet. Das dus 4000 newsposts en 20 categorieën per newsposts dat hij overloopt.

Bij LEFT JOIN:
Gaat kijken welke newsposts geselecteerd moeten worden in cat_type en gaat dan die newsposts uit news halen.

Bij INNER JOIN:
Hier gaat hij niet eerst 'links' doen (de WHERE clause) en dan pas 'rechts' (de ON clause) maar gaat hij doen alsof het één grote tabel is, waardoor het nog sneller is.

Nu jah kijk als ge het ni begrijpt, ik heb de finesses nu wel goed door - wat de manual ook zegt, er is wel degelijk een *groot* verschil, en het is bij 'grote' databases toch belangrijk die te weten. Altijd INNER JOIN doen, want die is immers het snelst. LEFT JOIN of RIGHT JOIN moet ge idd gebruiken als er NULL waarden zijn (ik snap nu waarom) en of ge LEFT of RIGHT join moet gebruiken hangt af van welke table de 'hoofd' table is en welke de table waar er mogelijke NULL waarden kunnen inzitten.

killgore

Legacy Member
sneax zei:
Nu jah kijk als ge het ni begrijpt, ik heb de finesses nu wel goed door - wat de manual ook zegt, er is wel degelijk een *groot* verschil, en het is bij 'grote' databases toch belangrijk die te weten. Altijd INNER JOIN doen, want die is immers het snelst. LEFT JOIN of RIGHT JOIN moet ge idd gebruiken als er NULL waarden zijn (ik snap nu waarom) en of ge LEFT of RIGHT join moet gebruiken hangt af van welke table de 'hoofd' table is en welke de table waar er mogelijke NULL waarden kunnen inzitten.
ik begrijp het, ty om dat op te klaren :). (zoals ik zei: INNER is dus zowat gelijk aan , seperator)

DarkBone

Legacy Member
Ik sta dus nog altijd versteld van die 100 queries da ge eerst had hé... kga er es over slapen, misschien da'k et tegen morgen verwerkt heb... zo'n schok zeg :D
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan