Learning Platform
Глоссарий Troubleshooting
Урок 18.03 · 22 мин
Начальный
Selectorstagpathstateresource_typeconfigCI

В прошлом уроке мы разобрали базовые селекторы по имени и направлению в DAG. Но dbt позволяет выбирать узлы и по их свойствам — тегам, пути, типу ресурса, материализации, изменённости. Это и есть «селектор-методы», и они открывают сценарии, без которых не построить нормальный CI.

Синтаксис: method:value

Метод — это префикс в формате имя:значение:

dbt run --select tag:daily
dbt run --select path:models/staging
dbt run --select resource_type:test
dbt run --select config.materialized:incremental

Это говорит dbt: «найди все узлы DAG, у которых указанный атрибут равен указанному значению».

Главные селектор-методы

Восемь методов покрывают 90% реальных нужд. Большинство комбинируется с + и + для расширения на соседей в DAG.

tag:dailyузлы с тегом daily
path:models/stagingузлы в этой папке
resource_type:testтолько тесты
config.materialized:tableпо конфигу материализации
state:modifiedизменённые vs base manifest
source:jaffleузлы из этого source
group:financeузлы из группы
package:dbt_utilsузлы из пакета

tag: — теги

Теги — это произвольные метки, которые ты ставишь моделям в YAML или в {{ config() }} блоке. Они нужны исключительно для удобства селекции.

В YAML:

models:
  - name: revenue_daily
    config:
      tags: ['daily', 'finance']

В Jinja:

{{ config(tags=['daily', 'finance']) }}

select ...

Затем в CLI:

dbt run --select tag:daily         # всё с тегом daily
dbt run --select tag:finance       # всё с тегом finance

Один узел может иметь много тегов — селектор tag:daily подберёт все, где daily есть в списке.

Стандартные практики тегирования:

  • tag:hourly | tag:daily | tag:weekly — расписание запуска
  • tag:finance | tag:marketing | tag:ops — доменная зона
  • tag:pii — модель содержит персональные данные (для compliance-фильтров)
  • tag:slow — известно тяжёлая модель, исключаем в локальной разработке

В dbt_project.yml можно задавать теги массово:

models:
  jaffle_shop:
    marts:
      finance:
        +tags: ['finance']

Все модели в models/marts/finance/ получат тег finance автоматически.


path: — по пути в файловой системе

path: фильтрует по пути относительно корня проекта:

dbt run --select path:models/staging
dbt run --select path:models/marts/finance

Это эквивалентно «папочному» селектору (staging или marts.finance), но более явно. Полезно когда название папки совпадает с именем модели — path: снимает неоднозначность.

Также path: поддерживает обычный путь без models/ префикса — для seeds, snapshots, tests:

dbt run --select path:seeds          # все seeds
dbt test --select path:tests         # все singular tests

resource_type: — тип узла

В DAG dbt живут разные типы узлов:

  • model — обычные SQL/Python модели
  • seed — CSV-сиды
  • snapshot — снэпшоты
  • test — тесты (generic + singular)
  • source — таблицы-источники
  • exposure — exposures
  • analysis — analysis-файлы
  • metric — метрики (1.6+)

Фильтрация по типу:

dbt list --select resource_type:model       # только модели
dbt list --select resource_type:test        # только тесты
dbt list --select resource_type:snapshot    # только снэпшоты

В команде dbt build все типы запускаются вместе — но в dbt list или для специфичных операций часто нужно ограничиться одним типом.


config.<param>:<value> — по конфигу

Можно фильтровать узлы по любому конфигу, который задаётся через {{ config() }} или YAML:

dbt run --select config.materialized:incremental
dbt run --select config.materialized:table
dbt run --select config.schema:marketing

Особенно полезно config.materialized:incremental — когда хочется запустить только инкрементальные модели (например, в почасовом крон-джобе).

config.tags:daily — то же, что tag:daily. Но конфиги покрывают вообще всё, включая кастомные параметры:

models:
  - name: revenue_daily
    config:
      meta:
        owner: 'finance-team'
dbt run --select config.meta.owner:finance-team

source: — выбор по источнику

source: фильтрует тесты и модели по source, к которому они привязаны:

dbt test --select source:jaffle              # все тесты на source jaffle
dbt run --select source:jaffle+              # все модели, зависящие от source jaffle

source:jaffle+ — это «всё, что вниз по DAG от sources в jaffle». Очень частый паттерн для проверки «что у меня сломается, если такой-то источник изменится».

Также можно указать конкретную таблицу: source:jaffle.customers.


state:modified — что изменилось

Самый важный селектор для CI. Чтобы он работал, нужен второй manifest — обычно manifest с предыдущего production-билда, который называется state baseline.

dbt run --select "state:modified" --state ./prod-manifest

dbt сравнит текущий код проекта с предыдущим manifest и выберет только изменённые узлы. Что считается «изменённым»:

  • изменён SQL/Python код модели
  • изменён {{ config() }} блок
  • изменён description, тест, или любой YAML конфиг
  • изменилась версия пакета
  • новые модели (modified.body)

Подвиды для тонкой фильтрации:

  • state:modified.body — только SQL/Python код
  • state:modified.configs — только конфиги (теги, материализация и т.п.)
  • state:modified.contract — изменились контракты модели
  • state:modified.relation — изменилось имя таблицы или схема

В CI типичная команда:

dbt build --select "state:modified+" --state ./prod-manifest

state:modified+ означает «изменённые узлы плюс всё downstream от них». То есть «то, что изменилось, и всё, на что оно повлияет».

TIP

Чтобы --state работал, в CI пайплайне нужно сначала скачать manifest.json с прошлого зелёного билда (артефакт из CI или объект из S3), затем дать на него путь через --state. Без этого state:modified упадёт с ошибкой “no state manifest found”.


group: и package:

group: фильтрует по dbt-группе (логическая группа моделей с access-контролем, 1.5+):

dbt run --select group:finance

package: — по пакету (главный проект называется именем из dbt_project.yml, пакеты — именем из packages.yml):

dbt list --select package:dbt_utils
dbt run --select package:jaffle_shop

В junior-проекте обычно одни и те же модели лежат в главном пакете, package: используется реже — пока в проект не подключатся внешние модели через пакеты.


Комбинирование методов с операторами

Все селектор-методы можно комбинировать с +, запятой, пробелом:

# Всё upstream от моделей с тегом daily
dbt run --select +tag:daily

# Всё downstream от моделей в staging
dbt run --select path:models/staging+

# Только инкрементальные модели в папке marts
dbt run --select "config.materialized:incremental path:models/marts"

# Изменённые модели в финансовой группе плюс их downstream
dbt build --select "state:modified group:finance"+ --state ./prod-manifest

Семантика та же, что и для имён: пробел = AND, запятая = OR.


tag:, config.tags: — точное место в YAML

Несколько нюансов:

  • tag:daily ищет тег в любом конфиге (Jinja, YAML, dbt_project.yml).
  • config.tags:daily — то же самое явно.

Разницы нет, можно писать как удобно.


Распространённые рецепты для CI

Рецепт 1: Минимальный CI-билд после PR

# Скачать manifest с прошлого зелёного билда
aws s3 cp s3://dbt-artifacts/manifest.json ./prod-manifest/manifest.json

# Билд только того, что изменилось
dbt build --select "state:modified+" --state ./prod-manifest

Рецепт 2: «Слим CI» — только тесты на изменённых

# Только тесты на изменённых моделях (быстро, для smoke check)
dbt test --select "state:modified,test_type:generic" --state ./prod-manifest

Рецепт 3: Production-почасовой джоб

# Все инкрементальные модели + тесты
dbt build --select "config.materialized:incremental+,tag:hourly+"

Рецепт 4: Локальная разработка — всё, кроме медленных

dbt run --exclude tag:slow

Рецепт 5: Проверить blast-radius source

# Что сломается, если изменится stg_orders?
dbt list --select stg_orders+ --resource-type model

Попробуй сам

В Jaffle Shop:

  1. Затэгай две модели daily через YAML и {{ config() }}. Запусти dbt run --select tag:daily.

  2. Список всех тестов:

    dbt list --select resource_type:test
  3. Список всех инкрементальных моделей (если есть):

    dbt list --select config.materialized:incremental
  4. Сделай небольшое изменение в stg_orders.sql. Скопируй текущий target/manifest.json в ./prod-manifest/manifest.json. Затем измени stg_orders.sql снова. Запусти:

    dbt list --select "state:modified" --state ./prod-manifest

    Должна выйти stg_orders. Затем state:modified+ — выйдут все downstream.


Чек-лист

  • tag: — для расписаний и доменов (hourly, daily, finance, pii).
  • path: — для папок (path:models/staging).
  • resource_type:model, test, seed, snapshot, source, exposure.
  • config.materialized:view, table, incremental, ephemeral.
  • source:source:jaffle или source:jaffle.customers.
  • state:modified[+/.body/.configs/.contract/.relation] — главный CI-фильтр.
  • group: — для access-control групп (1.5+).
  • package: — для фильтрации по пакетам.
  • Методы комбинируются с +model+, model+, +model, запятой (UNION), пробелом (INTERSECT).
  • state:modified+ (плюс справа) — must-have для CI: «изменённое + downstream».
Slim CI в продакшне: state:modified+ полный пример CI/CD: базовая концепция
Проверка знанийKnowledge check
У тебя проект на 200 моделей, CI на каждый PR обычно занимает 25 минут. Нужно ускорить — в PR обычно меняется 1-3 модели. Какую команду поставить в CI после dbt deps, чтобы билдить только изменённое плюс затронутый downstream, и почему важно --state, и почему именно "+" справа а не слева?
ОтветAnswer
Команда: dbt build --select "state:modified+" --state ./prod-manifest. --state указывает на baseline manifest — snapshot предыдущего зелёного билда проекта; без него dbt не с чем сравнить и не поймёт, что изменилось (state:modified упадёт). Префикс state:modified выбирает только узлы с изменениями (код модели, YAML конфиг, тест и т.д.). Постфикс "+" справа добавляет весь downstream — то есть всё, что зависит от изменённых моделей и тоже должно быть пересобрано и протестировано. "+" слева добавил бы upstream — это не нужно, потому что upstream не изменился и уже актуален в warehouse. Типичный baseline собирается раз в день в main-билде, артефакт manifest.json сохраняется в S3, и PR-CI его скачивает перед запуском.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 6. Что выберет селектор state:modified+ при наличии baseline manifest через --state?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4