Tabelfuncties
In veel queries worden tabelfuncties gebruikt. Dit is meestal het geval bij platformen die werken met zogenaamde “puntqueries” en het uitvoeren van talrijke I/O’s zoals:
select *
from customers ctr
join httpdownload(ctr.website_url) htp
Een tabelfunctie wordt vaak duizenden of miljoenen keren aangeroepen bij grote datasets. De uitvoering vindt altijd achtereenvolgens plaats:
- Haal een handvol rijen op uit de basistabel zoals
customers
hierboven. - Voer voor de eerste rij de tabelfunctie uit.
- Wacht tot die klaar is.
- Voer voor de tweede rij de tabelfunctie uit.
- Wacht tot die klaar is.
- … etc.
Veel tabelfuncties roepen een API of website aan, waarbij er vertraging kan optreden van enkele milliseconden tot honderden milliseconden per aanroep.
Bijvoorbeeld voor het verwerken van de gegevens achter https://zoek.officielebekendmakingen.nl zijn in bepaalde use cases 6 tot 12 miljoen aanroepen nodig.
Snellere verwerking
Met de nieuwe join_parallelization
hint krijgt de Invantive UniversalSQL-engine om - waar mogelijk - tabelfuncties parallel aan te roepen met meerdere threads:
- Haal een handvol rijen op uit de basistabel zoals
customers
hierboven. - Start de uitvoering voor de eerste rij met de tabelfunctie.
- Start de uitvoering voor de tweede rij met de tabelfunctie.
- … etc.
- Wacht tot er een klaar is en start weer een nieuwe.
- … etc.
In de meest optimale situatie wordt de doorlooptijd lineair korter: bij parallellisatie over n keer zoveel threads, is de totale verstreken kloktijd n keer korter.
Als het aantal threads niet opgegeven wordt, dan wordt 2x het aantal processoren gebruikt. Het maximaal aantal actieve threads wordt altijd op 128 afgekapt per query.
Een lineaire snelheidssprong zal niet altijd gehaald kunnen worden, maar zeker bij I/O-intensieve bewerkingen is een grote versnelling mogelijk.
Een grote snelheidswinst is niet te verwachten bij berekeningen die al beperkt worden doordat ze al de beschikbare rekenkracht en andere resources optimaal gebruiken.
Parallellisatie is sowieso pas aan te raden na het uitproberen van een slimmere aanpak via tuning.
Aan de hand van twee I/O-intensieve voorbeelden worden de mogelijkheden geillustreerd.
Teamleader
Het ophalen van de volgende query kan parallel plaatsvinden:
select count(*)
from Teamleader.V2.Companies l
join Teamleader.V2.CompanyById(l.id) p
Het aantal threads (in dit voorbeeld 8) kan ingesteld worden met de hint join_parallelization
:
select /*+ join_parallelization(dl, true, 8) */count(*)
from Teamleader.V2.Companies l
join Teamleader.V2.CompanyById(l.id) p
Als er 100 bedrijven geregistreerd zijn in Teamleader Focus, dan passen alle aanroepen van CompanyById
binnen de rate limiter van 200 API-calls per minuut. Er zullen uiteraard andere vertragende factoren zijn zoals een snelheidsbeperking binnen de database van Teamleader Focus zelf of wachtrijen met beperkte capaciteit.
Metingen tonen aan dat de doorvoersnelheid van initieel 4 rijen per seconde via parallellisatie stijgen als volgt:
#Threads | Doorvoersnelheid (rijen/sec) |
---|---|
1 | 4 |
2 | 6 |
4 | 9 |
8 | 13 |
16 | 16 |
32 | 17 |
64 | 18 |
128 | 19 |
De snelheidswinst is groot tot pakweg 8 a 16 threads, en een hogere snelheidssprong dan pakweg 5 lijkt niet haalbaar op deze manier.
Binaire download
De volgende query haalt 1000x een bestand van 1 MB op via een Intern-verbinding met maximaal 8 threads:
select /*+ join_parallelization(dl, true, 8) */ r.value rval
from range(1000, 1) r
join httpdownload
( url => 'https://ipv4.download.thinkbroadband.com/1MB.zip'
, ignoreInvalidCertificate => true
, ignoreWebError => true
) dl
De snelheidswinst is sterk afhankelijk van de beschikbare bandbreedte. Met 8 threads is de query 3x sneller klaar en met 128 threads is hij 28x sneller.
Beschikbaarheid
De join_parallelization
hint is beschikbaar vanaf BETA-release 24.1.122, die naar verwachting voor 15 juli 2025 beschikbaar zal komen.