[{"data":1,"prerenderedAt":2716},["ShallowReactive",2],{"article-alternates":3,"article-\u002Fru\u002Fdata\u002Fdbt-bigquery-modern-pazarlama-veri-yigini":13},{"i18nKey":4,"paths":5},"data-002-2026-08",{"de":6,"en":7,"es":8,"fr":9,"it":10,"ru":11,"tr":12},"\u002Fde\u002Fdata\u002Fdbt-bigquery-moderner-marketing-data-stack","\u002Fen\u002Fdata\u002Fdbt-bigquery-modern-marketing-data-stack","\u002Fes\u002Fdata\u002Fdbt-bigquery-modern-marketing-data-stack","\u002Ffr\u002Fdata\u002Fdbt-bigquery-modern-pazarlama-data-stack","\u002Fit\u002Fdata\u002Fdbt-bigquery-modern-data-stack-marketing","\u002Fru\u002Fdata\u002Fdbt-bigquery-modern-pazarlama-veri-yigini","\u002Ftr\u002Fdata\u002Fdbt-bigquery-ile-modern-pazarlama-data-stack",{"_path":11,"_dir":14,"_draft":15,"_partial":15,"_locale":16,"title":17,"description":18,"publishedAt":19,"modifiedAt":19,"category":20,"i18nKey":4,"tags":21,"readingTime":27,"author":28,"body":29,"_type":2710,"_id":2711,"_source":2712,"_file":2713,"_stem":2714,"_extension":2715},"data",false,"","dbt + BigQuery ile Современный маркетинговый Data Stack","Source mapping, modeling layer, semantic layer, exposures — маркетинговые данные, соединённые с механизмом принятия решений: архитектура и практическая реализация dbt.","2026-08-02","verianalizi",[22,23,24,25,26],"dbt","bigquery","data-stack","semantic-layer","marketing-analytics",9,"Roibase",{"type":30,"children":31,"toc":2698},"root",[32,40,47,61,285,298,325,661,674,680,692,1342,1347,1365,1372,1377,1618,1631,1637,1649,1912,1917,1927,1937,1943,1948,2109,2122,2148,2154,2167,2458,2479,2489,2495,2500,2539,2544,2565,2571,2576,2670,2687,2692],{"type":33,"tag":34,"props":35,"children":36},"element","p",{},[37],{"type":38,"value":39},"text","Маркетинговые команды больше не используют готовые отчёты из Google Analytics — они работают с собственными data pipeline'ами, где каждое правило написано ими. В 2026 году современный маркетинговый data stack состоит из трёх слоёв: raw source'ы, modeling layer и semantic layer. Эта статья показывает, как построить эти три слоя с помощью dbt + BigQuery, какие типичные ошибки возникают на каждом этапе и как создать устойчивую архитектуру для production.",{"type":33,"tag":41,"props":42,"children":44},"h2",{"id":43},"source-mapping-загрузить-данные-в-bigquery-недостаточно",[45],{"type":38,"value":46},"Source mapping: загрузить данные в BigQuery недостаточно",{"type":33,"tag":34,"props":48,"children":49},{},[50,52,59],{"type":38,"value":51},"Вы загрузили GA4, Meta Ads и события sGTM в BigQuery — но это только начало. Source mapping означает преобразование raw таблиц в значимые контракты данных. В dbt определения source'ов живут в ",{"type":33,"tag":53,"props":54,"children":56},"code",{"className":55},[],[57],{"type":38,"value":58},".yml",{"type":38,"value":60}," файлах:",{"type":33,"tag":62,"props":63,"children":67},"pre",{"className":64,"code":65,"language":66,"meta":16,"style":16},"language-yaml shiki shiki-themes github-dark","sources:\n  - name: raw_ga4\n    database: roibase-prod\n    schema: analytics_123456789\n    tables:\n      - name: events_*\n        identifier: events_*\n        loaded_at_field: event_timestamp\n        freshness:\n          warn_after: {count: 12, period: hour}\n","yaml",[68],{"type":33,"tag":53,"props":69,"children":70},{"__ignoreMap":16},[71,89,114,132,150,163,185,202,220,232],{"type":33,"tag":72,"props":73,"children":76},"span",{"class":74,"line":75},"line",1,[77,83],{"type":33,"tag":72,"props":78,"children":80},{"style":79},"--shiki-default:#85E89D",[81],{"type":38,"value":82},"sources",{"type":33,"tag":72,"props":84,"children":86},{"style":85},"--shiki-default:#E1E4E8",[87],{"type":38,"value":88},":\n",{"type":33,"tag":72,"props":90,"children":92},{"class":74,"line":91},2,[93,98,103,108],{"type":33,"tag":72,"props":94,"children":95},{"style":85},[96],{"type":38,"value":97},"  - ",{"type":33,"tag":72,"props":99,"children":100},{"style":79},[101],{"type":38,"value":102},"name",{"type":33,"tag":72,"props":104,"children":105},{"style":85},[106],{"type":38,"value":107},": ",{"type":33,"tag":72,"props":109,"children":111},{"style":110},"--shiki-default:#9ECBFF",[112],{"type":38,"value":113},"raw_ga4\n",{"type":33,"tag":72,"props":115,"children":117},{"class":74,"line":116},3,[118,123,127],{"type":33,"tag":72,"props":119,"children":120},{"style":79},[121],{"type":38,"value":122},"    database",{"type":33,"tag":72,"props":124,"children":125},{"style":85},[126],{"type":38,"value":107},{"type":33,"tag":72,"props":128,"children":129},{"style":110},[130],{"type":38,"value":131},"roibase-prod\n",{"type":33,"tag":72,"props":133,"children":135},{"class":74,"line":134},4,[136,141,145],{"type":33,"tag":72,"props":137,"children":138},{"style":79},[139],{"type":38,"value":140},"    schema",{"type":33,"tag":72,"props":142,"children":143},{"style":85},[144],{"type":38,"value":107},{"type":33,"tag":72,"props":146,"children":147},{"style":110},[148],{"type":38,"value":149},"analytics_123456789\n",{"type":33,"tag":72,"props":151,"children":153},{"class":74,"line":152},5,[154,159],{"type":33,"tag":72,"props":155,"children":156},{"style":79},[157],{"type":38,"value":158},"    tables",{"type":33,"tag":72,"props":160,"children":161},{"style":85},[162],{"type":38,"value":88},{"type":33,"tag":72,"props":164,"children":166},{"class":74,"line":165},6,[167,172,176,180],{"type":33,"tag":72,"props":168,"children":169},{"style":85},[170],{"type":38,"value":171},"      - ",{"type":33,"tag":72,"props":173,"children":174},{"style":79},[175],{"type":38,"value":102},{"type":33,"tag":72,"props":177,"children":178},{"style":85},[179],{"type":38,"value":107},{"type":33,"tag":72,"props":181,"children":182},{"style":110},[183],{"type":38,"value":184},"events_*\n",{"type":33,"tag":72,"props":186,"children":188},{"class":74,"line":187},7,[189,194,198],{"type":33,"tag":72,"props":190,"children":191},{"style":79},[192],{"type":38,"value":193},"        identifier",{"type":33,"tag":72,"props":195,"children":196},{"style":85},[197],{"type":38,"value":107},{"type":33,"tag":72,"props":199,"children":200},{"style":110},[201],{"type":38,"value":184},{"type":33,"tag":72,"props":203,"children":205},{"class":74,"line":204},8,[206,211,215],{"type":33,"tag":72,"props":207,"children":208},{"style":79},[209],{"type":38,"value":210},"        loaded_at_field",{"type":33,"tag":72,"props":212,"children":213},{"style":85},[214],{"type":38,"value":107},{"type":33,"tag":72,"props":216,"children":217},{"style":110},[218],{"type":38,"value":219},"event_timestamp\n",{"type":33,"tag":72,"props":221,"children":222},{"class":74,"line":27},[223,228],{"type":33,"tag":72,"props":224,"children":225},{"style":79},[226],{"type":38,"value":227},"        freshness",{"type":33,"tag":72,"props":229,"children":230},{"style":85},[231],{"type":38,"value":88},{"type":33,"tag":72,"props":233,"children":235},{"class":74,"line":234},10,[236,241,246,251,255,261,266,271,275,280],{"type":33,"tag":72,"props":237,"children":238},{"style":79},[239],{"type":38,"value":240},"          warn_after",{"type":33,"tag":72,"props":242,"children":243},{"style":85},[244],{"type":38,"value":245},": {",{"type":33,"tag":72,"props":247,"children":248},{"style":79},[249],{"type":38,"value":250},"count",{"type":33,"tag":72,"props":252,"children":253},{"style":85},[254],{"type":38,"value":107},{"type":33,"tag":72,"props":256,"children":258},{"style":257},"--shiki-default:#79B8FF",[259],{"type":38,"value":260},"12",{"type":33,"tag":72,"props":262,"children":263},{"style":85},[264],{"type":38,"value":265},", ",{"type":33,"tag":72,"props":267,"children":268},{"style":79},[269],{"type":38,"value":270},"period",{"type":33,"tag":72,"props":272,"children":273},{"style":85},[274],{"type":38,"value":107},{"type":33,"tag":72,"props":276,"children":277},{"style":110},[278],{"type":38,"value":279},"hour",{"type":33,"tag":72,"props":281,"children":282},{"style":85},[283],{"type":38,"value":284},"}\n",{"type":33,"tag":34,"props":286,"children":287},{},[288,290,296],{"type":38,"value":289},"Это определение выполняет три функции: (1) Data lineage — какая модель использует какую raw таблицу, (2) Freshness check — если последнее событие старше 12 часов, выдаётся предупреждение, (3) Contract — если отсутствует колонка ",{"type":33,"tag":53,"props":291,"children":293},{"className":292},[],[294],{"type":38,"value":295},"event_timestamp",{"type":38,"value":297},", build падает.",{"type":33,"tag":34,"props":299,"children":300},{},[301,307,309,315,317,323],{"type":33,"tag":302,"props":303,"children":304},"strong",{},[305],{"type":38,"value":306},"Самая частая ошибка:",{"type":38,"value":308}," использование raw schema'ы как есть. Писать SQL с nested array'ем GA4 ",{"type":33,"tag":53,"props":310,"children":312},{"className":311},[],[313],{"type":38,"value":314},"event_params",{"type":38,"value":316}," без flatten'инга означает, что каждый запрос займёт 200+ строк. Logic ",{"type":33,"tag":53,"props":318,"children":320},{"className":319},[],[321],{"type":38,"value":322},"unnest",{"type":38,"value":324}," должна жить в одном месте на этапе source mapping:",{"type":33,"tag":62,"props":326,"children":330},{"className":327,"code":328,"language":329,"meta":16,"style":16},"language-sql shiki shiki-themes github-dark","-- models\u002Fstaging\u002Fstg_ga4_events.sql\nwith source as (\n  select * from {{ source('raw_ga4', 'events_*') }}\n),\n\nflattened as (\n  select\n    event_date,\n    event_timestamp,\n    user_pseudo_id,\n    (select value.string_value from unnest(event_params) where key = 'session_id') as session_id,\n    (select value.int_value from unnest(event_params) where key = 'ga_session_number') as session_number\n  from source\n)\n\nselect * from flattened\n","sql",[331],{"type":33,"tag":53,"props":332,"children":333},{"__ignoreMap":16},[334,343,367,409,417,426,442,450,458,466,474,546,609,623,632,640],{"type":33,"tag":72,"props":335,"children":336},{"class":74,"line":75},[337],{"type":33,"tag":72,"props":338,"children":340},{"style":339},"--shiki-default:#6A737D",[341],{"type":38,"value":342},"-- models\u002Fstaging\u002Fstg_ga4_events.sql\n",{"type":33,"tag":72,"props":344,"children":345},{"class":74,"line":91},[346,352,357,362],{"type":33,"tag":72,"props":347,"children":349},{"style":348},"--shiki-default:#F97583",[350],{"type":38,"value":351},"with",{"type":33,"tag":72,"props":353,"children":354},{"style":85},[355],{"type":38,"value":356}," source ",{"type":33,"tag":72,"props":358,"children":359},{"style":348},[360],{"type":38,"value":361},"as",{"type":33,"tag":72,"props":363,"children":364},{"style":85},[365],{"type":38,"value":366}," (\n",{"type":33,"tag":72,"props":368,"children":369},{"class":74,"line":116},[370,375,380,385,390,395,399,404],{"type":33,"tag":72,"props":371,"children":372},{"style":348},[373],{"type":38,"value":374},"  select",{"type":33,"tag":72,"props":376,"children":377},{"style":348},[378],{"type":38,"value":379}," *",{"type":33,"tag":72,"props":381,"children":382},{"style":348},[383],{"type":38,"value":384}," from",{"type":33,"tag":72,"props":386,"children":387},{"style":85},[388],{"type":38,"value":389}," {{ source(",{"type":33,"tag":72,"props":391,"children":392},{"style":110},[393],{"type":38,"value":394},"'raw_ga4'",{"type":33,"tag":72,"props":396,"children":397},{"style":85},[398],{"type":38,"value":265},{"type":33,"tag":72,"props":400,"children":401},{"style":110},[402],{"type":38,"value":403},"'events_*'",{"type":33,"tag":72,"props":405,"children":406},{"style":85},[407],{"type":38,"value":408},") }}\n",{"type":33,"tag":72,"props":410,"children":411},{"class":74,"line":134},[412],{"type":33,"tag":72,"props":413,"children":414},{"style":85},[415],{"type":38,"value":416},"),\n",{"type":33,"tag":72,"props":418,"children":419},{"class":74,"line":152},[420],{"type":33,"tag":72,"props":421,"children":423},{"emptyLinePlaceholder":422},true,[424],{"type":38,"value":425},"\n",{"type":33,"tag":72,"props":427,"children":428},{"class":74,"line":165},[429,434,438],{"type":33,"tag":72,"props":430,"children":431},{"style":85},[432],{"type":38,"value":433},"flattened ",{"type":33,"tag":72,"props":435,"children":436},{"style":348},[437],{"type":38,"value":361},{"type":33,"tag":72,"props":439,"children":440},{"style":85},[441],{"type":38,"value":366},{"type":33,"tag":72,"props":443,"children":444},{"class":74,"line":187},[445],{"type":33,"tag":72,"props":446,"children":447},{"style":348},[448],{"type":38,"value":449},"  select\n",{"type":33,"tag":72,"props":451,"children":452},{"class":74,"line":204},[453],{"type":33,"tag":72,"props":454,"children":455},{"style":85},[456],{"type":38,"value":457},"    event_date,\n",{"type":33,"tag":72,"props":459,"children":460},{"class":74,"line":27},[461],{"type":33,"tag":72,"props":462,"children":463},{"style":85},[464],{"type":38,"value":465},"    event_timestamp,\n",{"type":33,"tag":72,"props":467,"children":468},{"class":74,"line":234},[469],{"type":33,"tag":72,"props":470,"children":471},{"style":85},[472],{"type":38,"value":473},"    user_pseudo_id,\n",{"type":33,"tag":72,"props":475,"children":477},{"class":74,"line":476},11,[478,483,488,493,498,503,507,512,517,522,527,532,537,541],{"type":33,"tag":72,"props":479,"children":480},{"style":85},[481],{"type":38,"value":482},"    (",{"type":33,"tag":72,"props":484,"children":485},{"style":348},[486],{"type":38,"value":487},"select",{"type":33,"tag":72,"props":489,"children":490},{"style":257},[491],{"type":38,"value":492}," value",{"type":33,"tag":72,"props":494,"children":495},{"style":85},[496],{"type":38,"value":497},".",{"type":33,"tag":72,"props":499,"children":500},{"style":257},[501],{"type":38,"value":502},"string_value",{"type":33,"tag":72,"props":504,"children":505},{"style":348},[506],{"type":38,"value":384},{"type":33,"tag":72,"props":508,"children":509},{"style":85},[510],{"type":38,"value":511}," unnest(event_params) ",{"type":33,"tag":72,"props":513,"children":514},{"style":348},[515],{"type":38,"value":516},"where",{"type":33,"tag":72,"props":518,"children":519},{"style":348},[520],{"type":38,"value":521}," key",{"type":33,"tag":72,"props":523,"children":524},{"style":348},[525],{"type":38,"value":526}," =",{"type":33,"tag":72,"props":528,"children":529},{"style":110},[530],{"type":38,"value":531}," 'session_id'",{"type":33,"tag":72,"props":533,"children":534},{"style":85},[535],{"type":38,"value":536},") ",{"type":33,"tag":72,"props":538,"children":539},{"style":348},[540],{"type":38,"value":361},{"type":33,"tag":72,"props":542,"children":543},{"style":85},[544],{"type":38,"value":545}," session_id,\n",{"type":33,"tag":72,"props":547,"children":549},{"class":74,"line":548},12,[550,554,558,562,566,571,575,579,583,587,591,596,600,604],{"type":33,"tag":72,"props":551,"children":552},{"style":85},[553],{"type":38,"value":482},{"type":33,"tag":72,"props":555,"children":556},{"style":348},[557],{"type":38,"value":487},{"type":33,"tag":72,"props":559,"children":560},{"style":257},[561],{"type":38,"value":492},{"type":33,"tag":72,"props":563,"children":564},{"style":85},[565],{"type":38,"value":497},{"type":33,"tag":72,"props":567,"children":568},{"style":257},[569],{"type":38,"value":570},"int_value",{"type":33,"tag":72,"props":572,"children":573},{"style":348},[574],{"type":38,"value":384},{"type":33,"tag":72,"props":576,"children":577},{"style":85},[578],{"type":38,"value":511},{"type":33,"tag":72,"props":580,"children":581},{"style":348},[582],{"type":38,"value":516},{"type":33,"tag":72,"props":584,"children":585},{"style":348},[586],{"type":38,"value":521},{"type":33,"tag":72,"props":588,"children":589},{"style":348},[590],{"type":38,"value":526},{"type":33,"tag":72,"props":592,"children":593},{"style":110},[594],{"type":38,"value":595}," 'ga_session_number'",{"type":33,"tag":72,"props":597,"children":598},{"style":85},[599],{"type":38,"value":536},{"type":33,"tag":72,"props":601,"children":602},{"style":348},[603],{"type":38,"value":361},{"type":33,"tag":72,"props":605,"children":606},{"style":85},[607],{"type":38,"value":608}," session_number\n",{"type":33,"tag":72,"props":610,"children":612},{"class":74,"line":611},13,[613,618],{"type":33,"tag":72,"props":614,"children":615},{"style":348},[616],{"type":38,"value":617},"  from",{"type":33,"tag":72,"props":619,"children":620},{"style":85},[621],{"type":38,"value":622}," source\n",{"type":33,"tag":72,"props":624,"children":626},{"class":74,"line":625},14,[627],{"type":33,"tag":72,"props":628,"children":629},{"style":85},[630],{"type":38,"value":631},")\n",{"type":33,"tag":72,"props":633,"children":635},{"class":74,"line":634},15,[636],{"type":33,"tag":72,"props":637,"children":638},{"emptyLinePlaceholder":422},[639],{"type":38,"value":425},{"type":33,"tag":72,"props":641,"children":643},{"class":74,"line":642},16,[644,648,652,656],{"type":33,"tag":72,"props":645,"children":646},{"style":348},[647],{"type":38,"value":487},{"type":33,"tag":72,"props":649,"children":650},{"style":348},[651],{"type":38,"value":379},{"type":33,"tag":72,"props":653,"children":654},{"style":348},[655],{"type":38,"value":384},{"type":33,"tag":72,"props":657,"children":658},{"style":85},[659],{"type":38,"value":660}," flattened\n",{"type":33,"tag":34,"props":662,"children":663},{},[664,666,672],{"type":38,"value":665},"Теперь эта модель вызывается downstream'ом через ",{"type":33,"tag":53,"props":667,"children":669},{"className":668},[],[670],{"type":38,"value":671},"ref('stg_ga4_events')",{"type":38,"value":673}," — синтаксис raw event_params изолирован upstream. Freshness check запускается ежедневно, изменения schema автоматически вызывают ошибки.",{"type":33,"tag":41,"props":675,"children":677},{"id":676},"modeling-layer-определите-метрику-один-раз-используйте-сто-раз",[678],{"type":38,"value":679},"Modeling layer: определите метрику один раз, используйте сто раз",{"type":33,"tag":34,"props":681,"children":682},{},[683,685,690],{"type":38,"value":684},"После staging layer идёт modeling layer. Здесь разделяются intermediate модели (business logic) и mart модели (aggregation). В маркетинговом data stack самая критичная модель — это ",{"type":33,"tag":302,"props":686,"children":687},{},[688],{"type":38,"value":689},"session → transaction",{"type":38,"value":691}," join:",{"type":33,"tag":62,"props":693,"children":695},{"className":327,"code":694,"language":329,"meta":16,"style":16},"-- models\u002Fmarts\u002Fmrt_session_metrics.sql\nwith sessions as (\n  select * from {{ ref('int_sessions') }}\n),\n\ntransactions as (\n  select * from {{ ref('int_transactions') }}\n),\n\njoined as (\n  select\n    s.session_id,\n    s.session_date,\n    s.traffic_source,\n    s.medium,\n    s.campaign,\n    t.transaction_id,\n    t.revenue,\n    t.transaction_timestamp\n  from sessions s\n  left join transactions t\n    on s.session_id = t.session_id\n)\n\nselect\n  session_date,\n  traffic_source,\n  medium,\n  campaign,\n  count(distinct session_id) as sessions,\n  count(distinct transaction_id) as transactions,\n  sum(revenue) as total_revenue,\n  safe_divide(count(distinct transaction_id), count(distinct session_id)) as conversion_rate\nfrom joined\ngroup by 1, 2, 3, 4\n",[696],{"type":33,"tag":53,"props":697,"children":698},{"__ignoreMap":16},[699,707,728,757,764,771,787,815,822,829,845,852,874,894,914,934,954,976,997,1014,1031,1045,1085,1093,1101,1110,1119,1128,1137,1146,1182,1212,1235,1287,1301],{"type":33,"tag":72,"props":700,"children":701},{"class":74,"line":75},[702],{"type":33,"tag":72,"props":703,"children":704},{"style":339},[705],{"type":38,"value":706},"-- models\u002Fmarts\u002Fmrt_session_metrics.sql\n",{"type":33,"tag":72,"props":708,"children":709},{"class":74,"line":91},[710,714,719,724],{"type":33,"tag":72,"props":711,"children":712},{"style":348},[713],{"type":38,"value":351},{"type":33,"tag":72,"props":715,"children":716},{"style":348},[717],{"type":38,"value":718}," sessions",{"type":33,"tag":72,"props":720,"children":721},{"style":348},[722],{"type":38,"value":723}," as",{"type":33,"tag":72,"props":725,"children":726},{"style":85},[727],{"type":38,"value":366},{"type":33,"tag":72,"props":729,"children":730},{"class":74,"line":116},[731,735,739,743,748,753],{"type":33,"tag":72,"props":732,"children":733},{"style":348},[734],{"type":38,"value":374},{"type":33,"tag":72,"props":736,"children":737},{"style":348},[738],{"type":38,"value":379},{"type":33,"tag":72,"props":740,"children":741},{"style":348},[742],{"type":38,"value":384},{"type":33,"tag":72,"props":744,"children":745},{"style":85},[746],{"type":38,"value":747}," {{ ref(",{"type":33,"tag":72,"props":749,"children":750},{"style":110},[751],{"type":38,"value":752},"'int_sessions'",{"type":33,"tag":72,"props":754,"children":755},{"style":85},[756],{"type":38,"value":408},{"type":33,"tag":72,"props":758,"children":759},{"class":74,"line":134},[760],{"type":33,"tag":72,"props":761,"children":762},{"style":85},[763],{"type":38,"value":416},{"type":33,"tag":72,"props":765,"children":766},{"class":74,"line":152},[767],{"type":33,"tag":72,"props":768,"children":769},{"emptyLinePlaceholder":422},[770],{"type":38,"value":425},{"type":33,"tag":72,"props":772,"children":773},{"class":74,"line":165},[774,779,783],{"type":33,"tag":72,"props":775,"children":776},{"style":85},[777],{"type":38,"value":778},"transactions ",{"type":33,"tag":72,"props":780,"children":781},{"style":348},[782],{"type":38,"value":361},{"type":33,"tag":72,"props":784,"children":785},{"style":85},[786],{"type":38,"value":366},{"type":33,"tag":72,"props":788,"children":789},{"class":74,"line":187},[790,794,798,802,806,811],{"type":33,"tag":72,"props":791,"children":792},{"style":348},[793],{"type":38,"value":374},{"type":33,"tag":72,"props":795,"children":796},{"style":348},[797],{"type":38,"value":379},{"type":33,"tag":72,"props":799,"children":800},{"style":348},[801],{"type":38,"value":384},{"type":33,"tag":72,"props":803,"children":804},{"style":85},[805],{"type":38,"value":747},{"type":33,"tag":72,"props":807,"children":808},{"style":110},[809],{"type":38,"value":810},"'int_transactions'",{"type":33,"tag":72,"props":812,"children":813},{"style":85},[814],{"type":38,"value":408},{"type":33,"tag":72,"props":816,"children":817},{"class":74,"line":204},[818],{"type":33,"tag":72,"props":819,"children":820},{"style":85},[821],{"type":38,"value":416},{"type":33,"tag":72,"props":823,"children":824},{"class":74,"line":27},[825],{"type":33,"tag":72,"props":826,"children":827},{"emptyLinePlaceholder":422},[828],{"type":38,"value":425},{"type":33,"tag":72,"props":830,"children":831},{"class":74,"line":234},[832,837,841],{"type":33,"tag":72,"props":833,"children":834},{"style":85},[835],{"type":38,"value":836},"joined ",{"type":33,"tag":72,"props":838,"children":839},{"style":348},[840],{"type":38,"value":361},{"type":33,"tag":72,"props":842,"children":843},{"style":85},[844],{"type":38,"value":366},{"type":33,"tag":72,"props":846,"children":847},{"class":74,"line":476},[848],{"type":33,"tag":72,"props":849,"children":850},{"style":348},[851],{"type":38,"value":449},{"type":33,"tag":72,"props":853,"children":854},{"class":74,"line":548},[855,860,864,869],{"type":33,"tag":72,"props":856,"children":857},{"style":257},[858],{"type":38,"value":859},"    s",{"type":33,"tag":72,"props":861,"children":862},{"style":85},[863],{"type":38,"value":497},{"type":33,"tag":72,"props":865,"children":866},{"style":257},[867],{"type":38,"value":868},"session_id",{"type":33,"tag":72,"props":870,"children":871},{"style":85},[872],{"type":38,"value":873},",\n",{"type":33,"tag":72,"props":875,"children":876},{"class":74,"line":611},[877,881,885,890],{"type":33,"tag":72,"props":878,"children":879},{"style":257},[880],{"type":38,"value":859},{"type":33,"tag":72,"props":882,"children":883},{"style":85},[884],{"type":38,"value":497},{"type":33,"tag":72,"props":886,"children":887},{"style":257},[888],{"type":38,"value":889},"session_date",{"type":33,"tag":72,"props":891,"children":892},{"style":85},[893],{"type":38,"value":873},{"type":33,"tag":72,"props":895,"children":896},{"class":74,"line":625},[897,901,905,910],{"type":33,"tag":72,"props":898,"children":899},{"style":257},[900],{"type":38,"value":859},{"type":33,"tag":72,"props":902,"children":903},{"style":85},[904],{"type":38,"value":497},{"type":33,"tag":72,"props":906,"children":907},{"style":257},[908],{"type":38,"value":909},"traffic_source",{"type":33,"tag":72,"props":911,"children":912},{"style":85},[913],{"type":38,"value":873},{"type":33,"tag":72,"props":915,"children":916},{"class":74,"line":634},[917,921,925,930],{"type":33,"tag":72,"props":918,"children":919},{"style":257},[920],{"type":38,"value":859},{"type":33,"tag":72,"props":922,"children":923},{"style":85},[924],{"type":38,"value":497},{"type":33,"tag":72,"props":926,"children":927},{"style":257},[928],{"type":38,"value":929},"medium",{"type":33,"tag":72,"props":931,"children":932},{"style":85},[933],{"type":38,"value":873},{"type":33,"tag":72,"props":935,"children":936},{"class":74,"line":642},[937,941,945,950],{"type":33,"tag":72,"props":938,"children":939},{"style":257},[940],{"type":38,"value":859},{"type":33,"tag":72,"props":942,"children":943},{"style":85},[944],{"type":38,"value":497},{"type":33,"tag":72,"props":946,"children":947},{"style":257},[948],{"type":38,"value":949},"campaign",{"type":33,"tag":72,"props":951,"children":952},{"style":85},[953],{"type":38,"value":873},{"type":33,"tag":72,"props":955,"children":957},{"class":74,"line":956},17,[958,963,967,972],{"type":33,"tag":72,"props":959,"children":960},{"style":257},[961],{"type":38,"value":962},"    t",{"type":33,"tag":72,"props":964,"children":965},{"style":85},[966],{"type":38,"value":497},{"type":33,"tag":72,"props":968,"children":969},{"style":257},[970],{"type":38,"value":971},"transaction_id",{"type":33,"tag":72,"props":973,"children":974},{"style":85},[975],{"type":38,"value":873},{"type":33,"tag":72,"props":977,"children":979},{"class":74,"line":978},18,[980,984,988,993],{"type":33,"tag":72,"props":981,"children":982},{"style":257},[983],{"type":38,"value":962},{"type":33,"tag":72,"props":985,"children":986},{"style":85},[987],{"type":38,"value":497},{"type":33,"tag":72,"props":989,"children":990},{"style":257},[991],{"type":38,"value":992},"revenue",{"type":33,"tag":72,"props":994,"children":995},{"style":85},[996],{"type":38,"value":873},{"type":33,"tag":72,"props":998,"children":1000},{"class":74,"line":999},19,[1001,1005,1009],{"type":33,"tag":72,"props":1002,"children":1003},{"style":257},[1004],{"type":38,"value":962},{"type":33,"tag":72,"props":1006,"children":1007},{"style":85},[1008],{"type":38,"value":497},{"type":33,"tag":72,"props":1010,"children":1011},{"style":257},[1012],{"type":38,"value":1013},"transaction_timestamp\n",{"type":33,"tag":72,"props":1015,"children":1017},{"class":74,"line":1016},20,[1018,1022,1026],{"type":33,"tag":72,"props":1019,"children":1020},{"style":348},[1021],{"type":38,"value":617},{"type":33,"tag":72,"props":1023,"children":1024},{"style":348},[1025],{"type":38,"value":718},{"type":33,"tag":72,"props":1027,"children":1028},{"style":85},[1029],{"type":38,"value":1030}," s\n",{"type":33,"tag":72,"props":1032,"children":1034},{"class":74,"line":1033},21,[1035,1040],{"type":33,"tag":72,"props":1036,"children":1037},{"style":348},[1038],{"type":38,"value":1039},"  left join",{"type":33,"tag":72,"props":1041,"children":1042},{"style":85},[1043],{"type":38,"value":1044}," transactions t\n",{"type":33,"tag":72,"props":1046,"children":1048},{"class":74,"line":1047},22,[1049,1054,1059,1063,1067,1071,1076,1080],{"type":33,"tag":72,"props":1050,"children":1051},{"style":348},[1052],{"type":38,"value":1053},"    on",{"type":33,"tag":72,"props":1055,"children":1056},{"style":257},[1057],{"type":38,"value":1058}," s",{"type":33,"tag":72,"props":1060,"children":1061},{"style":85},[1062],{"type":38,"value":497},{"type":33,"tag":72,"props":1064,"children":1065},{"style":257},[1066],{"type":38,"value":868},{"type":33,"tag":72,"props":1068,"children":1069},{"style":348},[1070],{"type":38,"value":526},{"type":33,"tag":72,"props":1072,"children":1073},{"style":257},[1074],{"type":38,"value":1075}," t",{"type":33,"tag":72,"props":1077,"children":1078},{"style":85},[1079],{"type":38,"value":497},{"type":33,"tag":72,"props":1081,"children":1082},{"style":257},[1083],{"type":38,"value":1084},"session_id\n",{"type":33,"tag":72,"props":1086,"children":1088},{"class":74,"line":1087},23,[1089],{"type":33,"tag":72,"props":1090,"children":1091},{"style":85},[1092],{"type":38,"value":631},{"type":33,"tag":72,"props":1094,"children":1096},{"class":74,"line":1095},24,[1097],{"type":33,"tag":72,"props":1098,"children":1099},{"emptyLinePlaceholder":422},[1100],{"type":38,"value":425},{"type":33,"tag":72,"props":1102,"children":1104},{"class":74,"line":1103},25,[1105],{"type":33,"tag":72,"props":1106,"children":1107},{"style":348},[1108],{"type":38,"value":1109},"select\n",{"type":33,"tag":72,"props":1111,"children":1113},{"class":74,"line":1112},26,[1114],{"type":33,"tag":72,"props":1115,"children":1116},{"style":85},[1117],{"type":38,"value":1118},"  session_date,\n",{"type":33,"tag":72,"props":1120,"children":1122},{"class":74,"line":1121},27,[1123],{"type":33,"tag":72,"props":1124,"children":1125},{"style":85},[1126],{"type":38,"value":1127},"  traffic_source,\n",{"type":33,"tag":72,"props":1129,"children":1131},{"class":74,"line":1130},28,[1132],{"type":33,"tag":72,"props":1133,"children":1134},{"style":85},[1135],{"type":38,"value":1136},"  medium,\n",{"type":33,"tag":72,"props":1138,"children":1140},{"class":74,"line":1139},29,[1141],{"type":33,"tag":72,"props":1142,"children":1143},{"style":85},[1144],{"type":38,"value":1145},"  campaign,\n",{"type":33,"tag":72,"props":1147,"children":1149},{"class":74,"line":1148},30,[1150,1155,1160,1165,1170,1174,1178],{"type":33,"tag":72,"props":1151,"children":1152},{"style":257},[1153],{"type":38,"value":1154},"  count",{"type":33,"tag":72,"props":1156,"children":1157},{"style":85},[1158],{"type":38,"value":1159},"(",{"type":33,"tag":72,"props":1161,"children":1162},{"style":348},[1163],{"type":38,"value":1164},"distinct",{"type":33,"tag":72,"props":1166,"children":1167},{"style":85},[1168],{"type":38,"value":1169}," session_id) ",{"type":33,"tag":72,"props":1171,"children":1172},{"style":348},[1173],{"type":38,"value":361},{"type":33,"tag":72,"props":1175,"children":1176},{"style":348},[1177],{"type":38,"value":718},{"type":33,"tag":72,"props":1179,"children":1180},{"style":85},[1181],{"type":38,"value":873},{"type":33,"tag":72,"props":1183,"children":1185},{"class":74,"line":1184},31,[1186,1190,1194,1198,1203,1207],{"type":33,"tag":72,"props":1187,"children":1188},{"style":257},[1189],{"type":38,"value":1154},{"type":33,"tag":72,"props":1191,"children":1192},{"style":85},[1193],{"type":38,"value":1159},{"type":33,"tag":72,"props":1195,"children":1196},{"style":348},[1197],{"type":38,"value":1164},{"type":33,"tag":72,"props":1199,"children":1200},{"style":85},[1201],{"type":38,"value":1202}," transaction_id) ",{"type":33,"tag":72,"props":1204,"children":1205},{"style":348},[1206],{"type":38,"value":361},{"type":33,"tag":72,"props":1208,"children":1209},{"style":85},[1210],{"type":38,"value":1211}," transactions,\n",{"type":33,"tag":72,"props":1213,"children":1215},{"class":74,"line":1214},32,[1216,1221,1226,1230],{"type":33,"tag":72,"props":1217,"children":1218},{"style":257},[1219],{"type":38,"value":1220},"  sum",{"type":33,"tag":72,"props":1222,"children":1223},{"style":85},[1224],{"type":38,"value":1225},"(revenue) ",{"type":33,"tag":72,"props":1227,"children":1228},{"style":348},[1229],{"type":38,"value":361},{"type":33,"tag":72,"props":1231,"children":1232},{"style":85},[1233],{"type":38,"value":1234}," total_revenue,\n",{"type":33,"tag":72,"props":1236,"children":1238},{"class":74,"line":1237},33,[1239,1244,1248,1252,1256,1261,1265,1269,1273,1278,1282],{"type":33,"tag":72,"props":1240,"children":1241},{"style":85},[1242],{"type":38,"value":1243},"  safe_divide(",{"type":33,"tag":72,"props":1245,"children":1246},{"style":257},[1247],{"type":38,"value":250},{"type":33,"tag":72,"props":1249,"children":1250},{"style":85},[1251],{"type":38,"value":1159},{"type":33,"tag":72,"props":1253,"children":1254},{"style":348},[1255],{"type":38,"value":1164},{"type":33,"tag":72,"props":1257,"children":1258},{"style":85},[1259],{"type":38,"value":1260}," transaction_id), ",{"type":33,"tag":72,"props":1262,"children":1263},{"style":257},[1264],{"type":38,"value":250},{"type":33,"tag":72,"props":1266,"children":1267},{"style":85},[1268],{"type":38,"value":1159},{"type":33,"tag":72,"props":1270,"children":1271},{"style":348},[1272],{"type":38,"value":1164},{"type":33,"tag":72,"props":1274,"children":1275},{"style":85},[1276],{"type":38,"value":1277}," session_id)) ",{"type":33,"tag":72,"props":1279,"children":1280},{"style":348},[1281],{"type":38,"value":361},{"type":33,"tag":72,"props":1283,"children":1284},{"style":85},[1285],{"type":38,"value":1286}," conversion_rate\n",{"type":33,"tag":72,"props":1288,"children":1290},{"class":74,"line":1289},34,[1291,1296],{"type":33,"tag":72,"props":1292,"children":1293},{"style":348},[1294],{"type":38,"value":1295},"from",{"type":33,"tag":72,"props":1297,"children":1298},{"style":85},[1299],{"type":38,"value":1300}," joined\n",{"type":33,"tag":72,"props":1302,"children":1304},{"class":74,"line":1303},35,[1305,1310,1315,1319,1324,1328,1333,1337],{"type":33,"tag":72,"props":1306,"children":1307},{"style":348},[1308],{"type":38,"value":1309},"group by",{"type":33,"tag":72,"props":1311,"children":1312},{"style":257},[1313],{"type":38,"value":1314}," 1",{"type":33,"tag":72,"props":1316,"children":1317},{"style":85},[1318],{"type":38,"value":265},{"type":33,"tag":72,"props":1320,"children":1321},{"style":257},[1322],{"type":38,"value":1323},"2",{"type":33,"tag":72,"props":1325,"children":1326},{"style":85},[1327],{"type":38,"value":265},{"type":33,"tag":72,"props":1329,"children":1330},{"style":257},[1331],{"type":38,"value":1332},"3",{"type":33,"tag":72,"props":1334,"children":1335},{"style":85},[1336],{"type":38,"value":265},{"type":33,"tag":72,"props":1338,"children":1339},{"style":257},[1340],{"type":38,"value":1341},"4\n",{"type":33,"tag":34,"props":1343,"children":1344},{},[1345],{"type":38,"value":1346},"Эта модель запускается ежедневно в 03:00 (dbt Cloud scheduler), Looker Studio подключается напрямую к этой таблице. Когда требуется изменение, вы меняете SQL в одном месте — все dashboard'ы обновляются автоматически.",{"type":33,"tag":34,"props":1348,"children":1349},{},[1350,1355,1357,1363],{"type":33,"tag":302,"props":1351,"children":1352},{},[1353],{"type":38,"value":1354},"Важная деталь:",{"type":38,"value":1356}," использование ",{"type":33,"tag":53,"props":1358,"children":1360},{"className":1359},[],[1361],{"type":38,"value":1362},"safe_divide",{"type":38,"value":1364}," — если sessions = 0, он не вызывает ошибку деления на ноль, а возвращает null. В production pipeline'е обработка исключений происходит на этом уровне.",{"type":33,"tag":1366,"props":1367,"children":1369},"h3",{"id":1368},"dbt-tests-автоматическая-проверка-качества-данных",[1370],{"type":38,"value":1371},"dbt tests: автоматическая проверка качества данных",{"type":33,"tag":34,"props":1373,"children":1374},{},[1375],{"type":38,"value":1376},"При определении метрик в modeling layer одновременно пишут тесты:",{"type":33,"tag":62,"props":1378,"children":1380},{"className":64,"code":1379,"language":66,"meta":16,"style":16},"# models\u002Fmarts\u002Fschema.yml\nmodels:\n  - name: mrt_session_metrics\n    columns:\n      - name: session_date\n        tests:\n          - not_null\n      - name: sessions\n        tests:\n          - not_null\n          - dbt_utils.expression_is_true:\n              expression: \">= 0\"\n      - name: conversion_rate\n        tests:\n          - dbt_utils.expression_is_true:\n              expression: \"\u003C= 1\"\n",[1381],{"type":33,"tag":53,"props":1382,"children":1383},{"__ignoreMap":16},[1384,1392,1404,1424,1436,1456,1468,1481,1501,1512,1523,1539,1556,1576,1587,1602],{"type":33,"tag":72,"props":1385,"children":1386},{"class":74,"line":75},[1387],{"type":33,"tag":72,"props":1388,"children":1389},{"style":339},[1390],{"type":38,"value":1391},"# models\u002Fmarts\u002Fschema.yml\n",{"type":33,"tag":72,"props":1393,"children":1394},{"class":74,"line":91},[1395,1400],{"type":33,"tag":72,"props":1396,"children":1397},{"style":79},[1398],{"type":38,"value":1399},"models",{"type":33,"tag":72,"props":1401,"children":1402},{"style":85},[1403],{"type":38,"value":88},{"type":33,"tag":72,"props":1405,"children":1406},{"class":74,"line":116},[1407,1411,1415,1419],{"type":33,"tag":72,"props":1408,"children":1409},{"style":85},[1410],{"type":38,"value":97},{"type":33,"tag":72,"props":1412,"children":1413},{"style":79},[1414],{"type":38,"value":102},{"type":33,"tag":72,"props":1416,"children":1417},{"style":85},[1418],{"type":38,"value":107},{"type":33,"tag":72,"props":1420,"children":1421},{"style":110},[1422],{"type":38,"value":1423},"mrt_session_metrics\n",{"type":33,"tag":72,"props":1425,"children":1426},{"class":74,"line":134},[1427,1432],{"type":33,"tag":72,"props":1428,"children":1429},{"style":79},[1430],{"type":38,"value":1431},"    columns",{"type":33,"tag":72,"props":1433,"children":1434},{"style":85},[1435],{"type":38,"value":88},{"type":33,"tag":72,"props":1437,"children":1438},{"class":74,"line":152},[1439,1443,1447,1451],{"type":33,"tag":72,"props":1440,"children":1441},{"style":85},[1442],{"type":38,"value":171},{"type":33,"tag":72,"props":1444,"children":1445},{"style":79},[1446],{"type":38,"value":102},{"type":33,"tag":72,"props":1448,"children":1449},{"style":85},[1450],{"type":38,"value":107},{"type":33,"tag":72,"props":1452,"children":1453},{"style":110},[1454],{"type":38,"value":1455},"session_date\n",{"type":33,"tag":72,"props":1457,"children":1458},{"class":74,"line":165},[1459,1464],{"type":33,"tag":72,"props":1460,"children":1461},{"style":79},[1462],{"type":38,"value":1463},"        tests",{"type":33,"tag":72,"props":1465,"children":1466},{"style":85},[1467],{"type":38,"value":88},{"type":33,"tag":72,"props":1469,"children":1470},{"class":74,"line":187},[1471,1476],{"type":33,"tag":72,"props":1472,"children":1473},{"style":85},[1474],{"type":38,"value":1475},"          - ",{"type":33,"tag":72,"props":1477,"children":1478},{"style":110},[1479],{"type":38,"value":1480},"not_null\n",{"type":33,"tag":72,"props":1482,"children":1483},{"class":74,"line":204},[1484,1488,1492,1496],{"type":33,"tag":72,"props":1485,"children":1486},{"style":85},[1487],{"type":38,"value":171},{"type":33,"tag":72,"props":1489,"children":1490},{"style":79},[1491],{"type":38,"value":102},{"type":33,"tag":72,"props":1493,"children":1494},{"style":85},[1495],{"type":38,"value":107},{"type":33,"tag":72,"props":1497,"children":1498},{"style":110},[1499],{"type":38,"value":1500},"sessions\n",{"type":33,"tag":72,"props":1502,"children":1503},{"class":74,"line":27},[1504,1508],{"type":33,"tag":72,"props":1505,"children":1506},{"style":79},[1507],{"type":38,"value":1463},{"type":33,"tag":72,"props":1509,"children":1510},{"style":85},[1511],{"type":38,"value":88},{"type":33,"tag":72,"props":1513,"children":1514},{"class":74,"line":234},[1515,1519],{"type":33,"tag":72,"props":1516,"children":1517},{"style":85},[1518],{"type":38,"value":1475},{"type":33,"tag":72,"props":1520,"children":1521},{"style":110},[1522],{"type":38,"value":1480},{"type":33,"tag":72,"props":1524,"children":1525},{"class":74,"line":476},[1526,1530,1535],{"type":33,"tag":72,"props":1527,"children":1528},{"style":85},[1529],{"type":38,"value":1475},{"type":33,"tag":72,"props":1531,"children":1532},{"style":79},[1533],{"type":38,"value":1534},"dbt_utils.expression_is_true",{"type":33,"tag":72,"props":1536,"children":1537},{"style":85},[1538],{"type":38,"value":88},{"type":33,"tag":72,"props":1540,"children":1541},{"class":74,"line":548},[1542,1547,1551],{"type":33,"tag":72,"props":1543,"children":1544},{"style":79},[1545],{"type":38,"value":1546},"              expression",{"type":33,"tag":72,"props":1548,"children":1549},{"style":85},[1550],{"type":38,"value":107},{"type":33,"tag":72,"props":1552,"children":1553},{"style":110},[1554],{"type":38,"value":1555},"\">= 0\"\n",{"type":33,"tag":72,"props":1557,"children":1558},{"class":74,"line":611},[1559,1563,1567,1571],{"type":33,"tag":72,"props":1560,"children":1561},{"style":85},[1562],{"type":38,"value":171},{"type":33,"tag":72,"props":1564,"children":1565},{"style":79},[1566],{"type":38,"value":102},{"type":33,"tag":72,"props":1568,"children":1569},{"style":85},[1570],{"type":38,"value":107},{"type":33,"tag":72,"props":1572,"children":1573},{"style":110},[1574],{"type":38,"value":1575},"conversion_rate\n",{"type":33,"tag":72,"props":1577,"children":1578},{"class":74,"line":625},[1579,1583],{"type":33,"tag":72,"props":1580,"children":1581},{"style":79},[1582],{"type":38,"value":1463},{"type":33,"tag":72,"props":1584,"children":1585},{"style":85},[1586],{"type":38,"value":88},{"type":33,"tag":72,"props":1588,"children":1589},{"class":74,"line":634},[1590,1594,1598],{"type":33,"tag":72,"props":1591,"children":1592},{"style":85},[1593],{"type":38,"value":1475},{"type":33,"tag":72,"props":1595,"children":1596},{"style":79},[1597],{"type":38,"value":1534},{"type":33,"tag":72,"props":1599,"children":1600},{"style":85},[1601],{"type":38,"value":88},{"type":33,"tag":72,"props":1603,"children":1604},{"class":74,"line":642},[1605,1609,1613],{"type":33,"tag":72,"props":1606,"children":1607},{"style":79},[1608],{"type":38,"value":1546},{"type":33,"tag":72,"props":1610,"children":1611},{"style":85},[1612],{"type":38,"value":107},{"type":33,"tag":72,"props":1614,"children":1615},{"style":110},[1616],{"type":38,"value":1617},"\"\u003C= 1\"\n",{"type":33,"tag":34,"props":1619,"children":1620},{},[1621,1623,1629],{"type":38,"value":1622},"Команда ",{"type":33,"tag":53,"props":1624,"children":1626},{"className":1625},[],[1627],{"type":38,"value":1628},"dbt test",{"type":38,"value":1630}," запускает эти правила. Если conversion rate > 1 (в SQL ошибка), build падает и в Slack уходит alert. Вместо ручной QA — автоматизированная проверка качества данных. На этом основании строится весь остальной data stack.",{"type":33,"tag":41,"props":1632,"children":1634},{"id":1633},"semantic-layer-определите-метрику-а-не-запрос",[1635],{"type":38,"value":1636},"Semantic layer: определите метрику, а не запрос",{"type":33,"tag":34,"props":1638,"children":1639},{},[1640,1642,1647],{"type":38,"value":1641},"С dbt v1.6+ semantic layer вышел из beta. Теперь метрика определяется не в SQL, а в ",{"type":33,"tag":53,"props":1643,"children":1645},{"className":1644},[],[1646],{"type":38,"value":58},{"type":38,"value":1648}," файле:",{"type":33,"tag":62,"props":1650,"children":1652},{"className":64,"code":1651,"language":66,"meta":16,"style":16},"# models\u002Fsemantic\u002Fmetrics.yml\nmetrics:\n  - name: total_revenue\n    label: Total Revenue\n    model: ref('mrt_session_metrics')\n    type: sum\n    sql: total_revenue\n    timestamp: session_date\n    time_grains: [day, week, month]\n\n  - name: roas\n    label: Return on Ad Spend\n    type: ratio\n    numerator: total_revenue\n    denominator: total_ad_spend\n",[1653],{"type":33,"tag":53,"props":1654,"children":1655},{"__ignoreMap":16},[1656,1664,1676,1696,1713,1730,1747,1763,1779,1820,1827,1847,1863,1879,1895],{"type":33,"tag":72,"props":1657,"children":1658},{"class":74,"line":75},[1659],{"type":33,"tag":72,"props":1660,"children":1661},{"style":339},[1662],{"type":38,"value":1663},"# models\u002Fsemantic\u002Fmetrics.yml\n",{"type":33,"tag":72,"props":1665,"children":1666},{"class":74,"line":91},[1667,1672],{"type":33,"tag":72,"props":1668,"children":1669},{"style":79},[1670],{"type":38,"value":1671},"metrics",{"type":33,"tag":72,"props":1673,"children":1674},{"style":85},[1675],{"type":38,"value":88},{"type":33,"tag":72,"props":1677,"children":1678},{"class":74,"line":116},[1679,1683,1687,1691],{"type":33,"tag":72,"props":1680,"children":1681},{"style":85},[1682],{"type":38,"value":97},{"type":33,"tag":72,"props":1684,"children":1685},{"style":79},[1686],{"type":38,"value":102},{"type":33,"tag":72,"props":1688,"children":1689},{"style":85},[1690],{"type":38,"value":107},{"type":33,"tag":72,"props":1692,"children":1693},{"style":110},[1694],{"type":38,"value":1695},"total_revenue\n",{"type":33,"tag":72,"props":1697,"children":1698},{"class":74,"line":134},[1699,1704,1708],{"type":33,"tag":72,"props":1700,"children":1701},{"style":79},[1702],{"type":38,"value":1703},"    label",{"type":33,"tag":72,"props":1705,"children":1706},{"style":85},[1707],{"type":38,"value":107},{"type":33,"tag":72,"props":1709,"children":1710},{"style":110},[1711],{"type":38,"value":1712},"Total Revenue\n",{"type":33,"tag":72,"props":1714,"children":1715},{"class":74,"line":152},[1716,1721,1725],{"type":33,"tag":72,"props":1717,"children":1718},{"style":79},[1719],{"type":38,"value":1720},"    model",{"type":33,"tag":72,"props":1722,"children":1723},{"style":85},[1724],{"type":38,"value":107},{"type":33,"tag":72,"props":1726,"children":1727},{"style":110},[1728],{"type":38,"value":1729},"ref('mrt_session_metrics')\n",{"type":33,"tag":72,"props":1731,"children":1732},{"class":74,"line":165},[1733,1738,1742],{"type":33,"tag":72,"props":1734,"children":1735},{"style":79},[1736],{"type":38,"value":1737},"    type",{"type":33,"tag":72,"props":1739,"children":1740},{"style":85},[1741],{"type":38,"value":107},{"type":33,"tag":72,"props":1743,"children":1744},{"style":110},[1745],{"type":38,"value":1746},"sum\n",{"type":33,"tag":72,"props":1748,"children":1749},{"class":74,"line":187},[1750,1755,1759],{"type":33,"tag":72,"props":1751,"children":1752},{"style":79},[1753],{"type":38,"value":1754},"    sql",{"type":33,"tag":72,"props":1756,"children":1757},{"style":85},[1758],{"type":38,"value":107},{"type":33,"tag":72,"props":1760,"children":1761},{"style":110},[1762],{"type":38,"value":1695},{"type":33,"tag":72,"props":1764,"children":1765},{"class":74,"line":204},[1766,1771,1775],{"type":33,"tag":72,"props":1767,"children":1768},{"style":79},[1769],{"type":38,"value":1770},"    timestamp",{"type":33,"tag":72,"props":1772,"children":1773},{"style":85},[1774],{"type":38,"value":107},{"type":33,"tag":72,"props":1776,"children":1777},{"style":110},[1778],{"type":38,"value":1455},{"type":33,"tag":72,"props":1780,"children":1781},{"class":74,"line":27},[1782,1787,1792,1797,1801,1806,1810,1815],{"type":33,"tag":72,"props":1783,"children":1784},{"style":79},[1785],{"type":38,"value":1786},"    time_grains",{"type":33,"tag":72,"props":1788,"children":1789},{"style":85},[1790],{"type":38,"value":1791},": [",{"type":33,"tag":72,"props":1793,"children":1794},{"style":110},[1795],{"type":38,"value":1796},"day",{"type":33,"tag":72,"props":1798,"children":1799},{"style":85},[1800],{"type":38,"value":265},{"type":33,"tag":72,"props":1802,"children":1803},{"style":110},[1804],{"type":38,"value":1805},"week",{"type":33,"tag":72,"props":1807,"children":1808},{"style":85},[1809],{"type":38,"value":265},{"type":33,"tag":72,"props":1811,"children":1812},{"style":110},[1813],{"type":38,"value":1814},"month",{"type":33,"tag":72,"props":1816,"children":1817},{"style":85},[1818],{"type":38,"value":1819},"]\n",{"type":33,"tag":72,"props":1821,"children":1822},{"class":74,"line":234},[1823],{"type":33,"tag":72,"props":1824,"children":1825},{"emptyLinePlaceholder":422},[1826],{"type":38,"value":425},{"type":33,"tag":72,"props":1828,"children":1829},{"class":74,"line":476},[1830,1834,1838,1842],{"type":33,"tag":72,"props":1831,"children":1832},{"style":85},[1833],{"type":38,"value":97},{"type":33,"tag":72,"props":1835,"children":1836},{"style":79},[1837],{"type":38,"value":102},{"type":33,"tag":72,"props":1839,"children":1840},{"style":85},[1841],{"type":38,"value":107},{"type":33,"tag":72,"props":1843,"children":1844},{"style":110},[1845],{"type":38,"value":1846},"roas\n",{"type":33,"tag":72,"props":1848,"children":1849},{"class":74,"line":548},[1850,1854,1858],{"type":33,"tag":72,"props":1851,"children":1852},{"style":79},[1853],{"type":38,"value":1703},{"type":33,"tag":72,"props":1855,"children":1856},{"style":85},[1857],{"type":38,"value":107},{"type":33,"tag":72,"props":1859,"children":1860},{"style":110},[1861],{"type":38,"value":1862},"Return on Ad Spend\n",{"type":33,"tag":72,"props":1864,"children":1865},{"class":74,"line":611},[1866,1870,1874],{"type":33,"tag":72,"props":1867,"children":1868},{"style":79},[1869],{"type":38,"value":1737},{"type":33,"tag":72,"props":1871,"children":1872},{"style":85},[1873],{"type":38,"value":107},{"type":33,"tag":72,"props":1875,"children":1876},{"style":110},[1877],{"type":38,"value":1878},"ratio\n",{"type":33,"tag":72,"props":1880,"children":1881},{"class":74,"line":625},[1882,1887,1891],{"type":33,"tag":72,"props":1883,"children":1884},{"style":79},[1885],{"type":38,"value":1886},"    numerator",{"type":33,"tag":72,"props":1888,"children":1889},{"style":85},[1890],{"type":38,"value":107},{"type":33,"tag":72,"props":1892,"children":1893},{"style":110},[1894],{"type":38,"value":1695},{"type":33,"tag":72,"props":1896,"children":1897},{"class":74,"line":634},[1898,1903,1907],{"type":33,"tag":72,"props":1899,"children":1900},{"style":79},[1901],{"type":38,"value":1902},"    denominator",{"type":33,"tag":72,"props":1904,"children":1905},{"style":85},[1906],{"type":38,"value":107},{"type":33,"tag":72,"props":1908,"children":1909},{"style":110},[1910],{"type":38,"value":1911},"total_ad_spend\n",{"type":33,"tag":34,"props":1913,"children":1914},{},[1915],{"type":38,"value":1916},"Это определение используется в трёх местах: (1) Looker Studio, (2) Slack bot через dbt Cloud discovery API для запроса метрик, (3) Airflow DAG в качестве входа для downstream ML pipeline.",{"type":33,"tag":34,"props":1918,"children":1919},{},[1920,1925],{"type":33,"tag":302,"props":1921,"children":1922},{},[1923],{"type":38,"value":1924},"Преимущество:",{"type":38,"value":1926}," метрика потребляется без написания SQL. Marketing analyst просто пишет \"Show me ROAS by campaign, last 7 days\", и semantic layer автоматически компилирует запрос. SQL logic находится в модели, определение метрики — в semantic layer. Они независимы, изменения изолированы.",{"type":33,"tag":34,"props":1928,"children":1929},{},[1930,1935],{"type":33,"tag":302,"props":1931,"children":1932},{},[1933],{"type":38,"value":1934},"Внимание:",{"type":38,"value":1936}," semantic layer всё ещё молод — не все BI инструменты имеют native интеграцию. В production stack Roibase используется гибридный подход: критические метрики в semantic layer, custom анализ через SQL exposure'ы.",{"type":33,"tag":1366,"props":1938,"children":1940},{"id":1939},"exposures-документируйте-downstream-зависимости",[1941],{"type":38,"value":1942},"Exposures: документируйте downstream зависимости",{"type":33,"tag":34,"props":1944,"children":1945},{},[1946],{"type":38,"value":1947},"Exposures показывают, где за пределами dbt используется модель:",{"type":33,"tag":62,"props":1949,"children":1951},{"className":64,"code":1950,"language":66,"meta":16,"style":16},"# models\u002Fexposures.yml\nexposures:\n  - name: looker_studio_performance_dashboard\n    type: dashboard\n    url: https:\u002F\u002Flookerstudio.google.com\u002F...\n    depends_on:\n      - ref('mrt_session_metrics')\n      - ref('mrt_campaign_performance')\n    owner:\n      name: Marketing Analytics Team\n      email: analytics@roibase.com.tr\n",[1952],{"type":33,"tag":53,"props":1953,"children":1954},{"__ignoreMap":16},[1955,1963,1975,1995,2011,2028,2040,2051,2063,2075,2092],{"type":33,"tag":72,"props":1956,"children":1957},{"class":74,"line":75},[1958],{"type":33,"tag":72,"props":1959,"children":1960},{"style":339},[1961],{"type":38,"value":1962},"# models\u002Fexposures.yml\n",{"type":33,"tag":72,"props":1964,"children":1965},{"class":74,"line":91},[1966,1971],{"type":33,"tag":72,"props":1967,"children":1968},{"style":79},[1969],{"type":38,"value":1970},"exposures",{"type":33,"tag":72,"props":1972,"children":1973},{"style":85},[1974],{"type":38,"value":88},{"type":33,"tag":72,"props":1976,"children":1977},{"class":74,"line":116},[1978,1982,1986,1990],{"type":33,"tag":72,"props":1979,"children":1980},{"style":85},[1981],{"type":38,"value":97},{"type":33,"tag":72,"props":1983,"children":1984},{"style":79},[1985],{"type":38,"value":102},{"type":33,"tag":72,"props":1987,"children":1988},{"style":85},[1989],{"type":38,"value":107},{"type":33,"tag":72,"props":1991,"children":1992},{"style":110},[1993],{"type":38,"value":1994},"looker_studio_performance_dashboard\n",{"type":33,"tag":72,"props":1996,"children":1997},{"class":74,"line":134},[1998,2002,2006],{"type":33,"tag":72,"props":1999,"children":2000},{"style":79},[2001],{"type":38,"value":1737},{"type":33,"tag":72,"props":2003,"children":2004},{"style":85},[2005],{"type":38,"value":107},{"type":33,"tag":72,"props":2007,"children":2008},{"style":110},[2009],{"type":38,"value":2010},"dashboard\n",{"type":33,"tag":72,"props":2012,"children":2013},{"class":74,"line":152},[2014,2019,2023],{"type":33,"tag":72,"props":2015,"children":2016},{"style":79},[2017],{"type":38,"value":2018},"    url",{"type":33,"tag":72,"props":2020,"children":2021},{"style":85},[2022],{"type":38,"value":107},{"type":33,"tag":72,"props":2024,"children":2025},{"style":110},[2026],{"type":38,"value":2027},"https:\u002F\u002Flookerstudio.google.com\u002F...\n",{"type":33,"tag":72,"props":2029,"children":2030},{"class":74,"line":165},[2031,2036],{"type":33,"tag":72,"props":2032,"children":2033},{"style":79},[2034],{"type":38,"value":2035},"    depends_on",{"type":33,"tag":72,"props":2037,"children":2038},{"style":85},[2039],{"type":38,"value":88},{"type":33,"tag":72,"props":2041,"children":2042},{"class":74,"line":187},[2043,2047],{"type":33,"tag":72,"props":2044,"children":2045},{"style":85},[2046],{"type":38,"value":171},{"type":33,"tag":72,"props":2048,"children":2049},{"style":110},[2050],{"type":38,"value":1729},{"type":33,"tag":72,"props":2052,"children":2053},{"class":74,"line":204},[2054,2058],{"type":33,"tag":72,"props":2055,"children":2056},{"style":85},[2057],{"type":38,"value":171},{"type":33,"tag":72,"props":2059,"children":2060},{"style":110},[2061],{"type":38,"value":2062},"ref('mrt_campaign_performance')\n",{"type":33,"tag":72,"props":2064,"children":2065},{"class":74,"line":27},[2066,2071],{"type":33,"tag":72,"props":2067,"children":2068},{"style":79},[2069],{"type":38,"value":2070},"    owner",{"type":33,"tag":72,"props":2072,"children":2073},{"style":85},[2074],{"type":38,"value":88},{"type":33,"tag":72,"props":2076,"children":2077},{"class":74,"line":234},[2078,2083,2087],{"type":33,"tag":72,"props":2079,"children":2080},{"style":79},[2081],{"type":38,"value":2082},"      name",{"type":33,"tag":72,"props":2084,"children":2085},{"style":85},[2086],{"type":38,"value":107},{"type":33,"tag":72,"props":2088,"children":2089},{"style":110},[2090],{"type":38,"value":2091},"Marketing Analytics Team\n",{"type":33,"tag":72,"props":2093,"children":2094},{"class":74,"line":476},[2095,2100,2104],{"type":33,"tag":72,"props":2096,"children":2097},{"style":79},[2098],{"type":38,"value":2099},"      email",{"type":33,"tag":72,"props":2101,"children":2102},{"style":85},[2103],{"type":38,"value":107},{"type":33,"tag":72,"props":2105,"children":2106},{"style":110},[2107],{"type":38,"value":2108},"analytics@roibase.com.tr\n",{"type":33,"tag":34,"props":2110,"children":2111},{},[2112,2114,2120],{"type":38,"value":2113},"Это определение визуализируется в dbt docs — видно, какой dashboard зависит от какой модели, на кого нужно подписать изменения schema. В production, когда нужно сделать breaking change, команда ",{"type":33,"tag":53,"props":2115,"children":2117},{"className":2116},[],[2118],{"type":38,"value":2119},"dbt run --select +mrt_session_metrics+",{"type":38,"value":2121}," показывает все downstream зависимости.",{"type":33,"tag":34,"props":2123,"children":2124},{},[2125,2130,2132,2138,2140,2146],{"type":33,"tag":302,"props":2126,"children":2127},{},[2128],{"type":38,"value":2129},"Реальный сценарий:",{"type":38,"value":2131}," в GA4 key ",{"type":33,"tag":53,"props":2133,"children":2135},{"className":2134},[],[2136],{"type":38,"value":2137},"page_location",{"type":38,"value":2139}," в event_params переименован на ",{"type":33,"tag":53,"props":2141,"children":2143},{"className":2142},[],[2144],{"type":38,"value":2145},"page_url",{"type":38,"value":2147},". Благодаря exposure'ам мы нашли 3 затронутых dashboard'а и 1 Airflow DAG, миграция заняла 2 часа. Без exposure'ов dashboard'ы молча сломались бы, об ошибке узнали бы от users.",{"type":33,"tag":41,"props":2149,"children":2151},{"id":2150},"incremental-models-не-делайте-полный-rebuild-2tb-данных-ежедневно",[2152],{"type":38,"value":2153},"Incremental models: не делайте полный rebuild 2TB данных ежедневно",{"type":33,"tag":34,"props":2155,"children":2156},{},[2157,2159,2165],{"type":38,"value":2158},"В маркетинговых данных daily partition'ы достигают терабайтов. Каждый ",{"type":33,"tag":53,"props":2160,"children":2162},{"className":2161},[],[2163],{"type":38,"value":2164},"dbt run",{"type":38,"value":2166}," с полным refresh неприемлем — стоимость BigQuery и время выполнения будут недопустимы. Используйте incremental модель:",{"type":33,"tag":62,"props":2168,"children":2170},{"className":327,"code":2169,"language":329,"meta":16,"style":16},"-- models\u002Fmarts\u002Fmrt_user_journey.sql\n{{\n  config(\n    materialized='incremental',\n    partition_by={'field': 'event_date', 'data_type': 'date'},\n    cluster_by=['user_pseudo_id', 'traffic_source'],\n    incremental_strategy='insert_overwrite'\n  )\n}}\n\nselect\n  event_date,\n  user_pseudo_id,\n  traffic_source,\n  -- ...\nfrom {{ ref('stg_ga4_events') }}\n\n{% if is_incremental() %}\n  where event_date >= date_sub(current_date(), interval 3 day)\n{% endif %}\n",[2171],{"type":33,"tag":53,"props":2172,"children":2173},{"__ignoreMap":16},[2174,2182,2190,2198,2220,2274,2291,2308,2316,2324,2331,2338,2346,2354,2361,2369,2389,2396,2414,2450],{"type":33,"tag":72,"props":2175,"children":2176},{"class":74,"line":75},[2177],{"type":33,"tag":72,"props":2178,"children":2179},{"style":339},[2180],{"type":38,"value":2181},"-- models\u002Fmarts\u002Fmrt_user_journey.sql\n",{"type":33,"tag":72,"props":2183,"children":2184},{"class":74,"line":91},[2185],{"type":33,"tag":72,"props":2186,"children":2187},{"style":85},[2188],{"type":38,"value":2189},"{{\n",{"type":33,"tag":72,"props":2191,"children":2192},{"class":74,"line":116},[2193],{"type":33,"tag":72,"props":2194,"children":2195},{"style":85},[2196],{"type":38,"value":2197},"  config(\n",{"type":33,"tag":72,"props":2199,"children":2200},{"class":74,"line":134},[2201,2206,2211,2216],{"type":33,"tag":72,"props":2202,"children":2203},{"style":85},[2204],{"type":38,"value":2205},"    materialized",{"type":33,"tag":72,"props":2207,"children":2208},{"style":348},[2209],{"type":38,"value":2210},"=",{"type":33,"tag":72,"props":2212,"children":2213},{"style":110},[2214],{"type":38,"value":2215},"'incremental'",{"type":33,"tag":72,"props":2217,"children":2218},{"style":85},[2219],{"type":38,"value":873},{"type":33,"tag":72,"props":2221,"children":2222},{"class":74,"line":152},[2223,2228,2232,2237,2242,2246,2251,2255,2260,2264,2269],{"type":33,"tag":72,"props":2224,"children":2225},{"style":85},[2226],{"type":38,"value":2227},"    partition_by",{"type":33,"tag":72,"props":2229,"children":2230},{"style":348},[2231],{"type":38,"value":2210},{"type":33,"tag":72,"props":2233,"children":2234},{"style":85},[2235],{"type":38,"value":2236},"{",{"type":33,"tag":72,"props":2238,"children":2239},{"style":110},[2240],{"type":38,"value":2241},"'field'",{"type":33,"tag":72,"props":2243,"children":2244},{"style":85},[2245],{"type":38,"value":107},{"type":33,"tag":72,"props":2247,"children":2248},{"style":110},[2249],{"type":38,"value":2250},"'event_date'",{"type":33,"tag":72,"props":2252,"children":2253},{"style":85},[2254],{"type":38,"value":265},{"type":33,"tag":72,"props":2256,"children":2257},{"style":110},[2258],{"type":38,"value":2259},"'data_type'",{"type":33,"tag":72,"props":2261,"children":2262},{"style":85},[2263],{"type":38,"value":107},{"type":33,"tag":72,"props":2265,"children":2266},{"style":110},[2267],{"type":38,"value":2268},"'date'",{"type":33,"tag":72,"props":2270,"children":2271},{"style":85},[2272],{"type":38,"value":2273},"},\n",{"type":33,"tag":72,"props":2275,"children":2276},{"class":74,"line":165},[2277,2282,2286],{"type":33,"tag":72,"props":2278,"children":2279},{"style":85},[2280],{"type":38,"value":2281},"    cluster_by",{"type":33,"tag":72,"props":2283,"children":2284},{"style":348},[2285],{"type":38,"value":2210},{"type":33,"tag":72,"props":2287,"children":2288},{"style":85},[2289],{"type":38,"value":2290},"['user_pseudo_id', 'traffic_source'],\n",{"type":33,"tag":72,"props":2292,"children":2293},{"class":74,"line":187},[2294,2299,2303],{"type":33,"tag":72,"props":2295,"children":2296},{"style":85},[2297],{"type":38,"value":2298},"    incremental_strategy",{"type":33,"tag":72,"props":2300,"children":2301},{"style":348},[2302],{"type":38,"value":2210},{"type":33,"tag":72,"props":2304,"children":2305},{"style":110},[2306],{"type":38,"value":2307},"'insert_overwrite'\n",{"type":33,"tag":72,"props":2309,"children":2310},{"class":74,"line":204},[2311],{"type":33,"tag":72,"props":2312,"children":2313},{"style":85},[2314],{"type":38,"value":2315},"  )\n",{"type":33,"tag":72,"props":2317,"children":2318},{"class":74,"line":27},[2319],{"type":33,"tag":72,"props":2320,"children":2321},{"style":85},[2322],{"type":38,"value":2323},"}}\n",{"type":33,"tag":72,"props":2325,"children":2326},{"class":74,"line":234},[2327],{"type":33,"tag":72,"props":2328,"children":2329},{"emptyLinePlaceholder":422},[2330],{"type":38,"value":425},{"type":33,"tag":72,"props":2332,"children":2333},{"class":74,"line":476},[2334],{"type":33,"tag":72,"props":2335,"children":2336},{"style":348},[2337],{"type":38,"value":1109},{"type":33,"tag":72,"props":2339,"children":2340},{"class":74,"line":548},[2341],{"type":33,"tag":72,"props":2342,"children":2343},{"style":85},[2344],{"type":38,"value":2345},"  event_date,\n",{"type":33,"tag":72,"props":2347,"children":2348},{"class":74,"line":611},[2349],{"type":33,"tag":72,"props":2350,"children":2351},{"style":85},[2352],{"type":38,"value":2353},"  user_pseudo_id,\n",{"type":33,"tag":72,"props":2355,"children":2356},{"class":74,"line":625},[2357],{"type":33,"tag":72,"props":2358,"children":2359},{"style":85},[2360],{"type":38,"value":1127},{"type":33,"tag":72,"props":2362,"children":2363},{"class":74,"line":634},[2364],{"type":33,"tag":72,"props":2365,"children":2366},{"style":339},[2367],{"type":38,"value":2368},"  -- ...\n",{"type":33,"tag":72,"props":2370,"children":2371},{"class":74,"line":642},[2372,2376,2380,2385],{"type":33,"tag":72,"props":2373,"children":2374},{"style":348},[2375],{"type":38,"value":1295},{"type":33,"tag":72,"props":2377,"children":2378},{"style":85},[2379],{"type":38,"value":747},{"type":33,"tag":72,"props":2381,"children":2382},{"style":110},[2383],{"type":38,"value":2384},"'stg_ga4_events'",{"type":33,"tag":72,"props":2386,"children":2387},{"style":85},[2388],{"type":38,"value":408},{"type":33,"tag":72,"props":2390,"children":2391},{"class":74,"line":956},[2392],{"type":33,"tag":72,"props":2393,"children":2394},{"emptyLinePlaceholder":422},[2395],{"type":38,"value":425},{"type":33,"tag":72,"props":2397,"children":2398},{"class":74,"line":978},[2399,2404,2409],{"type":33,"tag":72,"props":2400,"children":2401},{"style":85},[2402],{"type":38,"value":2403},"{% ",{"type":33,"tag":72,"props":2405,"children":2406},{"style":348},[2407],{"type":38,"value":2408},"if",{"type":33,"tag":72,"props":2410,"children":2411},{"style":85},[2412],{"type":38,"value":2413}," is_incremental() %}\n",{"type":33,"tag":72,"props":2415,"children":2416},{"class":74,"line":999},[2417,2422,2427,2432,2437,2441,2446],{"type":33,"tag":72,"props":2418,"children":2419},{"style":348},[2420],{"type":38,"value":2421},"  where",{"type":33,"tag":72,"props":2423,"children":2424},{"style":85},[2425],{"type":38,"value":2426}," event_date ",{"type":33,"tag":72,"props":2428,"children":2429},{"style":348},[2430],{"type":38,"value":2431},">=",{"type":33,"tag":72,"props":2433,"children":2434},{"style":85},[2435],{"type":38,"value":2436}," date_sub(current_date(), interval ",{"type":33,"tag":72,"props":2438,"children":2439},{"style":257},[2440],{"type":38,"value":1332},{"type":33,"tag":72,"props":2442,"children":2443},{"style":348},[2444],{"type":38,"value":2445}," day",{"type":33,"tag":72,"props":2447,"children":2448},{"style":85},[2449],{"type":38,"value":631},{"type":33,"tag":72,"props":2451,"children":2452},{"class":74,"line":1016},[2453],{"type":33,"tag":72,"props":2454,"children":2455},{"style":85},[2456],{"type":38,"value":2457},"{% endif %}\n",{"type":33,"tag":34,"props":2459,"children":2460},{},[2461,2463,2469,2471,2477],{"type":38,"value":2462},"Эта конфигурация делает три вещи: (1) создаёт partition в BigQuery — добавляет новые дни, не трогая старые, (2) ",{"type":33,"tag":53,"props":2464,"children":2466},{"className":2465},[],[2467],{"type":38,"value":2468},"cluster_by",{"type":38,"value":2470}," улучшает производительность запросов, (3) стратегия ",{"type":33,"tag":53,"props":2472,"children":2474},{"className":2473},[],[2475],{"type":38,"value":2476},"insert_overwrite",{"type":38,"value":2478}," удаляет последние 3 дня и пересчитывает (для late arriving data).",{"type":33,"tag":34,"props":2480,"children":2481},{},[2482,2487],{"type":33,"tag":302,"props":2483,"children":2484},{},[2485],{"type":38,"value":2486},"Разница в стоимости:",{"type":38,"value":2488}," 365 дней данных, full refresh = 2.5 TB scan ($12.5), incremental = 3 GB scan ($0.015). Для ежедневного pipeline'а годовая разница ~$4500 vs ~$5. Поэтому incremental модель — основа production stack'а.",{"type":33,"tag":41,"props":2490,"children":2492},{"id":2491},"связать-data-stack-с-механизмом-принятия-решений",[2493],{"type":38,"value":2494},"Связать data stack с механизмом принятия решений",{"type":33,"tag":34,"props":2496,"children":2497},{},[2498],{"type":38,"value":2499},"dbt + BigQuery создают инфраструктуру, но реальная ценность проявляется в маркетинговых решениях. Типичный сценарий — метрики из semantic layer в Slack bot:",{"type":33,"tag":2501,"props":2502,"children":2503},"ol",{},[2504,2516,2521,2534],{"type":33,"tag":2505,"props":2506,"children":2507},"li",{},[2508,2510],{"type":38,"value":2509},"Marketing manager пишет в Slack ",{"type":33,"tag":53,"props":2511,"children":2513},{"className":2512},[],[2514],{"type":38,"value":2515},"\u002Fmetric roas last_30_days campaign=brand",{"type":33,"tag":2505,"props":2517,"children":2518},{},[2519],{"type":38,"value":2520},"Slack app вызывает dbt Cloud semantic layer API",{"type":33,"tag":2505,"props":2522,"children":2523},{},[2524,2526,2532],{"type":38,"value":2525},"API запрашивает таблицу ",{"type":33,"tag":53,"props":2527,"children":2529},{"className":2528},[],[2530],{"type":38,"value":2531},"mrt_session_metrics",{"type":38,"value":2533},", вычисляет ROAS",{"type":33,"tag":2505,"props":2535,"children":2536},{},[2537],{"type":38,"value":2538},"Результат возвращается в Slack: \"Brand campaign ROAS: 4.2x\"",{"type":33,"tag":34,"props":2540,"children":2541},{},[2542],{"type":38,"value":2543},"Для этого потока нужны semantic layer + custom Python middleware. В production stack Roibase Airflow DAG'ей делает ежедневный snapshot semantic layer, Looker Studio и internal app'ы используют этот snapshot — без проблем с API rate limit.",{"type":33,"tag":34,"props":2545,"children":2546},{},[2547,2552,2554,2563],{"type":33,"tag":302,"props":2548,"children":2549},{},[2550],{"type":38,"value":2551},"Альтернативный подход:",{"type":38,"value":2553}," в сервисе ",{"type":33,"tag":2555,"props":2556,"children":2560},"a",{"href":2557,"rel":2558},"https:\u002F\u002Fwww.roibase.com.tr\u002Fru\u002Ffirstparty",[2559],"nofollow",[2561],{"type":38,"value":2562},"First-Party Data & Ölçüm Architecture",{"type":38,"value":2564}," используется гибридный stack — dbt semantic layer + Cube.js. Cube.js добавляет слой кеширования, улучшает BI производительность. Выбор зависит от объёма данных и паттерна запросов.",{"type":33,"tag":41,"props":2566,"children":2568},{"id":2567},"production-checklist-перед-deployment-dbt-stackа",[2569],{"type":38,"value":2570},"Production checklist: перед deployment dbt stack'а",{"type":33,"tag":34,"props":2572,"children":2573},{},[2574],{"type":38,"value":2575},"dbt работает локально — перед production нужны эти проверки:",{"type":33,"tag":2577,"props":2578,"children":2579},"ul",{},[2580,2598,2622,2632,2650,2660],{"type":33,"tag":2505,"props":2581,"children":2582},{},[2583,2588,2590,2596],{"type":33,"tag":302,"props":2584,"children":2585},{},[2586],{"type":38,"value":2587},"CI\u002FCD:",{"type":38,"value":2589}," dbt Cloud или GitHub Actions должны запускать ",{"type":33,"tag":53,"props":2591,"children":2593},{"className":2592},[],[2594],{"type":38,"value":2595},"dbt build --select state:modified+",{"type":38,"value":2597}," на каждый commit",{"type":33,"tag":2505,"props":2599,"children":2600},{},[2601,2606,2608,2614,2616],{"type":33,"tag":302,"props":2602,"children":2603},{},[2604],{"type":38,"value":2605},"Freshness monitoring:",{"type":38,"value":2607}," для критичных source'ов определите ",{"type":33,"tag":53,"props":2609,"children":2611},{"className":2610},[],[2612],{"type":38,"value":2613},"warn_after",{"type":38,"value":2615}," и ",{"type":33,"tag":53,"props":2617,"children":2619},{"className":2618},[],[2620],{"type":38,"value":2621},"error_after",{"type":33,"tag":2505,"props":2623,"children":2624},{},[2625,2630],{"type":33,"tag":302,"props":2626,"children":2627},{},[2628],{"type":38,"value":2629},"Alerting:",{"type":38,"value":2631}," webhook dbt Cloud → Slack интеграция; при fail build'а команда узнает в течение 5 минут",{"type":33,"tag":2505,"props":2633,"children":2634},{},[2635,2640,2642,2648],{"type":33,"tag":302,"props":2636,"children":2637},{},[2638],{"type":38,"value":2639},"Documentation:",{"type":38,"value":2641}," ",{"type":33,"tag":53,"props":2643,"children":2645},{"className":2644},[],[2646],{"type":38,"value":2647},"dbt docs generate",{"type":38,"value":2649}," запускается автоматически, artifact'ы push'ятся в S3\u002FGCS",{"type":33,"tag":2505,"props":2651,"children":2652},{},[2653,2658],{"type":33,"tag":302,"props":2654,"children":2655},{},[2656],{"type":38,"value":2657},"Cost monitoring:",{"type":38,"value":2659}," BigQuery slot reservation или on-demand alert — установите threshold $500\u002Fдень на неожиданные spike'ы",{"type":33,"tag":2505,"props":2661,"children":2662},{},[2663,2668],{"type":33,"tag":302,"props":2664,"children":2665},{},[2666],{"type":38,"value":2667},"Backup strategy:",{"type":38,"value":2669}," snapshot таблица критичных моделей — если обновление сломало данные, сможете откатиться",{"type":33,"tag":34,"props":2671,"children":2672},{},[2673,2678,2680,2685],{"type":33,"tag":302,"props":2674,"children":2675},{},[2676],{"type":38,"value":2677},"Самое критичное правило:",{"type":38,"value":2679}," в production нет manual ",{"type":33,"tag":53,"props":2681,"children":2683},{"className":2682},[],[2684],{"type":38,"value":2164},{"type":38,"value":2686},". Всё выполняется только через scheduler (dbt Cloud, Airflow, Prefect). Manual run нарушает data lineage, при ошибке невозможно найти root cause.",{"type":33,"tag":34,"props":2688,"children":2689},{},[2690],{"type":38,"value":2691},"dbt + BigQuery — позвоночник современного маркетингового data stack'а. Source mapping связывает raw данные с контрактом, modeling layer централизует определение метрики, semantic layer позволяет потреблять метрики без SQL. В production incremental модели и test coverage делают pipeline'ы устойчивыми. Следующий слой — связать данные с real-time activation'ом: CDP, audience sync, incrementality measurement. Но это — отдельная история data stack'а.",{"type":33,"tag":2693,"props":2694,"children":2695},"style",{},[2696],{"type":38,"value":2697},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":16,"searchDepth":116,"depth":116,"links":2699},[2700,2701,2704,2707,2708,2709],{"id":43,"depth":91,"text":46},{"id":676,"depth":91,"text":679,"children":2702},[2703],{"id":1368,"depth":116,"text":1371},{"id":1633,"depth":91,"text":1636,"children":2705},[2706],{"id":1939,"depth":116,"text":1942},{"id":2150,"depth":91,"text":2153},{"id":2491,"depth":91,"text":2494},{"id":2567,"depth":91,"text":2570},"markdown","content:ru:data:dbt-bigquery-modern-pazarlama-veri-yigini.md","content","ru\u002Fdata\u002Fdbt-bigquery-modern-pazarlama-veri-yigini.md","ru\u002Fdata\u002Fdbt-bigquery-modern-pazarlama-veri-yigini","md",1785967485622]