Incremental Load vs Full Load: Welke Laadstrategie Kies Je?

Gepubliceerd: 31 juli 2026
Leestijd: 15 minuten
Data Engineering · ETL/ELT

Elke datapipeline stelt vroeg of laat dezelfde vraag: haal je bij elke run de volledige bron opnieuw op, of verwerk je alleen wat er is veranderd? In deze gids leggen we het verschil tussen full load en incremental load haarfijn uit — met CDC-technieken, SQL MERGE-voorbeelden, een beslisboom en de valkuilen waar je in de praktijk tegenaan loopt.

Het Verschil in Één Alinea

Een full load haalt bij elke run de complete dataset uit de bron en vervangt (of herbouwt) de doeltabel volledig. Een incremental load — ook wel delta load genoemd — haalt alleen de records op die nieuw zijn of zijn gewijzigd sinds de vorige run, en verwerkt die met een insert/update (upsert) in de doeltabel.

Het klinkt als een technische keuze, maar de impact raakt bijna alles: laadtijd, belasting van de bron, kosten, complexiteit van je code én hoe robuust je pipeline is tegen fouten. Er is geen universeel juiste keuze — wel een duidelijke afweging die we in dit artikel stap voor stap doorlopen.

In één zin

Full load is eenvoudig en betrouwbaar, maar duur op schaal. Incremental load is snel en zuinig, maar vraagt meer engineering om correct te blijven.

Wat is Full Load?

Bij een full load doorloopt de pipeline bij elke run dezelfde stappen: alle rijen uit de bron ophalen, de bestaande doeltabel leegmaken (of een nieuwe versie ernaast bouwen) en de volledige dataset opnieuw wegschrijven. Er wordt niet gekeken naar wat er sinds de vorige keer is veranderd — de pipeline behandelt elke run alsof het de eerste keer is.

-- Klassiek full-load patroon: truncate + insert
TRUNCATE TABLE analytics.klanten;

INSERT INTO analytics.klanten
SELECT * FROM bron.klanten;

Voordelen van full load:

  • Eenvoud — geen logica nodig om wijzigingen te detecteren.
  • Garantie op consistentie — de doeltabel is altijd een exacte kopie van de bron op het moment van laden. Geen risico op gemiste wijzigingen of vergeten deletes.
  • Zelfherstellend — een fout in een eerdere run wordt automatisch gecorrigeerd bij de volgende volledige run.

Nadelen van full load:

  • Traag en resource-intensief bij grote datasets — je verplaatst data die niet is veranderd, elke keer opnieuw.
  • Belastend voor de bron — een volledige extractie van een operationele database kan de productieomgeving onder druk zetten.
  • Kostbaar in cloud-omgevingen waar je betaalt per verwerkte hoeveelheid data of compute-tijd.
  • Verliest historie tenzij je expliciet historisering toevoegt (zie Slowly Changing Dimensions) — een truncate + insert onthoudt niet wat de waarde gisteren was.

Wat is Incremental Load?

Bij een incremental load selecteert de pipeline alleen de rijen die nieuw zijn of zijn gewijzigd sinds de vorige succesvolle run, en verwerkt uitsluitend die rijen. Het resultaat in de doeltabel is hetzelfde als bij full load — een actuele weergave van de bron — maar de weg ernaartoe kost een fractie van de tijd en resources.

-- Klassiek incremental-load patroon: alleen wijzigingen sinds de watermark
SELECT *
FROM bron.klanten
WHERE updated_at > :laatste_watermark;

De kern van incremental load is niet het laden zelf, maar het betrouwbaar herkennen van wijzigingen. Dat is precies waar Change Data Capture (CDC) om de hoek komt kijken.

Wijzigingen Detecteren: CDC-technieken

Change Data Capture (CDC) is de verzamelnaam voor technieken om te bepalen welke rijen in een bron zijn veranderd. De keuze voor een CDC-techniek bepaalt hoe betrouwbaar en compleet je incremental load is.

1. Timestamp-based CDC (watermarking)

De meest gebruikte en eenvoudigste techniek: de bron heeft een kolom als updated_at of modified_date die wordt bijgewerkt bij elke wijziging. Je pipeline onthoudt de hoogste waarde van de vorige run (de watermark) en haalt bij de volgende run alleen rijen op met een hogere waarde.

-- Watermark ophalen uit de metadata-tabel van de pipeline
SELECT max_watermark FROM pipeline_control
WHERE table_name = 'klanten';

-- Alleen nieuwe/gewijzigde rijen ophalen
SELECT * FROM bron.klanten
WHERE updated_at > '2026-07-30 06:00:00';

-- Watermark bijwerken na succesvolle load
UPDATE pipeline_control
SET max_watermark = (SELECT MAX(updated_at) FROM bron.klanten)
WHERE table_name = 'klanten';

Belangrijkste zwakte

Timestamp-based CDC ziet harde deletes niet — een verwijderde rij heeft geen updated_at meer om op te filteren. Ook rijen die buiten de applicatie om zijn gewijzigd (bijvoorbeeld een handmatige SQL-update zonder trigger) worden gemist als de timestamp niet is bijgewerkt.

2. Log-based CDC

Log-based CDC leest het transactielog van de bronsystemen (bijv. de write-ahead log van PostgreSQL, de binlog van MySQL, of de change tracking van SQL Server) in plaats van de tabellen zelf te bevragen. Elke insert, update én delete wordt vastgelegd als event, inclusief de oude en nieuwe waarde.

  • Voordeel: vangt ook deletes op, veroorzaakt vrijwel geen belasting op de bron (het log wordt toch al geschreven) en werkt near-realtime.
  • Nadeel: vraagt gespecialiseerde tooling (Debezium, Fivetran, Qlik Replicate, native CDC in Fabric/Synapse) en toegang tot het transactielog, wat niet altijd is toegestaan of technisch mogelijk is.

Log-based CDC koppelt goed aan streaming platformen — zie Apache Kafka voor hoe CDC-events vaak als topic worden gepubliceerd en verderop in near-realtime worden verwerkt.

3. Trigger-based CDC

Database-triggers schrijven bij elke wijziging een record naar een aparte audit- of change-tabel. Werkt op vrijwel elk RDBMS zonder extra tooling, maar voegt overhead toe aan elke transactie in de bron en is lastiger te onderhouden bij schemawijzigingen.

4. Hash-based CDC (full comparison)

Als de bron geen betrouwbare timestamp of transactielog heeft, kun je per rij een hash berekenen over alle kolommen en die vergelijken met de hash van de vorige run. Wijkt de hash af, dan is de rij gewijzigd. Robuust, maar rekenkundig zwaar — in feite een full load met slimme vergelijking, vaak gebruikt als terugvaloptie.

-- Hash-vergelijking om wijzigingen te detecteren zonder betrouwbare timestamp
SELECT
    klant_id,
    MD5(CONCAT_WS('|', naam, adres, email, status)) AS row_hash
FROM bron.klanten;
-- vergelijk row_hash met de opgeslagen hash van de vorige run

De Wijzigingen Verwerken: Upsert en MERGE

Zodra je weet wélke rijen zijn gewijzigd, moet je ze correct in de doeltabel verwerken: nieuwe rijen invoegen, bestaande rijen bijwerken. Dat combinatiepatroon heet een upsert (update + insert), en vrijwel elk modern platform ondersteunt dit via een MERGE-statement.

Standaard SQL MERGE

MERGE INTO analytics.klanten AS target
USING staging.klanten_delta AS source
ON target.klant_id = source.klant_id

WHEN MATCHED THEN
    UPDATE SET
        naam       = source.naam,
        adres      = source.adres,
        email      = source.email,
        updated_at = source.updated_at

WHEN NOT MATCHED THEN
    INSERT (klant_id, naam, adres, email, updated_at)
    VALUES (source.klant_id, source.naam, source.adres, source.email, source.updated_at);

Delta Lake / Databricks: MERGE INTO

Delta Lake ondersteunt hetzelfde patroon, inclusief het afhandelen van deletes wanneer de bron die als event meegeeft (bijvoorbeeld via log-based CDC):

MERGE INTO analytics.klanten AS target
USING cdc_events AS source
ON target.klant_id = source.klant_id

WHEN MATCHED AND source.operation = 'DELETE' THEN DELETE

WHEN MATCHED AND source.operation = 'UPDATE' THEN
    UPDATE SET *

WHEN NOT MATCHED AND source.operation = 'INSERT' THEN
    INSERT *

dbt: incremental models

In dbt markeer je een model als incremental en definieer je een uniek-sleutel (unique_key). dbt genereert dan automatisch de MERGE-logica op basis van het onderliggende platform.

-- models/klanten_incremental.sql
{{
  config(
    materialized='incremental',
    unique_key='klant_id',
    incremental_strategy='merge'
  )
}}

SELECT *
FROM {{ source('bron', 'klanten') }}

{% if is_incremental() %}
  WHERE updated_at > (SELECT MAX(updated_at) FROM {{ this }})
{% endif %}

Het is_incremental()-blok wordt alleen uitgevoerd bij een bestaande doeltabel — de eerste run is automatisch een full load die de tabel opbouwt. Zie ook dbt vs Snowflake DCM voor hoe dit zich verhoudt tot objectbeheer.

Full Load vs Incremental Load: Samengevat

Dimensie Full Load Incremental Load
Laadtijd Lineair met totale datasetgrootte Lineair met alleen de wijzigingen
Belasting op bron Hoog — volledige extractie elke run Laag — alleen gewijzigde rijen
Complexiteit Laag — geen wijzigingsdetectie nodig Hoger — CDC, watermarks, MERGE-logica
Omgaan met deletes Automatisch correct (volledige vervanging) Vraagt expliciete aanpak (soft delete of log-based CDC)
Foutherstel Zelfherstellend bij volgende run Vraagt reprocessing of backfill-logica
Historisering Vereist expliciete toevoeging (SCD) Natuurlijker te combineren met SCD Type 2
Kosten op schaal Stijgt mee met datasetgrootte Stijgt mee met wijzigingsvolume — vaak veel lager
Geschikt voor Kleine/statische datasets, referentiedata, dimensietabellen Grote of snelgroeiende feittabellen, transactiedata, events

Welke Strategie Kies Je? Een Praktische Beslisboom

  • Dataset kleiner dan een paar miljoen rijen én laadtijd geen probleem? Kies full load. De eenvoud en betrouwbaarheid wegen zwaarder dan de winst van incremental load.
  • Bron heeft geen betrouwbare wijzigingsindicator en je hebt geen toegang tot het transactielog? Begin met full load, of val terug op hash-based CDC als de kosten dat rechtvaardigen.
  • Dataset groeit snel, of de bron is een operationele database die je niet zwaar wil belasten? Kies incremental load — bij voorkeur log-based CDC als je toegang hebt tot het transactielog.
  • Referentie- of dimensiedata die zelden verandert (landen, productcategorieën)? Full load is vaak simpeler en de overhead is verwaarloosbaar.
  • Near-realtime inzicht nodig? Alleen incremental load (met log-based CDC en streaming) maakt dat haalbaar — een full load van een grote tabel elke paar minuten is zelden realistisch.

Vuistregel

Begin bij twijfel met full load. Het is de eenvoudigste weg naar een werkende pipeline. Migreer pas naar incremental load zodra laadtijd, kosten of belasting op de bron een aantoonbaar probleem worden — voortijdig optimaliseren voegt complexiteit toe die je (nog) niet nodig hebt.

Veelvoorkomende Valkuilen bij Incremental Load

Gemiste harde deletes

Timestamp-based CDC ziet geen verwijderde rijen. Los dit op met soft deletes (een is_deleted-vlag die door de bronapplicatie wordt gezet in plaats van een echte DELETE), log-based CDC, of een periodieke reconciliatiecontrole die het aantal rijen in bron en doel vergelijkt.

Late-arriving data

Een rij met een timestamp van gisteren komt soms pas vandaag binnen (bijvoorbeeld door een vertraagde batch-job elders in de keten). Als je watermark al voorbij die timestamp is, mis je de rij stilzwijgend. Werk met een overlapvenster — haal bijvoorbeeld altijd de laatste 24 uur opnieuw op in plaats van precies vanaf de vorige watermark — en dedupliceer op basis van de unieke sleutel in de MERGE-stap.

Out-of-order events

Bij streaming CDC kunnen events in een andere volgorde aankomen dan ze zijn ontstaan. Zonder een sequence-nummer of event-timestamp in de MERGE-logica kan een oudere wijziging een nieuwere overschrijven. Vergelijk daarom altijd op een monotoon oplopend veld, niet alleen op aankomstvolgorde.

Schema drift

Een nieuwe kolom in de bron wordt bij full load automatisch meegenomen (de hele tabel wordt immers herbouwd), maar bij incremental load kan een hardgecodeerde kolomlijst in je MERGE-statement dat missen. Bouw expliciete schema-checks in, of gebruik MERGE ... UPDATE SET * waar het platform dat ondersteunt.

Backfill na een fout

Als een incremental-run faalt of foute data wegschrijft, kun je niet zomaar "opnieuw draaien" zoals bij full load — de watermark staat al verder. Zorg voor een expliciete backfill-procedure: watermark terugzetten naar een eerder punt, of de run idempotent maken zodat herhaling geen dubbele of foute data oplevert.

Hybride Aanpak: Het Beste van Twee Werelden

In de praktijk kiezen de meeste volwassen dataplatformen niet voor het één óf het ander, maar voor een combinatie:

  • Dagelijkse (of vaker) incremental loads voor snelheid en lage belasting op de bron.
  • Periodieke full load als reconciliatie — bijvoorbeeld wekelijks of maandelijks in een rustig venster — om drift, gemiste deletes en verschoven data recht te zetten.

Deze aanpak past goed bij het bredere idee van betrouwbare pipelines: zie Data Pipeline Best Practices voor meer patronen rond betrouwbaarheid en idempotentie, en Data Contracts voor hoe je vooraf afspraken maakt over wat een "wijziging" precies betekent tussen bron en doel.

Conclusie

Full load en incremental load zijn geen concurrerende technologieën maar twee gereedschappen met een andere afweging tussen eenvoud en efficiëntie. Full load is de veilige, voorspelbare basis; incremental load is de schaalbare aanpak die vraagt om zorgvuldige wijzigingsdetectie (CDC), correcte upsert-logica en aandacht voor edge cases als deletes, late-arriving data en backfills.

De juiste keuze hangt af van datasetgrootte, de belasting die de bron aankan, de gewenste actualiteit en hoeveel engineering-tijd je kunt investeren. Begin eenvoudig, meet waar de pijn zit, en migreer gericht naar incremental load waar het verschil maakt.

Twijfel je welke laadstrategie bij jouw dataplatform past, of wil je een bestaande full-load pipeline omzetten naar incremental? Neem contact op — ik denk graag mee. Zie ook Slowly Changing Dimensions voor hoe je historie bijhoudt zodra je incrementeel laadt, en Apache Kafka voor near-realtime CDC-verwerking.

Veelgestelde vragen

Wat is het verschil tussen full load en incremental load?

Bij een full load haal je bij elke run de volledige dataset opnieuw op en vervang je de doeltabel. Bij een incremental load haal je alleen de nieuwe of gewijzigde records sinds de vorige run op en verwerk je die met een upsert (MERGE) in de doeltabel.

Wat is Change Data Capture (CDC)?

Change Data Capture is een verzameling technieken om te detecteren welke rijen in een bron zijn gewijzigd sinds de vorige extractie. Bekende varianten zijn timestamp-based CDC, log-based CDC (transactielog uitlezen) en trigger-based CDC.

Wanneer kies je voor full load in plaats van incremental load?

Full load is geschikt bij kleine datasets, bronnen zonder betrouwbare wijzigingsindicator, of wanneer eenvoud en garantie op consistentie zwaarder wegen dan performance. Incremental load is de betere keuze bij grote of snelgroeiende datasets waar verwerkingstijd en belasting van de bron een probleem worden.

Hoe ga je om met verwijderde records bij incremental load?

Timestamp-based CDC ziet harde deletes niet, omdat een verwijderde rij geen gewijzigde "updated_at" meer heeft. Oplossingen zijn: soft deletes (een is_deleted-vlag in de bron), log-based CDC (die DELETE-events wel registreert), of periodieke full-load reconciliatie om verschillen te detecteren.

Wat is een hybride laadstrategie?

Een hybride aanpak combineert dagelijkse (of vaker) incremental loads voor snelheid met een periodieke full load — bijvoorbeeld wekelijks of maandelijks — als reconciliatiestap om drift, gemiste deletes en verschoven data recht te zetten.

Snowflake DCM Projects Alle blogs Dynamic Tables vs Views