ETL против ELT
Урок разбирает два подхода к построению конвейера — ETL и ELT — и помогает выбрать правильный.
ETL — Extract, Transform, Load: извлечь, преобразовать, загрузить. ELT — Extract, Load, Transform: извлечь, загрузить сырыми, преобразовать уже внутри хранилища.
Три буквы конвейера
Любой пакетный конвейер состоит из трёх шагов: Extract (забрать данные из источника), Transform (очистить, привести к нужному виду, посчитать) и Load (положить в приёмник). Разница между ETL и ELT — только в порядке шагов T и L.
ETL: Extract → Transform → Load (преобразуем ДО загрузки)
ELT: Extract → Load → Transform (грузим сырьё, преобразуем ВНУТРИ)Когда какой подход
ETL — классика
Преобразование происходит на отдельном сервере конвейера до записи в хранилище. Так делали десятилетиями, когда хранилища были дорогими и медленными — туда клали только готовые, очищенные данные. ETL хорош, когда нужно строго контролировать, что попадает в хранилище, или скрывать персональные данные ещё на входе. Минус — преобразования живут в коде конвейера, и чтобы изменить логику, часто приходится переписать пайплайн и перекачать данные заново.
ELT — современный подход
Сырые данные грузят в облачное хранилище (Snowflake, BigQuery, ClickHouse), а преобразования пишут на SQL уже там. Хранилища стали дешёвыми и мощными, поэтому считать прямо в них выгоднее. Бонус: сырьё сохранено, и логику преобразований можно переписать задним числом, не выкачивая данные заново. Это огромное преимущество для аналитики, где требования меняются постоянно: добавили новую метрику — просто написали ещё одну SQL-модель поверх того же сырья, и backfill пересчитал историю.
| Критерий | ETL | ELT |
| Где преобразование | на сервере конвейера | внутри хранилища (SQL) |
| Хранится сырьё | обычно нет | да |
| Типичный стек | Python, Spark | SQL, dbt |
Как работает под капотом
Покажем шаг Transform на чистом Python: фильтруем строки и приводим валюту к рублям до загрузки (это «T» в ETL).
rows = [
{"id": 1, "sum": 100, "cur": "USD"},
{"id": 2, "sum": 50, "cur": "RUB"},
{"id": 3, "sum": 0, "cur": "RUB"},
]
rate = {"USD": 90, "RUB": 1}
clean = [
{"id": r["id"], "rub": r["sum"] * rate[r["cur"]]}
for r in rows if r["sum"] > 0
]
for r in clean:
print(r)Вывод:
{'id': 1, 'rub': 9000}
{'id': 2, 'rub': 50}А вот тот же Transform, но в стиле ELT — на SQL прямо в хранилище, куда сырьё уже загружено.
CREATE TABLE raw_orders (id INTEGER, sum INTEGER, cur TEXT);
INSERT INTO raw_orders VALUES (1, 100, 'USD'), (2, 50, 'RUB'), (3, 0, 'RUB');
SELECT id,
sum * CASE cur WHEN 'USD' THEN 90 ELSE 1 END AS rub
FROM raw_orders
WHERE sum > 0;Логика одна и та же — отфильтровать пустые заказы и пересчитать валюту, — но в ETL она исполняется на сервере конвейера на Python, а в ELT уже внутри хранилища на SQL. Заметьте: в ELT-версии сырая таблица raw_orders остаётся нетронутой, и если завтра курс доллара поменяется, достаточно переписать SELECT, не трогая загрузку. Именно эта гибкость и сделала связку «ELT + dbt» индустриальным стандартом для аналитических хранилищ.
Частые ошибки
- Думать, что ELT всегда лучше. Если в данных есть персональные сведения, которые нельзя хранить сырыми, ETL с очисткой на входе уместнее.
- Грузить «всё подряд» в ELT без плана. Дешёвое хранилище не повод сваливать туда мусор — это превращается в неуправляемое болото данных.
- Путать порядок букв. В ELT сырьё ложится в хранилище до преобразования, а не после.
Итог
- ETL и ELT отличаются порядком шагов Transform и Load.
- ETL преобразует до загрузки, ELT — внутри хранилища на SQL.
- Дешёвые облачные хранилища сделали ELT подходом по умолчанию для аналитики.