Commit 33cca1d
authored
feat: Enable concurrent microbatch execution (#1326)
Resolves #914
### Description
Declares `MicrobatchConcurrency` adapter capability so dbt-core 1.9+ can
execute microbatch incremental batches in parallel threads instead of
sequentially.
Per reviewer feedback from @sd-db, the capability is **gated behind the
`use_concurrent_microbatch` behavior flag** (default: `false`). Users
opt in via:
```yaml
# dbt_project.yml
flags:
use_concurrent_microbatch: true
```
When the flag is disabled (default),
`adapter.supports(MicrobatchConcurrency)` returns `False` and dbt-core
falls back to sequential batch execution — identical to current
behavior.
### Implementation
1. **`USE_CONCURRENT_MICROBATCH` behavior flag** — module-level
`BehaviorFlag` with `default=False`, registered in `_behavior_flags`
2. **`supports()` instance method override** — intercepts
`Capability.MicrobatchConcurrency` and gates on the flag; delegates all
other capabilities to `super().supports()`
3. **`MicrobatchConcurrency` removed from `_capabilities` dict** — the
`supports()` override is the sole gatekeeper (if the capability stayed
in `_capabilities`, `super().supports()` would return `True` regardless
of the flag)
4. **Unit tests** — disabled-by-default, enabled-with-flag, guard test
(capability not declared as Full in `_capabilities`), delegation
regression test
### Integration test findings (Databricks cluster, `batch_size='day'`,
31 batches, `--threads 4`)
| Run | Flag | Batches OK | Notes |
|-----|------|-----------|-------|
| Sequential | `false` | 31/31 | Correct fallback, warning emitted |
| Concurrent | `true` | 13-30/31 | `DELTA_CONCURRENT_APPEND` on
non-partitioned tables |
**Key finding: `REPLACE WHERE` predicates are non-overlapping** (each
batch is exactly one `batch_size` wide, regardless of `lookback`), **but
non-partitioned Delta tables still conflict** because Delta's
`WriteSerializable` isolation cannot verify non-overlap at the file
level — it conservatively rejects concurrent conditional overwrites to
the same table root.
A secondary error class (`DELTA_METADATA_CHANGED`) occurs when
dbt-databricks applies `SET TBLPROPERTIES` (e.g., `autoCompact`) per
batch, conflicting with concurrent writes.
**Safe configurations for concurrent microbatch:**
- Partition the target table by `event_time` at the same granularity as
`batch_size` (allows Delta to verify non-overlap at the partition level)
- Avoid per-batch `tblproperties` changes
- `DATABRICKS_SKIP_OPTIMIZE=true` prevents post-write OPTIMIZE conflicts
(but does not prevent the core `REPLACE WHERE` conflict)
**`lookback` is NOT a factor** — it only controls which batches are
generated (shifts the start of the batch list backwards), not the width
of any individual batch's `REPLACE WHERE` predicate.
**The `default=false` is the correct safe choice.** The default can be
flipped to `true` around 1.12 once partitioning guidance and/or retry
logic is established.
**Prior art:** dbt-snowflake added the same capability in
[dbt-snowflake#1259](dbt-labs/dbt-snowflake#1259).
### Checklist
- [x] I have run this code in development and it appears to resolve the
stated issue
- [x] This PR includes tests, or tests are not required/relevant for
this PR
- [x] I have updated the `CHANGELOG.md` and added information about my
change to the "dbt-databricks next" section.
---------
Signed-off-by: Wyatt Jones <wyatt.jones6@cfacorp.com>1 parent 24325a3 commit 33cca1d
3 files changed
Lines changed: 37 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
1 | 10 | | |
2 | 11 | | |
3 | 12 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
141 | 141 | | |
142 | 142 | | |
143 | 143 | | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
144 | 155 | | |
145 | 156 | | |
146 | 157 | | |
| |||
246 | 257 | | |
247 | 258 | | |
248 | 259 | | |
| 260 | + | |
249 | 261 | | |
250 | 262 | | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
251 | 269 | | |
252 | 270 | | |
253 | 271 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
| |||
169 | 170 | | |
170 | 171 | | |
171 | 172 | | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
0 commit comments