Orchestrating dbt with Airflow - Time & Space Complexity
When using Airflow to run dbt tasks, it's important to understand how the total time grows as you add more dbt models or steps.
We want to know how the orchestration time changes when the number of dbt tasks increases.
Analyze the time complexity of this Airflow DAG running dbt models sequentially.
from airflow import DAG
from airflow.operators.bash import BashOperator
from datetime import datetime
def create_dbt_task(model_name, dag):
return BashOperator(
task_id=f'dbt_run_{model_name}',
bash_command=f'dbt run --models {model_name}',
dag=dag
)
dag = DAG('dbt_sequential', start_date=datetime(2024,1,1))
models = ['model1', 'model2', 'model3', 'model4']
previous_task = None
for model in models:
task = create_dbt_task(model, dag)
if previous_task:
previous_task >> task
previous_task = task
This code runs dbt models one after another in Airflow, waiting for each to finish before starting the next.
Look at what repeats as the input grows.
- Primary operation: Running each dbt model as a separate Airflow task.
- How many times: Once per model, so the number of tasks equals the number of models.
As you add more dbt models, the total time grows because each model runs one after another.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 dbt runs, one after another |
| 100 | 100 dbt runs, sequentially |
| 1000 | 1000 dbt runs, sequentially |
Pattern observation: The total time grows roughly in direct proportion to the number of models.
Time Complexity: O(n)
This means the total orchestration time grows linearly as you add more dbt models to run one after another.
[X] Wrong: "Running multiple dbt models in Airflow always happens at the same time, so time stays the same no matter how many models."
[OK] Correct: In this setup, models run one after another, so adding more models adds more total time.
Understanding how task orchestration time grows helps you design workflows that scale well and keep pipelines efficient.
What if we changed the Airflow DAG to run all dbt models in parallel instead of sequentially? How would the time complexity change?
Practice
Solution
Step 1: Understand Airflow's role
Airflow is a tool to automate and schedule tasks, including dbt commands.Step 2: Connect Airflow with dbt
Using Airflow, you can run dbt commands automatically and in order without manual intervention.Final Answer:
To automate and schedule dbt commands in a specific order -> Option AQuick Check:
Airflow automates dbt runs = C [OK]
- Thinking Airflow replaces dbt's SQL modeling
- Confusing manual and automated runs
- Assuming Airflow visualizes dbt models
Solution
Step 1: Identify how dbt commands run
dbt commands run in the shell or terminal, so Airflow needs an operator that runs shell commands.Step 2: Match operator to shell commands
BashOperator runs bash shell commands, perfect for running dbt CLI commands inside Airflow.Final Answer:
BashOperator -> Option AQuick Check:
BashOperator runs shell commands = A [OK]
- Choosing PythonOperator which runs Python code, not shell commands
- Confusing HttpOperator with web requests
- Thinking EmailOperator runs commands
dbt_run = BashOperator(task_id='dbt_run', bash_command='dbt run') dbt_test = BashOperator(task_id='dbt_test', bash_command='dbt test') dbt_run >> dbt_test
Solution
Step 1: Understand the dependency operator
The '>>' operator in Airflow means the left task runs before the right task.Step 2: Apply to given tasks
dbt_run >> dbt_test means dbt_run runs first, then dbt_test runs after it finishes.Final Answer:
dbt_run runs first, then dbt_test -> Option BQuick Check:
dbt_run >> dbt_test means run then test = A [OK]
- Thinking >> means parallel execution
- Reversing the order of tasks
- Assuming only one task runs
dbt_test = BashOperator(task_id='dbt_test', bash_command='dbt test')
dbt_test.set_upstream('dbt_run')Solution
Step 1: Check set_upstream usage
set_upstream expects another task object, not a string task id.Step 2: Identify correct usage
It should be dbt_test.set_upstream(dbt_run) where dbt_run is the task object, not 'dbt_run' string.Final Answer:
set_upstream expects a task object, not a string -> Option CQuick Check:
set_upstream needs task object = B [OK]
- Passing string instead of task object to set_upstream
- Thinking bash_command must be a list
- Believing task_id has naming restrictions
- Assuming BashOperator can't run dbt
dbt run, then dbt test, and finally sends an email notification only if tests pass. Which sequence correctly sets task dependencies?Solution
Step 1: Define correct task order
First, run models with dbt run, then test them with dbt test, and finally notify if tests pass.Step 2: Set dependencies accordingly
Use '>>' to chain tasks in order: dbt_run >> dbt_test >> email_notify.Final Answer:
dbt_run >> dbt_test >> email_notify -> Option DQuick Check:
Run then test then notify = D [OK]
- Placing email notification before tests
- Reversing run and test order
- Skipping dependencies causing parallel runs
Ready to prove it?
Pass the test and this pattern moves unknown
