Engineering High-Throughput ETL Pipelines: Ingesting 41TB of Document Data
Lessons learned from building batch and incremental ETL pipelines to extract, transform, and aggregate 41 terabytes of official document records for data science analytics.
At enterprise scale, processing transactional data is straightforward until you encounter tens of terabytes of historical documents, scanned correspondence, metadata attachments, and relational logs.
When spearheading the migration of 41 Terabytes of official electronic document data into the Ministry of Finance Data Center, our goal was clear: establish a dependable, verified data foundation that data scientists and analysts could query with high performance.
The Architecture of the 41TB Ingestion Pipeline
Ingesting massive workloads requires decoupling extraction from transformation to prevent overwhelming source operational databases.
+---------------------+ +--------------------+ +---------------------+
| Source App Database | --> | Staging Chunk Lake | --> | Transformation & |
| (OLTP SQL Server) | | (Encrypted Blob) | | Validation (Python) |
+---------------------+ +--------------------+ +---------------------+
|
v
+---------------------+
| Central Data Center |
| Data Warehouse (DW) |
+---------------------+
1. Chunked Partitioning & Incremental Extraction
Instead of broad table queries, we divided the 41TB dataset by deterministic date ranges and partition keys. Python workers queried slices concurrently, buffering records into memory before streaming to staging tables:
import pyodbc
import pandas as pd
from typing import Iterator
def fetch_document_chunks(connection_str: str, batch_size: int = 50000) -> Iterator[pd.DataFrame]:
query = """
SELECT DocId, RegisteredDate, ClassificationCode, MetadataJSON, Checksum
FROM OfficialDocuments WITH (NOLOCK)
WHERE ProcessedFlag = 0
ORDER BY RegisteredDate ASC
"""
with pyodbc.connect(connection_str) as conn:
for chunk in pd.read_sql(query, conn, chunksize=batch_size):
yield chunk
[!TIP] Always use
WITH (NOLOCK)or read-committed snapshot isolation (RCSI) on transactional sources during heavy ETL extraction to prevent locking operational records during business hours.
2. SQL Server Columnstore Indexing & Aggregations
For analytical queries across billions of rows, traditional rowstore B-trees consume immense disk space and cause heavy I/O overhead. By creating Clustered Columnstore Indexes (CCI) on fact tables, we achieved up to 10x data compression and sub-second aggregation query performance for Jupyter analytics.
CREATE CLUSTERED COLUMNSTORE INDEX CCI_FactDocumentArchive
ON FactDocumentArchive;
3. Data Quality & Checksum Validation
To guarantee zero corruption across 41TB of institutional records, our pipeline calculated SHA-256 cryptographic checksums on extraction and verified them upon insertion into the destination data warehouse.
Key Outcomes
- Successfully migrated and verified 41TB of official electronic records with 100% data integrity.
- Enabled data science and analytics teams to perform complex statistical models and aggregate exploratory queries in Jupyter Notebooks effortlessly.