The pipeline now supports batch processing for large SQL operations to prevent long-running transactions that can block PostgreSQL and cause performance issues.
Previously, mapping operations executed queries like:
INSERT INTO mapping_table (way_id, data, ...)
SELECT ...
FROM ways_base w -- millions of rows
JOIN LATERAL (...)
This could:
The new batching system automatically:
Add to your config.yaml under database:
database:
# ... existing config ...
performance:
enable_batching: true # Enable batch processing
default_batch_size: 10000 # Default rows per batch
batch_commit_interval: 5000 # Commit every N rows (0 = per batch only)
Override batch size for specific datasources:
datasources:
- name: "my_heavy_datasource"
# ... other config ...
mapping:
enable: true
batch_size: 5000 # Override global default for this datasource
strategy:
type: sql_template
config:
sql: |
INSERT INTO ...
# Your complex query here
The system detects queries that are suitable for batching:
INSERT INTO ... SELECTJOIN clauses (typically mapping queries)ways_base)Before (single query):
INFO: Starting SQL execution...
INFO: SQL execution completed. [10 minutes later]
After (batched):
INFO: Using batched execution for Mapping with batch size: 10000
INFO: Total rows to process: 125000, batch size: 10000
INFO: Processing in 13 batches...
INFO: Processing batch 1/13 (rows 1-10000)
INFO: Batch 1 completed in 45.23s (10000 rows affected)
INFO: Processing batch 2/13 (rows 10001-20000)
INFO: Batch 2 completed in 43.12s (10000 rows affected)
...
INFO: All 13 batches completed successfully
The system automatically transforms queries:
Original:
INSERT INTO trial.mapping_table (way_id, data)
SELECT w.id, e.data
FROM trial.ways_base w
JOIN enrichment e ON ...
Batched (Batch 1):
INSERT INTO trial.mapping_table (way_id, data)
SELECT w.id, e.data
FROM (SELECT * FROM trial.ways_base LIMIT 10000 OFFSET 0) w
JOIN enrichment e ON ...
Batched (Batch 2):
INSERT INTO trial.mapping_table (way_id, data)
SELECT w.id, e.data
FROM (SELECT * FROM trial.ways_base LIMIT 10000 OFFSET 10000) w
JOIN enrichment e ON ...
Look for log messages:
INFO: Batch 1 completed in 45.23s (10000 rows affected)
INFO: Batch 2 completed in 43.12s (10000 rows affected)
If batches slow down over time:
While batched queries run:
-- Check active queries
SELECT pid, state, query_start, query
FROM pg_stat_activity
WHERE state = 'active';
-- Check lock waits
SELECT * FROM pg_locks WHERE NOT granted;
To disable batching globally:
database:
performance:
enable_batching: false
To disable for specific datasource:
mapping:
batch_size: 0 # 0 or null disables batching
Or remove the performance config entirely to use original behavior.
For queries that need custom batching logic, you can call call_sql_batched() directly:
# In your mapper class
def mapping_db_query(self):
# Build your query
query = "INSERT INTO ... SELECT ..."
# Don't return it - execute with custom batch size
self.db.call_sql_batched(
query,
batch_size=5000,
base_id_column="id", # Column to use for ordering
raise_on_error=True
)
return None # Already executed
INSERT INTO ... SELECT ... JOIN_extract_base_table_from_sql()default_batch_sizebatch_commit_interval to smaller valuework_mem settingPotential improvements: