[{"data":1,"prerenderedAt":2321},["ShallowReactive",2],{"article-alternates":3,"article-\u002Fru\u002Fdata\u002Farkhitektura-tablitsy-kohorty-masshtabirovanie-analiza-drzhaniia-v-proizvodstve":13},{"i18nKey":4,"paths":5},"data-007-2026-08",{"de":6,"en":7,"es":8,"fr":9,"it":10,"ru":11,"tr":12},"\u002Fde\u002Fdata\u002Fcohort-table-architecture-scaling-retention-analysis-production","\u002Fen\u002Fdata\u002Fcohort-table-architecture-scaling-retention-analysis-production","\u002Fes\u002Fdata\u002Farquitectura-de-tabla-cohort-escalando-analisis-de-retencion-en-produccion","\u002Ffr\u002Fdata\u002Farchitecture-table-cohort-retention-scaling-production","\u002Fit\u002Fdata\u002Farchitettura-tabella-cohort-scalare-retention-analysis-in-produzione","\u002Fru\u002Fdata\u002Farkhitektura-tablitsy-kohorty-masshtabirovanie-analiza-drzhaniia-v-proizvodstve","\u002Ftr\u002Fdata\u002Fcohort-tablo-mimarisi-retention-analizinin-productionda-olceklenmesi",{"_path":11,"_dir":14,"_draft":15,"_partial":15,"_locale":16,"title":17,"description":18,"publishedAt":19,"modifiedAt":19,"category":14,"i18nKey":4,"tags":20,"readingTime":26,"author":27,"body":28,"_type":2315,"_id":2316,"_source":2317,"_file":2318,"_stem":2319,"_extension":2320},"data",false,"","Архитектура таблицы когорты: масштабирование анализа удержания в production","Materialized views, стратегия partitioning и оптимизация стоимости запросов для масштабирования анализа когорт удержания в production, снижения расходов на 90% и ускорения принятия решений.","2026-08-14",[21,22,23,24,25],"cohort-analysis","bigquery","materialized-views","data-engineering","retention",8,"Roibase",{"type":29,"children":30,"toc":2308},"root",[31,39,46,60,65,70,76,81,94,346,359,372,554,559,1007,1012,1018,1037,1055,1068,1081,1086,1092,1097,1102,1484,1497,1509,1821,1826,1847,1853,1872,1877,2292,2297,2302],{"type":32,"tag":33,"props":34,"children":35},"element","p",{},[36],{"type":37,"value":38},"text","Анализ удержания находится в центре механизма принятия решений в e-commerce и SaaS-моделях. Однако классические запросы когорты при запуске в production полностью сканируют таблицы событий объёмом в терабайты, выполняются минутами и доводят стоимость запросов до сотен долларов в день. Когда когорты вычисляются по требованию, цикл принятия решений замедляется, аналитический отдел тратит время на оптимизацию запросов, дашборды остаются устаревшими. Решение: хранить таблицы когорт как предварительно вычисленный, партиционированный и инкрементально обновляемый data asset. В этой статье показываем, как настроить materialized views, partitioning и incremental build стратегии на BigQuery, снизить стоимость запросов на 90%, ускорить анализ до миллисекунд и привести решения по удержанию к near real-time.",{"type":32,"tag":40,"props":41,"children":43},"h2",{"id":42},"почему-классический-запрос-когорты-не-масштабируется",[44],{"type":37,"value":45},"Почему классический запрос когорты не масштабируется",{"type":32,"tag":33,"props":47,"children":48},{},[49,51,58],{"type":37,"value":50},"Стандартный анализ когорты работает так: сгруппировать пользователей по дате первого события, рассчитать, какой процент вернулся в следующие дни. SQL-запрос делает двойное join таблицы ",{"type":32,"tag":52,"props":53,"children":55},"code",{"className":54},[],[56],{"type":37,"value":57},"events",{"type":37,"value":59}," — один раз для поиска даты когорты, один раз для подсчёта поведения удержания. На таблице событий объёмом 500 миллионов строк BigQuery выполняет этот запрос за 10-15 секунд и генерирует стоимость ~$0.50. Запрос повторяется при каждом обновлении дашборда, каждой итерации аналитика, каждом A\u002FB тестовом отчёте.",{"type":32,"tag":33,"props":61,"children":62},{},[63],{"type":37,"value":64},"Проблема не столько в стоимости, сколько в скорости и гибкости. Когда аналитический отдел хочет изменить определение когорты (например, попробовать \"второе добавление в корзину\" вместо \"первой покупки\"), переписание, тестирование и валидация запроса занимает часы. Дашборды становятся неактуальными. Когда маркетинг спрашивает \"какова была удержанность когорты на прошлой неделе\", свежих данных нет — аналитик запускает запрос вручную. Этот цикл замедляет процесс принятия решений на дни.",{"type":32,"tag":33,"props":66,"children":67},{},[68],{"type":37,"value":69},"Расчёты когорт также требуют слоя агрегирования как data asset. Метрика удержания — это не просто \"количество пользователей\", а \"количество активных пользователей\u002Fразмер когорты\" — соотношение. Это соотношение должно обновляться каждый день, новые дни поведения существующих когорт должны добавляться. Классический запрос не поддерживает эту логику с инкрементом, он пересчитывает всё с нуля.",{"type":32,"tag":40,"props":71,"children":73},{"id":72},"превращение-когорты-в-таблицу-с-помощью-materialized-view",[74],{"type":37,"value":75},"Превращение когорты в таблицу с помощью Materialized View",{"type":32,"tag":33,"props":77,"children":78},{},[79],{"type":37,"value":80},"Первый шаг решения — зафиксировать определение когорты как materialized view. BigQuery физически хранит результат запроса и инкрементально обновляет при изменениях базовой таблицы. Однако для анализа когорты стандартного MV недостаточно, потому что определение когорты и окно удержания — динамические параметры. Поэтому строим гибридную архитектуру: таблица присвоения когорты + таблица агрегирования событий удержания.",{"type":32,"tag":33,"props":82,"children":83},{},[84,86,92],{"type":37,"value":85},"Первая таблица ",{"type":32,"tag":52,"props":87,"children":89},{"className":88},[],[90],{"type":37,"value":91},"cohort_assignments",{"type":37,"value":93}," хранит дату, когда пользователь впервые вошёл в когорту:",{"type":32,"tag":95,"props":96,"children":100},"pre",{"className":97,"code":98,"language":99,"meta":16,"style":16},"language-sql shiki shiki-themes github-dark","CREATE TABLE `project.dataset.cohort_assignments`\nPARTITION BY DATE(cohort_date)\nCLUSTER BY user_id\nAS\nSELECT\n  user_id,\n  MIN(DATE(event_timestamp)) AS cohort_date,\n  COUNTIF(event_name = 'purchase') AS total_purchases\nFROM `project.dataset.events`\nWHERE event_name IN ('first_visit', 'purchase', 'signup')\nGROUP BY user_id;\n","sql",[101],{"type":32,"tag":52,"props":102,"children":103},{"__ignoreMap":16},[104,127,152,171,180,189,198,233,265,279,332],{"type":32,"tag":105,"props":106,"children":109},"span",{"class":107,"line":108},"line",1,[110,116,121],{"type":32,"tag":105,"props":111,"children":113},{"style":112},"--shiki-default:#F97583",[114],{"type":37,"value":115},"CREATE",{"type":32,"tag":105,"props":117,"children":118},{"style":112},[119],{"type":37,"value":120}," TABLE",{"type":32,"tag":105,"props":122,"children":124},{"style":123},"--shiki-default:#9ECBFF",[125],{"type":37,"value":126}," `project.dataset.cohort_assignments`\n",{"type":32,"tag":105,"props":128,"children":130},{"class":107,"line":129},2,[131,136,141,146],{"type":32,"tag":105,"props":132,"children":133},{"style":112},[134],{"type":37,"value":135},"PARTITION",{"type":32,"tag":105,"props":137,"children":138},{"style":112},[139],{"type":37,"value":140}," BY",{"type":32,"tag":105,"props":142,"children":143},{"style":112},[144],{"type":37,"value":145}," DATE",{"type":32,"tag":105,"props":147,"children":149},{"style":148},"--shiki-default:#E1E4E8",[150],{"type":37,"value":151},"(cohort_date)\n",{"type":32,"tag":105,"props":153,"children":155},{"class":107,"line":154},3,[156,161,166],{"type":32,"tag":105,"props":157,"children":158},{"style":148},[159],{"type":37,"value":160},"CLUSTER ",{"type":32,"tag":105,"props":162,"children":163},{"style":112},[164],{"type":37,"value":165},"BY",{"type":32,"tag":105,"props":167,"children":168},{"style":148},[169],{"type":37,"value":170}," user_id\n",{"type":32,"tag":105,"props":172,"children":174},{"class":107,"line":173},4,[175],{"type":32,"tag":105,"props":176,"children":177},{"style":112},[178],{"type":37,"value":179},"AS\n",{"type":32,"tag":105,"props":181,"children":183},{"class":107,"line":182},5,[184],{"type":32,"tag":105,"props":185,"children":186},{"style":112},[187],{"type":37,"value":188},"SELECT\n",{"type":32,"tag":105,"props":190,"children":192},{"class":107,"line":191},6,[193],{"type":32,"tag":105,"props":194,"children":195},{"style":148},[196],{"type":37,"value":197},"  user_id,\n",{"type":32,"tag":105,"props":199,"children":201},{"class":107,"line":200},7,[202,208,213,218,223,228],{"type":32,"tag":105,"props":203,"children":205},{"style":204},"--shiki-default:#79B8FF",[206],{"type":37,"value":207},"  MIN",{"type":32,"tag":105,"props":209,"children":210},{"style":148},[211],{"type":37,"value":212},"(",{"type":32,"tag":105,"props":214,"children":215},{"style":112},[216],{"type":37,"value":217},"DATE",{"type":32,"tag":105,"props":219,"children":220},{"style":148},[221],{"type":37,"value":222},"(event_timestamp)) ",{"type":32,"tag":105,"props":224,"children":225},{"style":112},[226],{"type":37,"value":227},"AS",{"type":32,"tag":105,"props":229,"children":230},{"style":148},[231],{"type":37,"value":232}," cohort_date,\n",{"type":32,"tag":105,"props":234,"children":235},{"class":107,"line":26},[236,241,246,251,256,260],{"type":32,"tag":105,"props":237,"children":238},{"style":148},[239],{"type":37,"value":240},"  COUNTIF(event_name ",{"type":32,"tag":105,"props":242,"children":243},{"style":112},[244],{"type":37,"value":245},"=",{"type":32,"tag":105,"props":247,"children":248},{"style":123},[249],{"type":37,"value":250}," 'purchase'",{"type":32,"tag":105,"props":252,"children":253},{"style":148},[254],{"type":37,"value":255},") ",{"type":32,"tag":105,"props":257,"children":258},{"style":112},[259],{"type":37,"value":227},{"type":32,"tag":105,"props":261,"children":262},{"style":148},[263],{"type":37,"value":264}," total_purchases\n",{"type":32,"tag":105,"props":266,"children":268},{"class":107,"line":267},9,[269,274],{"type":32,"tag":105,"props":270,"children":271},{"style":112},[272],{"type":37,"value":273},"FROM",{"type":32,"tag":105,"props":275,"children":276},{"style":123},[277],{"type":37,"value":278}," `project.dataset.events`\n",{"type":32,"tag":105,"props":280,"children":282},{"class":107,"line":281},10,[283,288,293,298,303,308,313,318,322,327],{"type":32,"tag":105,"props":284,"children":285},{"style":112},[286],{"type":37,"value":287},"WHERE",{"type":32,"tag":105,"props":289,"children":290},{"style":148},[291],{"type":37,"value":292}," event_name ",{"type":32,"tag":105,"props":294,"children":295},{"style":112},[296],{"type":37,"value":297},"IN",{"type":32,"tag":105,"props":299,"children":300},{"style":148},[301],{"type":37,"value":302}," (",{"type":32,"tag":105,"props":304,"children":305},{"style":123},[306],{"type":37,"value":307},"'first_visit'",{"type":32,"tag":105,"props":309,"children":310},{"style":148},[311],{"type":37,"value":312},", ",{"type":32,"tag":105,"props":314,"children":315},{"style":123},[316],{"type":37,"value":317},"'purchase'",{"type":32,"tag":105,"props":319,"children":320},{"style":148},[321],{"type":37,"value":312},{"type":32,"tag":105,"props":323,"children":324},{"style":123},[325],{"type":37,"value":326},"'signup'",{"type":32,"tag":105,"props":328,"children":329},{"style":148},[330],{"type":37,"value":331},")\n",{"type":32,"tag":105,"props":333,"children":335},{"class":107,"line":334},11,[336,341],{"type":32,"tag":105,"props":337,"children":338},{"style":112},[339],{"type":37,"value":340},"GROUP BY",{"type":32,"tag":105,"props":342,"children":343},{"style":148},[344],{"type":37,"value":345}," user_id;\n",{"type":32,"tag":33,"props":347,"children":348},{},[349,351,357],{"type":37,"value":350},"Эта таблица содержит каждого пользователя один раз, ",{"type":32,"tag":52,"props":352,"children":354},{"className":353},[],[355],{"type":37,"value":356},"cohort_date",{"type":37,"value":358}," — partition key. При появлении нового пользователя добавление происходит только в соответствующий partition. Размер таблицы масштабируется по числу пользователей (не по количеству событий); для 10 миллионов пользователей это ~500 МБ.",{"type":32,"tag":33,"props":360,"children":361},{},[362,364,370],{"type":37,"value":363},"Вторая таблица ",{"type":32,"tag":52,"props":365,"children":367},{"className":366},[],[368],{"type":37,"value":369},"daily_user_activity",{"type":37,"value":371}," хранит флаг, был ли активен каждый пользователь в каждый день:",{"type":32,"tag":95,"props":373,"children":375},{"className":97,"code":374,"language":99,"meta":16,"style":16},"CREATE TABLE `project.dataset.daily_user_activity`\nPARTITION BY activity_date\nCLUSTER BY user_id\nAS\nSELECT\n  user_id,\n  DATE(event_timestamp) AS activity_date,\n  TRUE AS is_active\nFROM `project.dataset.events`\nWHERE event_name IN ('pageview', 'purchase', 'session_start')\nGROUP BY user_id, activity_date;\n",[376],{"type":32,"tag":52,"props":377,"children":378},{"__ignoreMap":16},[379,395,411,426,433,440,447,469,486,497,542],{"type":32,"tag":105,"props":380,"children":381},{"class":107,"line":108},[382,386,390],{"type":32,"tag":105,"props":383,"children":384},{"style":112},[385],{"type":37,"value":115},{"type":32,"tag":105,"props":387,"children":388},{"style":112},[389],{"type":37,"value":120},{"type":32,"tag":105,"props":391,"children":392},{"style":123},[393],{"type":37,"value":394}," `project.dataset.daily_user_activity`\n",{"type":32,"tag":105,"props":396,"children":397},{"class":107,"line":129},[398,402,406],{"type":32,"tag":105,"props":399,"children":400},{"style":112},[401],{"type":37,"value":135},{"type":32,"tag":105,"props":403,"children":404},{"style":112},[405],{"type":37,"value":140},{"type":32,"tag":105,"props":407,"children":408},{"style":148},[409],{"type":37,"value":410}," activity_date\n",{"type":32,"tag":105,"props":412,"children":413},{"class":107,"line":154},[414,418,422],{"type":32,"tag":105,"props":415,"children":416},{"style":148},[417],{"type":37,"value":160},{"type":32,"tag":105,"props":419,"children":420},{"style":112},[421],{"type":37,"value":165},{"type":32,"tag":105,"props":423,"children":424},{"style":148},[425],{"type":37,"value":170},{"type":32,"tag":105,"props":427,"children":428},{"class":107,"line":173},[429],{"type":32,"tag":105,"props":430,"children":431},{"style":112},[432],{"type":37,"value":179},{"type":32,"tag":105,"props":434,"children":435},{"class":107,"line":182},[436],{"type":32,"tag":105,"props":437,"children":438},{"style":112},[439],{"type":37,"value":188},{"type":32,"tag":105,"props":441,"children":442},{"class":107,"line":191},[443],{"type":32,"tag":105,"props":444,"children":445},{"style":148},[446],{"type":37,"value":197},{"type":32,"tag":105,"props":448,"children":449},{"class":107,"line":200},[450,455,460,464],{"type":32,"tag":105,"props":451,"children":452},{"style":112},[453],{"type":37,"value":454},"  DATE",{"type":32,"tag":105,"props":456,"children":457},{"style":148},[458],{"type":37,"value":459},"(event_timestamp) ",{"type":32,"tag":105,"props":461,"children":462},{"style":112},[463],{"type":37,"value":227},{"type":32,"tag":105,"props":465,"children":466},{"style":148},[467],{"type":37,"value":468}," activity_date,\n",{"type":32,"tag":105,"props":470,"children":471},{"class":107,"line":26},[472,477,481],{"type":32,"tag":105,"props":473,"children":474},{"style":148},[475],{"type":37,"value":476},"  TRUE ",{"type":32,"tag":105,"props":478,"children":479},{"style":112},[480],{"type":37,"value":227},{"type":32,"tag":105,"props":482,"children":483},{"style":148},[484],{"type":37,"value":485}," is_active\n",{"type":32,"tag":105,"props":487,"children":488},{"class":107,"line":267},[489,493],{"type":32,"tag":105,"props":490,"children":491},{"style":112},[492],{"type":37,"value":273},{"type":32,"tag":105,"props":494,"children":495},{"style":123},[496],{"type":37,"value":278},{"type":32,"tag":105,"props":498,"children":499},{"class":107,"line":281},[500,504,508,512,516,521,525,529,533,538],{"type":32,"tag":105,"props":501,"children":502},{"style":112},[503],{"type":37,"value":287},{"type":32,"tag":105,"props":505,"children":506},{"style":148},[507],{"type":37,"value":292},{"type":32,"tag":105,"props":509,"children":510},{"style":112},[511],{"type":37,"value":297},{"type":32,"tag":105,"props":513,"children":514},{"style":148},[515],{"type":37,"value":302},{"type":32,"tag":105,"props":517,"children":518},{"style":123},[519],{"type":37,"value":520},"'pageview'",{"type":32,"tag":105,"props":522,"children":523},{"style":148},[524],{"type":37,"value":312},{"type":32,"tag":105,"props":526,"children":527},{"style":123},[528],{"type":37,"value":317},{"type":32,"tag":105,"props":530,"children":531},{"style":148},[532],{"type":37,"value":312},{"type":32,"tag":105,"props":534,"children":535},{"style":123},[536],{"type":37,"value":537},"'session_start'",{"type":32,"tag":105,"props":539,"children":540},{"style":148},[541],{"type":37,"value":331},{"type":32,"tag":105,"props":543,"children":544},{"class":107,"line":334},[545,549],{"type":32,"tag":105,"props":546,"children":547},{"style":112},[548],{"type":37,"value":340},{"type":32,"tag":105,"props":550,"children":551},{"style":148},[552],{"type":37,"value":553}," user_id, activity_date;\n",{"type":32,"tag":33,"props":555,"children":556},{},[557],{"type":37,"value":558},"Запрос удержания выполняется через join этих двух таблиц:",{"type":32,"tag":95,"props":560,"children":562},{"className":97,"code":561,"language":99,"meta":16,"style":16},"SELECT\n  c.cohort_date,\n  DATE_DIFF(a.activity_date, c.cohort_date, DAY) AS days_since_cohort,\n  COUNT(DISTINCT c.user_id) AS cohort_size,\n  COUNT(DISTINCT a.user_id) AS active_users,\n  SAFE_DIVIDE(COUNT(DISTINCT a.user_id), COUNT(DISTINCT c.user_id)) AS retention_rate\nFROM `project.dataset.cohort_assignments` c\nLEFT JOIN `project.dataset.daily_user_activity` a\n  ON c.user_id = a.user_id\n  AND a.activity_date >= c.cohort_date\nWHERE c.cohort_date >= '2026-01-01'\nGROUP BY c.cohort_date, days_since_cohort\nORDER BY c.cohort_date, days_since_cohort;\n",[563],{"type":32,"tag":52,"props":564,"children":565},{"__ignoreMap":16},[566,573,595,656,700,741,817,834,852,890,928,956,981],{"type":32,"tag":105,"props":567,"children":568},{"class":107,"line":108},[569],{"type":32,"tag":105,"props":570,"children":571},{"style":112},[572],{"type":37,"value":188},{"type":32,"tag":105,"props":574,"children":575},{"class":107,"line":129},[576,581,586,590],{"type":32,"tag":105,"props":577,"children":578},{"style":204},[579],{"type":37,"value":580},"  c",{"type":32,"tag":105,"props":582,"children":583},{"style":148},[584],{"type":37,"value":585},".",{"type":32,"tag":105,"props":587,"children":588},{"style":204},[589],{"type":37,"value":356},{"type":32,"tag":105,"props":591,"children":592},{"style":148},[593],{"type":37,"value":594},",\n",{"type":32,"tag":105,"props":596,"children":597},{"class":107,"line":154},[598,603,608,612,617,621,626,630,634,638,643,647,651],{"type":32,"tag":105,"props":599,"children":600},{"style":148},[601],{"type":37,"value":602},"  DATE_DIFF(",{"type":32,"tag":105,"props":604,"children":605},{"style":204},[606],{"type":37,"value":607},"a",{"type":32,"tag":105,"props":609,"children":610},{"style":148},[611],{"type":37,"value":585},{"type":32,"tag":105,"props":613,"children":614},{"style":204},[615],{"type":37,"value":616},"activity_date",{"type":32,"tag":105,"props":618,"children":619},{"style":148},[620],{"type":37,"value":312},{"type":32,"tag":105,"props":622,"children":623},{"style":204},[624],{"type":37,"value":625},"c",{"type":32,"tag":105,"props":627,"children":628},{"style":148},[629],{"type":37,"value":585},{"type":32,"tag":105,"props":631,"children":632},{"style":204},[633],{"type":37,"value":356},{"type":32,"tag":105,"props":635,"children":636},{"style":148},[637],{"type":37,"value":312},{"type":32,"tag":105,"props":639,"children":640},{"style":112},[641],{"type":37,"value":642},"DAY",{"type":32,"tag":105,"props":644,"children":645},{"style":148},[646],{"type":37,"value":255},{"type":32,"tag":105,"props":648,"children":649},{"style":112},[650],{"type":37,"value":227},{"type":32,"tag":105,"props":652,"children":653},{"style":148},[654],{"type":37,"value":655}," days_since_cohort,\n",{"type":32,"tag":105,"props":657,"children":658},{"class":107,"line":173},[659,664,668,673,678,682,687,691,695],{"type":32,"tag":105,"props":660,"children":661},{"style":204},[662],{"type":37,"value":663},"  COUNT",{"type":32,"tag":105,"props":665,"children":666},{"style":148},[667],{"type":37,"value":212},{"type":32,"tag":105,"props":669,"children":670},{"style":112},[671],{"type":37,"value":672},"DISTINCT",{"type":32,"tag":105,"props":674,"children":675},{"style":204},[676],{"type":37,"value":677}," c",{"type":32,"tag":105,"props":679,"children":680},{"style":148},[681],{"type":37,"value":585},{"type":32,"tag":105,"props":683,"children":684},{"style":204},[685],{"type":37,"value":686},"user_id",{"type":32,"tag":105,"props":688,"children":689},{"style":148},[690],{"type":37,"value":255},{"type":32,"tag":105,"props":692,"children":693},{"style":112},[694],{"type":37,"value":227},{"type":32,"tag":105,"props":696,"children":697},{"style":148},[698],{"type":37,"value":699}," cohort_size,\n",{"type":32,"tag":105,"props":701,"children":702},{"class":107,"line":182},[703,707,711,715,720,724,728,732,736],{"type":32,"tag":105,"props":704,"children":705},{"style":204},[706],{"type":37,"value":663},{"type":32,"tag":105,"props":708,"children":709},{"style":148},[710],{"type":37,"value":212},{"type":32,"tag":105,"props":712,"children":713},{"style":112},[714],{"type":37,"value":672},{"type":32,"tag":105,"props":716,"children":717},{"style":204},[718],{"type":37,"value":719}," a",{"type":32,"tag":105,"props":721,"children":722},{"style":148},[723],{"type":37,"value":585},{"type":32,"tag":105,"props":725,"children":726},{"style":204},[727],{"type":37,"value":686},{"type":32,"tag":105,"props":729,"children":730},{"style":148},[731],{"type":37,"value":255},{"type":32,"tag":105,"props":733,"children":734},{"style":112},[735],{"type":37,"value":227},{"type":32,"tag":105,"props":737,"children":738},{"style":148},[739],{"type":37,"value":740}," active_users,\n",{"type":32,"tag":105,"props":742,"children":743},{"class":107,"line":191},[744,749,754,758,762,766,770,774,779,783,787,791,795,799,803,808,812],{"type":32,"tag":105,"props":745,"children":746},{"style":148},[747],{"type":37,"value":748},"  SAFE_DIVIDE(",{"type":32,"tag":105,"props":750,"children":751},{"style":204},[752],{"type":37,"value":753},"COUNT",{"type":32,"tag":105,"props":755,"children":756},{"style":148},[757],{"type":37,"value":212},{"type":32,"tag":105,"props":759,"children":760},{"style":112},[761],{"type":37,"value":672},{"type":32,"tag":105,"props":763,"children":764},{"style":204},[765],{"type":37,"value":719},{"type":32,"tag":105,"props":767,"children":768},{"style":148},[769],{"type":37,"value":585},{"type":32,"tag":105,"props":771,"children":772},{"style":204},[773],{"type":37,"value":686},{"type":32,"tag":105,"props":775,"children":776},{"style":148},[777],{"type":37,"value":778},"), ",{"type":32,"tag":105,"props":780,"children":781},{"style":204},[782],{"type":37,"value":753},{"type":32,"tag":105,"props":784,"children":785},{"style":148},[786],{"type":37,"value":212},{"type":32,"tag":105,"props":788,"children":789},{"style":112},[790],{"type":37,"value":672},{"type":32,"tag":105,"props":792,"children":793},{"style":204},[794],{"type":37,"value":677},{"type":32,"tag":105,"props":796,"children":797},{"style":148},[798],{"type":37,"value":585},{"type":32,"tag":105,"props":800,"children":801},{"style":204},[802],{"type":37,"value":686},{"type":32,"tag":105,"props":804,"children":805},{"style":148},[806],{"type":37,"value":807},")) ",{"type":32,"tag":105,"props":809,"children":810},{"style":112},[811],{"type":37,"value":227},{"type":32,"tag":105,"props":813,"children":814},{"style":148},[815],{"type":37,"value":816}," retention_rate\n",{"type":32,"tag":105,"props":818,"children":819},{"class":107,"line":200},[820,824,829],{"type":32,"tag":105,"props":821,"children":822},{"style":112},[823],{"type":37,"value":273},{"type":32,"tag":105,"props":825,"children":826},{"style":123},[827],{"type":37,"value":828}," `project.dataset.cohort_assignments`",{"type":32,"tag":105,"props":830,"children":831},{"style":148},[832],{"type":37,"value":833}," c\n",{"type":32,"tag":105,"props":835,"children":836},{"class":107,"line":26},[837,842,847],{"type":32,"tag":105,"props":838,"children":839},{"style":112},[840],{"type":37,"value":841},"LEFT JOIN",{"type":32,"tag":105,"props":843,"children":844},{"style":123},[845],{"type":37,"value":846}," `project.dataset.daily_user_activity`",{"type":32,"tag":105,"props":848,"children":849},{"style":148},[850],{"type":37,"value":851}," a\n",{"type":32,"tag":105,"props":853,"children":854},{"class":107,"line":267},[855,860,864,868,872,877,881,885],{"type":32,"tag":105,"props":856,"children":857},{"style":112},[858],{"type":37,"value":859},"  ON",{"type":32,"tag":105,"props":861,"children":862},{"style":204},[863],{"type":37,"value":677},{"type":32,"tag":105,"props":865,"children":866},{"style":148},[867],{"type":37,"value":585},{"type":32,"tag":105,"props":869,"children":870},{"style":204},[871],{"type":37,"value":686},{"type":32,"tag":105,"props":873,"children":874},{"style":112},[875],{"type":37,"value":876}," =",{"type":32,"tag":105,"props":878,"children":879},{"style":204},[880],{"type":37,"value":719},{"type":32,"tag":105,"props":882,"children":883},{"style":148},[884],{"type":37,"value":585},{"type":32,"tag":105,"props":886,"children":887},{"style":204},[888],{"type":37,"value":889},"user_id\n",{"type":32,"tag":105,"props":891,"children":892},{"class":107,"line":281},[893,898,902,906,910,915,919,923],{"type":32,"tag":105,"props":894,"children":895},{"style":112},[896],{"type":37,"value":897},"  AND",{"type":32,"tag":105,"props":899,"children":900},{"style":204},[901],{"type":37,"value":719},{"type":32,"tag":105,"props":903,"children":904},{"style":148},[905],{"type":37,"value":585},{"type":32,"tag":105,"props":907,"children":908},{"style":204},[909],{"type":37,"value":616},{"type":32,"tag":105,"props":911,"children":912},{"style":112},[913],{"type":37,"value":914}," >=",{"type":32,"tag":105,"props":916,"children":917},{"style":204},[918],{"type":37,"value":677},{"type":32,"tag":105,"props":920,"children":921},{"style":148},[922],{"type":37,"value":585},{"type":32,"tag":105,"props":924,"children":925},{"style":204},[926],{"type":37,"value":927},"cohort_date\n",{"type":32,"tag":105,"props":929,"children":930},{"class":107,"line":334},[931,935,939,943,947,951],{"type":32,"tag":105,"props":932,"children":933},{"style":112},[934],{"type":37,"value":287},{"type":32,"tag":105,"props":936,"children":937},{"style":204},[938],{"type":37,"value":677},{"type":32,"tag":105,"props":940,"children":941},{"style":148},[942],{"type":37,"value":585},{"type":32,"tag":105,"props":944,"children":945},{"style":204},[946],{"type":37,"value":356},{"type":32,"tag":105,"props":948,"children":949},{"style":112},[950],{"type":37,"value":914},{"type":32,"tag":105,"props":952,"children":953},{"style":123},[954],{"type":37,"value":955}," '2026-01-01'\n",{"type":32,"tag":105,"props":957,"children":959},{"class":107,"line":958},12,[960,964,968,972,976],{"type":32,"tag":105,"props":961,"children":962},{"style":112},[963],{"type":37,"value":340},{"type":32,"tag":105,"props":965,"children":966},{"style":204},[967],{"type":37,"value":677},{"type":32,"tag":105,"props":969,"children":970},{"style":148},[971],{"type":37,"value":585},{"type":32,"tag":105,"props":973,"children":974},{"style":204},[975],{"type":37,"value":356},{"type":32,"tag":105,"props":977,"children":978},{"style":148},[979],{"type":37,"value":980},", days_since_cohort\n",{"type":32,"tag":105,"props":982,"children":984},{"class":107,"line":983},13,[985,990,994,998,1002],{"type":32,"tag":105,"props":986,"children":987},{"style":112},[988],{"type":37,"value":989},"ORDER BY",{"type":32,"tag":105,"props":991,"children":992},{"style":204},[993],{"type":37,"value":677},{"type":32,"tag":105,"props":995,"children":996},{"style":148},[997],{"type":37,"value":585},{"type":32,"tag":105,"props":999,"children":1000},{"style":204},[1001],{"type":37,"value":356},{"type":32,"tag":105,"props":1003,"children":1004},{"style":148},[1005],{"type":37,"value":1006},", days_since_cohort;\n",{"type":32,"tag":33,"props":1008,"children":1009},{},[1010],{"type":37,"value":1011},"Этот запрос больше не сканирует таблицу событий объёмом в терабайты, а выполняет простой join двух малых таблиц. На BigQuery для 10 миллионов пользователей это займёт ~2 секунды, стоимость $0.02 — 96% снижение затрат.",{"type":32,"tag":40,"props":1013,"children":1015},{"id":1014},"стратегия-partitioning-какая-дата-в-какой-раздел",[1016],{"type":37,"value":1017},"Стратегия partitioning: какая дата в какой раздел",{"type":32,"tag":33,"props":1019,"children":1020},{},[1021,1023,1028,1030,1035],{"type":37,"value":1022},"Стратегия partitioning для таблиц когорт критична, потому что существуют два временных измерения: дата когорты и дата активности. Таблица ",{"type":32,"tag":52,"props":1024,"children":1026},{"className":1025},[],[1027],{"type":37,"value":91},{"type":37,"value":1029}," партиционируется по ",{"type":32,"tag":52,"props":1031,"children":1033},{"className":1032},[],[1034],{"type":37,"value":356},{"type":37,"value":1036},", потому что она хранит первое событие пользователя и определение когорты неизменно. При появлении нового пользователя добавление происходит только в partition текущего дня, прошлые partitions остаются неизменяемыми.",{"type":32,"tag":33,"props":1038,"children":1039},{},[1040,1042,1047,1048,1053],{"type":37,"value":1041},"Таблица ",{"type":32,"tag":52,"props":1043,"children":1045},{"className":1044},[],[1046],{"type":37,"value":369},{"type":37,"value":1029},{"type":32,"tag":52,"props":1049,"children":1051},{"className":1050},[],[1052],{"type":37,"value":616},{"type":37,"value":1054},", потому что новые данные активности поступают каждый день и прошлые дни не меняются. Эта структура подходит для incremental refresh: job (dbt или Airflow) каждый день записывает только partition сегодня, не трогая прошлые partitions.",{"type":32,"tag":33,"props":1056,"children":1057},{},[1058,1060,1066],{"type":37,"value":1059},"Однако анализ удержания требует join между двумя датами: cohort_date и activity_date. Для оптимизации производительности join используется cluster key. BigQuery с ",{"type":32,"tag":52,"props":1061,"children":1063},{"className":1062},[],[1064],{"type":37,"value":1065},"CLUSTER BY user_id",{"type":37,"value":1067}," физически размещает строки с одинаковым user_id рядом, join использует блочное pruning и снижает дисковый ввод-вывод. Для 10 миллионов пользователей join без cluster key занимает ~8 секунд, с cluster key — ~2 секунды.",{"type":32,"tag":33,"props":1069,"children":1070},{},[1071,1073,1079],{"type":37,"value":1072},"Partition pruning также важна. Анализ удержания обычно рассматривает когорты за последние 90 дней. Фильтр ",{"type":32,"tag":52,"props":1074,"children":1076},{"className":1075},[],[1077],{"type":37,"value":1078},"WHERE c.cohort_date >= '2026-05-01'",{"type":37,"value":1080}," срабатывает partition pruning — BigQuery читает только релевантные partitions. Для 2 лет данных без partition pruning стоимость запроса ~$0.50, с pruning $0.02 — данные, которые сканируются, уменьшаются в 24 раза.",{"type":32,"tag":33,"props":1082,"children":1083},{},[1084],{"type":37,"value":1085},"В стратегии partitioning есть компромисс: дневные partitions упрощают incremental refresh, но слишком много partitions (более 1000) увеличивает overhead планирования запросов в BigQuery. Поэтому данные когорт старше 2 лет должны быть заархивированы или консолидированы в месячные partitions.",{"type":32,"tag":40,"props":1087,"children":1089},{"id":1088},"incremental-refresh-вычисляй-только-новые-данные",[1090],{"type":37,"value":1091},"Incremental Refresh: вычисляй только новые данные",{"type":32,"tag":33,"props":1093,"children":1094},{},[1095],{"type":37,"value":1096},"Таблицы когорт должны обновляться ежедневно, потому что новые пользователи добавляются в когорты и поведение удержания существующих когорт обновляется. Однако полный refresh — пересчёт всей таблицы с нуля — избыточен. Решение: паттерн incremental build.",{"type":32,"tag":33,"props":1098,"children":1099},{},[1100],{"type":37,"value":1101},"В dbt incremental модель выглядит так:",{"type":32,"tag":95,"props":1103,"children":1105},{"className":97,"code":1104,"language":99,"meta":16,"style":16},"{{\n  config(\n    materialized='incremental',\n    partition_by={'field': 'cohort_date', 'data_type': 'date'},\n    cluster_by=['user_id'],\n    incremental_strategy='insert_overwrite'\n  )\n}}\n\nSELECT\n  user_id,\n  MIN(DATE(event_timestamp)) AS cohort_date,\n  COUNTIF(event_name = 'purchase') AS total_purchases\nFROM {{ source('raw', 'events') }}\nWHERE DATE(event_timestamp) = CURRENT_DATE() - 1\n{% if is_incremental() %}\n  AND DATE(event_timestamp) > (SELECT MAX(cohort_date) FROM {{ this }})\n{% endif %}\nGROUP BY user_id\n",[1106],{"type":32,"tag":52,"props":1107,"children":1108},{"__ignoreMap":16},[1109,1117,1125,1146,1201,1218,1235,1243,1251,1260,1267,1274,1301,1328,1360,1395,1414,1463,1472],{"type":32,"tag":105,"props":1110,"children":1111},{"class":107,"line":108},[1112],{"type":32,"tag":105,"props":1113,"children":1114},{"style":148},[1115],{"type":37,"value":1116},"{{\n",{"type":32,"tag":105,"props":1118,"children":1119},{"class":107,"line":129},[1120],{"type":32,"tag":105,"props":1121,"children":1122},{"style":148},[1123],{"type":37,"value":1124},"  config(\n",{"type":32,"tag":105,"props":1126,"children":1127},{"class":107,"line":154},[1128,1133,1137,1142],{"type":32,"tag":105,"props":1129,"children":1130},{"style":148},[1131],{"type":37,"value":1132},"    materialized",{"type":32,"tag":105,"props":1134,"children":1135},{"style":112},[1136],{"type":37,"value":245},{"type":32,"tag":105,"props":1138,"children":1139},{"style":123},[1140],{"type":37,"value":1141},"'incremental'",{"type":32,"tag":105,"props":1143,"children":1144},{"style":148},[1145],{"type":37,"value":594},{"type":32,"tag":105,"props":1147,"children":1148},{"class":107,"line":173},[1149,1154,1158,1163,1168,1173,1178,1182,1187,1191,1196],{"type":32,"tag":105,"props":1150,"children":1151},{"style":148},[1152],{"type":37,"value":1153},"    partition_by",{"type":32,"tag":105,"props":1155,"children":1156},{"style":112},[1157],{"type":37,"value":245},{"type":32,"tag":105,"props":1159,"children":1160},{"style":148},[1161],{"type":37,"value":1162},"{",{"type":32,"tag":105,"props":1164,"children":1165},{"style":123},[1166],{"type":37,"value":1167},"'field'",{"type":32,"tag":105,"props":1169,"children":1170},{"style":148},[1171],{"type":37,"value":1172},": ",{"type":32,"tag":105,"props":1174,"children":1175},{"style":123},[1176],{"type":37,"value":1177},"'cohort_date'",{"type":32,"tag":105,"props":1179,"children":1180},{"style":148},[1181],{"type":37,"value":312},{"type":32,"tag":105,"props":1183,"children":1184},{"style":123},[1185],{"type":37,"value":1186},"'data_type'",{"type":32,"tag":105,"props":1188,"children":1189},{"style":148},[1190],{"type":37,"value":1172},{"type":32,"tag":105,"props":1192,"children":1193},{"style":123},[1194],{"type":37,"value":1195},"'date'",{"type":32,"tag":105,"props":1197,"children":1198},{"style":148},[1199],{"type":37,"value":1200},"},\n",{"type":32,"tag":105,"props":1202,"children":1203},{"class":107,"line":182},[1204,1209,1213],{"type":32,"tag":105,"props":1205,"children":1206},{"style":148},[1207],{"type":37,"value":1208},"    cluster_by",{"type":32,"tag":105,"props":1210,"children":1211},{"style":112},[1212],{"type":37,"value":245},{"type":32,"tag":105,"props":1214,"children":1215},{"style":148},[1216],{"type":37,"value":1217},"['user_id'],\n",{"type":32,"tag":105,"props":1219,"children":1220},{"class":107,"line":191},[1221,1226,1230],{"type":32,"tag":105,"props":1222,"children":1223},{"style":148},[1224],{"type":37,"value":1225},"    incremental_strategy",{"type":32,"tag":105,"props":1227,"children":1228},{"style":112},[1229],{"type":37,"value":245},{"type":32,"tag":105,"props":1231,"children":1232},{"style":123},[1233],{"type":37,"value":1234},"'insert_overwrite'\n",{"type":32,"tag":105,"props":1236,"children":1237},{"class":107,"line":200},[1238],{"type":32,"tag":105,"props":1239,"children":1240},{"style":148},[1241],{"type":37,"value":1242},"  )\n",{"type":32,"tag":105,"props":1244,"children":1245},{"class":107,"line":26},[1246],{"type":32,"tag":105,"props":1247,"children":1248},{"style":148},[1249],{"type":37,"value":1250},"}}\n",{"type":32,"tag":105,"props":1252,"children":1253},{"class":107,"line":267},[1254],{"type":32,"tag":105,"props":1255,"children":1257},{"emptyLinePlaceholder":1256},true,[1258],{"type":37,"value":1259},"\n",{"type":32,"tag":105,"props":1261,"children":1262},{"class":107,"line":281},[1263],{"type":32,"tag":105,"props":1264,"children":1265},{"style":112},[1266],{"type":37,"value":188},{"type":32,"tag":105,"props":1268,"children":1269},{"class":107,"line":334},[1270],{"type":32,"tag":105,"props":1271,"children":1272},{"style":148},[1273],{"type":37,"value":197},{"type":32,"tag":105,"props":1275,"children":1276},{"class":107,"line":958},[1277,1281,1285,1289,1293,1297],{"type":32,"tag":105,"props":1278,"children":1279},{"style":204},[1280],{"type":37,"value":207},{"type":32,"tag":105,"props":1282,"children":1283},{"style":148},[1284],{"type":37,"value":212},{"type":32,"tag":105,"props":1286,"children":1287},{"style":112},[1288],{"type":37,"value":217},{"type":32,"tag":105,"props":1290,"children":1291},{"style":148},[1292],{"type":37,"value":222},{"type":32,"tag":105,"props":1294,"children":1295},{"style":112},[1296],{"type":37,"value":227},{"type":32,"tag":105,"props":1298,"children":1299},{"style":148},[1300],{"type":37,"value":232},{"type":32,"tag":105,"props":1302,"children":1303},{"class":107,"line":983},[1304,1308,1312,1316,1320,1324],{"type":32,"tag":105,"props":1305,"children":1306},{"style":148},[1307],{"type":37,"value":240},{"type":32,"tag":105,"props":1309,"children":1310},{"style":112},[1311],{"type":37,"value":245},{"type":32,"tag":105,"props":1313,"children":1314},{"style":123},[1315],{"type":37,"value":250},{"type":32,"tag":105,"props":1317,"children":1318},{"style":148},[1319],{"type":37,"value":255},{"type":32,"tag":105,"props":1321,"children":1322},{"style":112},[1323],{"type":37,"value":227},{"type":32,"tag":105,"props":1325,"children":1326},{"style":148},[1327],{"type":37,"value":264},{"type":32,"tag":105,"props":1329,"children":1331},{"class":107,"line":1330},14,[1332,1336,1341,1346,1350,1355],{"type":32,"tag":105,"props":1333,"children":1334},{"style":112},[1335],{"type":37,"value":273},{"type":32,"tag":105,"props":1337,"children":1338},{"style":148},[1339],{"type":37,"value":1340}," {{ source(",{"type":32,"tag":105,"props":1342,"children":1343},{"style":123},[1344],{"type":37,"value":1345},"'raw'",{"type":32,"tag":105,"props":1347,"children":1348},{"style":148},[1349],{"type":37,"value":312},{"type":32,"tag":105,"props":1351,"children":1352},{"style":123},[1353],{"type":37,"value":1354},"'events'",{"type":32,"tag":105,"props":1356,"children":1357},{"style":148},[1358],{"type":37,"value":1359},") }}\n",{"type":32,"tag":105,"props":1361,"children":1363},{"class":107,"line":1362},15,[1364,1368,1372,1376,1380,1385,1390],{"type":32,"tag":105,"props":1365,"children":1366},{"style":112},[1367],{"type":37,"value":287},{"type":32,"tag":105,"props":1369,"children":1370},{"style":112},[1371],{"type":37,"value":145},{"type":32,"tag":105,"props":1373,"children":1374},{"style":148},[1375],{"type":37,"value":459},{"type":32,"tag":105,"props":1377,"children":1378},{"style":112},[1379],{"type":37,"value":245},{"type":32,"tag":105,"props":1381,"children":1382},{"style":148},[1383],{"type":37,"value":1384}," CURRENT_DATE() ",{"type":32,"tag":105,"props":1386,"children":1387},{"style":112},[1388],{"type":37,"value":1389},"-",{"type":32,"tag":105,"props":1391,"children":1392},{"style":204},[1393],{"type":37,"value":1394}," 1\n",{"type":32,"tag":105,"props":1396,"children":1398},{"class":107,"line":1397},16,[1399,1404,1409],{"type":32,"tag":105,"props":1400,"children":1401},{"style":148},[1402],{"type":37,"value":1403},"{% ",{"type":32,"tag":105,"props":1405,"children":1406},{"style":112},[1407],{"type":37,"value":1408},"if",{"type":32,"tag":105,"props":1410,"children":1411},{"style":148},[1412],{"type":37,"value":1413}," is_incremental() %}\n",{"type":32,"tag":105,"props":1415,"children":1417},{"class":107,"line":1416},17,[1418,1422,1426,1430,1435,1439,1444,1449,1454,1458],{"type":32,"tag":105,"props":1419,"children":1420},{"style":112},[1421],{"type":37,"value":897},{"type":32,"tag":105,"props":1423,"children":1424},{"style":112},[1425],{"type":37,"value":145},{"type":32,"tag":105,"props":1427,"children":1428},{"style":148},[1429],{"type":37,"value":459},{"type":32,"tag":105,"props":1431,"children":1432},{"style":112},[1433],{"type":37,"value":1434},">",{"type":32,"tag":105,"props":1436,"children":1437},{"style":148},[1438],{"type":37,"value":302},{"type":32,"tag":105,"props":1440,"children":1441},{"style":112},[1442],{"type":37,"value":1443},"SELECT",{"type":32,"tag":105,"props":1445,"children":1446},{"style":204},[1447],{"type":37,"value":1448}," MAX",{"type":32,"tag":105,"props":1450,"children":1451},{"style":148},[1452],{"type":37,"value":1453},"(cohort_date) ",{"type":32,"tag":105,"props":1455,"children":1456},{"style":112},[1457],{"type":37,"value":273},{"type":32,"tag":105,"props":1459,"children":1460},{"style":148},[1461],{"type":37,"value":1462}," {{ this }})\n",{"type":32,"tag":105,"props":1464,"children":1466},{"class":107,"line":1465},18,[1467],{"type":32,"tag":105,"props":1468,"children":1469},{"style":148},[1470],{"type":37,"value":1471},"{% endif %}\n",{"type":32,"tag":105,"props":1473,"children":1475},{"class":107,"line":1474},19,[1476,1480],{"type":32,"tag":105,"props":1477,"children":1478},{"style":112},[1479],{"type":37,"value":340},{"type":32,"tag":105,"props":1481,"children":1482},{"style":148},[1483],{"type":37,"value":170},{"type":32,"tag":33,"props":1485,"children":1486},{},[1487,1489,1495],{"type":37,"value":1488},"Эта модель каждый день вычисляет только partition вчерашнего дня. Стратегия ",{"type":32,"tag":52,"props":1490,"children":1492},{"className":1491},[],[1493],{"type":37,"value":1494},"insert_overwrite",{"type":37,"value":1496}," удаляет существующий partition и записывает новый. В BigQuery замена на уровне partition — атомарная операция, downstream запросы никогда не читают неполные данные.",{"type":32,"tag":33,"props":1498,"children":1499},{},[1500,1502,1507],{"type":37,"value":1501},"Для таблицы ",{"type":32,"tag":52,"props":1503,"children":1505},{"className":1504},[],[1506],{"type":37,"value":369},{"type":37,"value":1508}," логика incremental проще, потому что каждый день добавляется новый partition, прошлые partitions не меняются:",{"type":32,"tag":95,"props":1510,"children":1512},{"className":97,"code":1511,"language":99,"meta":16,"style":16},"{{\n  config(\n    materialized='incremental',\n    partition_by={'field': 'activity_date', 'data_type': 'date'},\n    cluster_by=['user_id']\n  )\n}}\n\nSELECT\n  user_id,\n  DATE(event_timestamp) AS activity_date,\n  TRUE AS is_active\nFROM {{ source('raw', 'events') }}\nWHERE DATE(event_timestamp) = CURRENT_DATE() - 1\n{% if is_incremental() %}\n  AND DATE(event_timestamp) NOT IN (SELECT DISTINCT activity_date FROM {{ this }})\n{% endif %}\nGROUP BY user_id, activity_date\n",[1513],{"type":32,"tag":52,"props":1514,"children":1515},{"__ignoreMap":16},[1516,1523,1530,1549,1597,1613,1620,1627,1634,1641,1648,1667,1682,1709,1740,1755,1802,1809],{"type":32,"tag":105,"props":1517,"children":1518},{"class":107,"line":108},[1519],{"type":32,"tag":105,"props":1520,"children":1521},{"style":148},[1522],{"type":37,"value":1116},{"type":32,"tag":105,"props":1524,"children":1525},{"class":107,"line":129},[1526],{"type":32,"tag":105,"props":1527,"children":1528},{"style":148},[1529],{"type":37,"value":1124},{"type":32,"tag":105,"props":1531,"children":1532},{"class":107,"line":154},[1533,1537,1541,1545],{"type":32,"tag":105,"props":1534,"children":1535},{"style":148},[1536],{"type":37,"value":1132},{"type":32,"tag":105,"props":1538,"children":1539},{"style":112},[1540],{"type":37,"value":245},{"type":32,"tag":105,"props":1542,"children":1543},{"style":123},[1544],{"type":37,"value":1141},{"type":32,"tag":105,"props":1546,"children":1547},{"style":148},[1548],{"type":37,"value":594},{"type":32,"tag":105,"props":1550,"children":1551},{"class":107,"line":173},[1552,1556,1560,1564,1568,1572,1577,1581,1585,1589,1593],{"type":32,"tag":105,"props":1553,"children":1554},{"style":148},[1555],{"type":37,"value":1153},{"type":32,"tag":105,"props":1557,"children":1558},{"style":112},[1559],{"type":37,"value":245},{"type":32,"tag":105,"props":1561,"children":1562},{"style":148},[1563],{"type":37,"value":1162},{"type":32,"tag":105,"props":1565,"children":1566},{"style":123},[1567],{"type":37,"value":1167},{"type":32,"tag":105,"props":1569,"children":1570},{"style":148},[1571],{"type":37,"value":1172},{"type":32,"tag":105,"props":1573,"children":1574},{"style":123},[1575],{"type":37,"value":1576},"'activity_date'",{"type":32,"tag":105,"props":1578,"children":1579},{"style":148},[1580],{"type":37,"value":312},{"type":32,"tag":105,"props":1582,"children":1583},{"style":123},[1584],{"type":37,"value":1186},{"type":32,"tag":105,"props":1586,"children":1587},{"style":148},[1588],{"type":37,"value":1172},{"type":32,"tag":105,"props":1590,"children":1591},{"style":123},[1592],{"type":37,"value":1195},{"type":32,"tag":105,"props":1594,"children":1595},{"style":148},[1596],{"type":37,"value":1200},{"type":32,"tag":105,"props":1598,"children":1599},{"class":107,"line":182},[1600,1604,1608],{"type":32,"tag":105,"props":1601,"children":1602},{"style":148},[1603],{"type":37,"value":1208},{"type":32,"tag":105,"props":1605,"children":1606},{"style":112},[1607],{"type":37,"value":245},{"type":32,"tag":105,"props":1609,"children":1610},{"style":148},[1611],{"type":37,"value":1612},"['user_id']\n",{"type":32,"tag":105,"props":1614,"children":1615},{"class":107,"line":191},[1616],{"type":32,"tag":105,"props":1617,"children":1618},{"style":148},[1619],{"type":37,"value":1242},{"type":32,"tag":105,"props":1621,"children":1622},{"class":107,"line":200},[1623],{"type":32,"tag":105,"props":1624,"children":1625},{"style":148},[1626],{"type":37,"value":1250},{"type":32,"tag":105,"props":1628,"children":1629},{"class":107,"line":26},[1630],{"type":32,"tag":105,"props":1631,"children":1632},{"emptyLinePlaceholder":1256},[1633],{"type":37,"value":1259},{"type":32,"tag":105,"props":1635,"children":1636},{"class":107,"line":267},[1637],{"type":32,"tag":105,"props":1638,"children":1639},{"style":112},[1640],{"type":37,"value":188},{"type":32,"tag":105,"props":1642,"children":1643},{"class":107,"line":281},[1644],{"type":32,"tag":105,"props":1645,"children":1646},{"style":148},[1647],{"type":37,"value":197},{"type":32,"tag":105,"props":1649,"children":1650},{"class":107,"line":334},[1651,1655,1659,1663],{"type":32,"tag":105,"props":1652,"children":1653},{"style":112},[1654],{"type":37,"value":454},{"type":32,"tag":105,"props":1656,"children":1657},{"style":148},[1658],{"type":37,"value":459},{"type":32,"tag":105,"props":1660,"children":1661},{"style":112},[1662],{"type":37,"value":227},{"type":32,"tag":105,"props":1664,"children":1665},{"style":148},[1666],{"type":37,"value":468},{"type":32,"tag":105,"props":1668,"children":1669},{"class":107,"line":958},[1670,1674,1678],{"type":32,"tag":105,"props":1671,"children":1672},{"style":148},[1673],{"type":37,"value":476},{"type":32,"tag":105,"props":1675,"children":1676},{"style":112},[1677],{"type":37,"value":227},{"type":32,"tag":105,"props":1679,"children":1680},{"style":148},[1681],{"type":37,"value":485},{"type":32,"tag":105,"props":1683,"children":1684},{"class":107,"line":983},[1685,1689,1693,1697,1701,1705],{"type":32,"tag":105,"props":1686,"children":1687},{"style":112},[1688],{"type":37,"value":273},{"type":32,"tag":105,"props":1690,"children":1691},{"style":148},[1692],{"type":37,"value":1340},{"type":32,"tag":105,"props":1694,"children":1695},{"style":123},[1696],{"type":37,"value":1345},{"type":32,"tag":105,"props":1698,"children":1699},{"style":148},[1700],{"type":37,"value":312},{"type":32,"tag":105,"props":1702,"children":1703},{"style":123},[1704],{"type":37,"value":1354},{"type":32,"tag":105,"props":1706,"children":1707},{"style":148},[1708],{"type":37,"value":1359},{"type":32,"tag":105,"props":1710,"children":1711},{"class":107,"line":1330},[1712,1716,1720,1724,1728,1732,1736],{"type":32,"tag":105,"props":1713,"children":1714},{"style":112},[1715],{"type":37,"value":287},{"type":32,"tag":105,"props":1717,"children":1718},{"style":112},[1719],{"type":37,"value":145},{"type":32,"tag":105,"props":1721,"children":1722},{"style":148},[1723],{"type":37,"value":459},{"type":32,"tag":105,"props":1725,"children":1726},{"style":112},[1727],{"type":37,"value":245},{"type":32,"tag":105,"props":1729,"children":1730},{"style":148},[1731],{"type":37,"value":1384},{"type":32,"tag":105,"props":1733,"children":1734},{"style":112},[1735],{"type":37,"value":1389},{"type":32,"tag":105,"props":1737,"children":1738},{"style":204},[1739],{"type":37,"value":1394},{"type":32,"tag":105,"props":1741,"children":1742},{"class":107,"line":1362},[1743,1747,1751],{"type":32,"tag":105,"props":1744,"children":1745},{"style":148},[1746],{"type":37,"value":1403},{"type":32,"tag":105,"props":1748,"children":1749},{"style":112},[1750],{"type":37,"value":1408},{"type":32,"tag":105,"props":1752,"children":1753},{"style":148},[1754],{"type":37,"value":1413},{"type":32,"tag":105,"props":1756,"children":1757},{"class":107,"line":1397},[1758,1762,1766,1770,1775,1780,1784,1789,1794,1798],{"type":32,"tag":105,"props":1759,"children":1760},{"style":112},[1761],{"type":37,"value":897},{"type":32,"tag":105,"props":1763,"children":1764},{"style":112},[1765],{"type":37,"value":145},{"type":32,"tag":105,"props":1767,"children":1768},{"style":148},[1769],{"type":37,"value":459},{"type":32,"tag":105,"props":1771,"children":1772},{"style":112},[1773],{"type":37,"value":1774},"NOT",{"type":32,"tag":105,"props":1776,"children":1777},{"style":112},[1778],{"type":37,"value":1779}," IN",{"type":32,"tag":105,"props":1781,"children":1782},{"style":148},[1783],{"type":37,"value":302},{"type":32,"tag":105,"props":1785,"children":1786},{"style":112},[1787],{"type":37,"value":1788},"SELECT DISTINCT",{"type":32,"tag":105,"props":1790,"children":1791},{"style":148},[1792],{"type":37,"value":1793}," activity_date ",{"type":32,"tag":105,"props":1795,"children":1796},{"style":112},[1797],{"type":37,"value":273},{"type":32,"tag":105,"props":1799,"children":1800},{"style":148},[1801],{"type":37,"value":1462},{"type":32,"tag":105,"props":1803,"children":1804},{"class":107,"line":1416},[1805],{"type":32,"tag":105,"props":1806,"children":1807},{"style":148},[1808],{"type":37,"value":1471},{"type":32,"tag":105,"props":1810,"children":1811},{"class":107,"line":1465},[1812,1816],{"type":32,"tag":105,"props":1813,"children":1814},{"style":112},[1815],{"type":37,"value":340},{"type":32,"tag":105,"props":1817,"children":1818},{"style":148},[1819],{"type":37,"value":1820}," user_id, activity_date\n",{"type":32,"tag":33,"props":1822,"children":1823},{},[1824],{"type":37,"value":1825},"С incremental refresh время дневного job сокращается с 5 минут до 30 секунд. Использование BigQuery slots снижается на 80%, ожидание в очереди запросов исчезает. Когда аналитический отдел открывает дашборд утром в 9:00, вчерашние данные удержания уже готовы.",{"type":32,"tag":33,"props":1827,"children":1828},{},[1829,1831,1837,1839,1845],{"type":37,"value":1830},"Однако в incremental build есть риск: поздно прибывающие данные. Если event pipeline имеет задержку в 2-3 часа, partition вчерашнего дня содержит неполные данные. Два подхода решают эту проблему: (1) параметр ",{"type":32,"tag":52,"props":1832,"children":1834},{"className":1833},[],[1835],{"type":37,"value":1836},"lookback_window",{"type":37,"value":1838}," в dbt — пересчитывать последние 3 дня каждый раз; (2) использование метаданных ",{"type":32,"tag":52,"props":1840,"children":1842},{"className":1841},[],[1843],{"type":37,"value":1844},"_PARTITIONTIME",{"type":37,"value":1846}," в BigQuery для фильтрации по времени вставки partition. Второй способ более эффективен, потому что пересчитывает только поздно прибывшие события.",{"type":32,"tag":40,"props":1848,"children":1850},{"id":1849},"оптимизация-стоимости-запросов-размер-таблицы-и-паттерны-сканирования",[1851],{"type":37,"value":1852},"Оптимизация стоимости запросов: размер таблицы и паттерны сканирования",{"type":32,"tag":33,"props":1854,"children":1855},{},[1856,1858,1863,1865,1870],{"type":37,"value":1857},"Стоимость таблиц когорт зависит от двух факторов: размера таблицы (ГБ) и паттерна сканирования запроса. Таблица ",{"type":32,"tag":52,"props":1859,"children":1861},{"className":1860},[],[1862],{"type":37,"value":91},{"type":37,"value":1864}," для 10 миллионов пользователей занимает ~500 МБ, ",{"type":32,"tag":52,"props":1866,"children":1868},{"className":1867},[],[1869],{"type":37,"value":369},{"type":37,"value":1871}," за 90-дневное окно — ~5 ГБ. При join этих двух таблиц BigQuery сканирует ~6 ГБ, стоимость ~$0.03. Если бы тот же анализ выполнялся на таблице raw events, сканировалось бы 500 ГБ, стоимость была бы ~$2.50 — 80-кратная разница.",{"type":32,"tag":33,"props":1873,"children":1874},{},[1875],{"type":37,"value":1876},"Для дальнейшего снижения стоимости используется таблица pre-aggregated cohort summary:",{"type":32,"tag":95,"props":1878,"children":1880},{"className":97,"code":1879,"language":99,"meta":16,"style":16},"CREATE TABLE `project.dataset.cohort_retention_summary`\nPARTITION BY cohort_date\nCLUSTER BY days_since_cohort\nAS\nSELECT\n  c.cohort_date,\n  DATE_DIFF(a.activity_date, c.cohort_date, DAY) AS days_since_cohort,\n  COUNT(DISTINCT c.user_id) AS cohort_size,\n  COUNT(DISTINCT a.user_id) AS active_users,\n  SAFE_DIVIDE(COUNT(DISTINCT a.user_id), COUNT(DISTINCT c.user_id)) AS retention_rate\nFROM `project.dataset.cohort_assignments` c\nLEFT JOIN `project.dataset.daily_user_activity` a\n  ON c.user_id = a.user_id\n  AND a.activity_date >= c.cohort_date\nGROUP BY c.cohort_date, days_since_cohort;\n",[1881],{"type":32,"tag":52,"props":1882,"children":1883},{"__ignoreMap":16},[1884,1900,1916,1932,1939,1946,1965,2020,2059,2098,2169,2184,2199,2234,2269],{"type":32,"tag":105,"props":1885,"children":1886},{"class":107,"line":108},[1887,1891,1895],{"type":32,"tag":105,"props":1888,"children":1889},{"style":112},[1890],{"type":37,"value":115},{"type":32,"tag":105,"props":1892,"children":1893},{"style":112},[1894],{"type":37,"value":120},{"type":32,"tag":105,"props":1896,"children":1897},{"style":123},[1898],{"type":37,"value":1899}," `project.dataset.cohort_retention_summary`\n",{"type":32,"tag":105,"props":1901,"children":1902},{"class":107,"line":129},[1903,1907,1911],{"type":32,"tag":105,"props":1904,"children":1905},{"style":112},[1906],{"type":37,"value":135},{"type":32,"tag":105,"props":1908,"children":1909},{"style":112},[1910],{"type":37,"value":140},{"type":32,"tag":105,"props":1912,"children":1913},{"style":148},[1914],{"type":37,"value":1915}," cohort_date\n",{"type":32,"tag":105,"props":1917,"children":1918},{"class":107,"line":154},[1919,1923,1927],{"type":32,"tag":105,"props":1920,"children":1921},{"style":148},[1922],{"type":37,"value":160},{"type":32,"tag":105,"props":1924,"children":1925},{"style":112},[1926],{"type":37,"value":165},{"type":32,"tag":105,"props":1928,"children":1929},{"style":148},[1930],{"type":37,"value":1931}," days_since_cohort\n",{"type":32,"tag":105,"props":1933,"children":1934},{"class":107,"line":173},[1935],{"type":32,"tag":105,"props":1936,"children":1937},{"style":112},[1938],{"type":37,"value":179},{"type":32,"tag":105,"props":1940,"children":1941},{"class":107,"line":182},[1942],{"type":32,"tag":105,"props":1943,"children":1944},{"style":112},[1945],{"type":37,"value":188},{"type":32,"tag":105,"props":1947,"children":1948},{"class":107,"line":191},[1949,1953,1957,1961],{"type":32,"tag":105,"props":1950,"children":1951},{"style":204},[1952],{"type":37,"value":580},{"type":32,"tag":105,"props":1954,"children":1955},{"style":148},[1956],{"type":37,"value":585},{"type":32,"tag":105,"props":1958,"children":1959},{"style":204},[1960],{"type":37,"value":356},{"type":32,"tag":105,"props":1962,"children":1963},{"style":148},[1964],{"type":37,"value":594},{"type":32,"tag":105,"props":1966,"children":1967},{"class":107,"line":200},[1968,1972,1976,1980,1984,1988,1992,1996,2000,2004,2008,2012,2016],{"type":32,"tag":105,"props":1969,"children":1970},{"style":148},[1971],{"type":37,"value":602},{"type":32,"tag":105,"props":1973,"children":1974},{"style":204},[1975],{"type":37,"value":607},{"type":32,"tag":105,"props":1977,"children":1978},{"style":148},[1979],{"type":37,"value":585},{"type":32,"tag":105,"props":1981,"children":1982},{"style":204},[1983],{"type":37,"value":616},{"type":32,"tag":105,"props":1985,"children":1986},{"style":148},[1987],{"type":37,"value":312},{"type":32,"tag":105,"props":1989,"children":1990},{"style":204},[1991],{"type":37,"value":625},{"type":32,"tag":105,"props":1993,"children":1994},{"style":148},[1995],{"type":37,"value":585},{"type":32,"tag":105,"props":1997,"children":1998},{"style":204},[1999],{"type":37,"value":356},{"type":32,"tag":105,"props":2001,"children":2002},{"style":148},[2003],{"type":37,"value":312},{"type":32,"tag":105,"props":2005,"children":2006},{"style":112},[2007],{"type":37,"value":642},{"type":32,"tag":105,"props":2009,"children":2010},{"style":148},[2011],{"type":37,"value":255},{"type":32,"tag":105,"props":2013,"children":2014},{"style":112},[2015],{"type":37,"value":227},{"type":32,"tag":105,"props":2017,"children":2018},{"style":148},[2019],{"type":37,"value":655},{"type":32,"tag":105,"props":2021,"children":2022},{"class":107,"line":26},[2023,2027,2031,2035,2039,2043,2047,2051,2055],{"type":32,"tag":105,"props":2024,"children":2025},{"style":204},[2026],{"type":37,"value":663},{"type":32,"tag":105,"props":2028,"children":2029},{"style":148},[2030],{"type":37,"value":212},{"type":32,"tag":105,"props":2032,"children":2033},{"style":112},[2034],{"type":37,"value":672},{"type":32,"tag":105,"props":2036,"children":2037},{"style":204},[2038],{"type":37,"value":677},{"type":32,"tag":105,"props":2040,"children":2041},{"style":148},[2042],{"type":37,"value":585},{"type":32,"tag":105,"props":2044,"children":2045},{"style":204},[2046],{"type":37,"value":686},{"type":32,"tag":105,"props":2048,"children":2049},{"style":148},[2050],{"type":37,"value":255},{"type":32,"tag":105,"props":2052,"children":2053},{"style":112},[2054],{"type":37,"value":227},{"type":32,"tag":105,"props":2056,"children":2057},{"style":148},[2058],{"type":37,"value":699},{"type":32,"tag":105,"props":2060,"children":2061},{"class":107,"line":267},[2062,2066,2070,2074,2078,2082,2086,2090,2094],{"type":32,"tag":105,"props":2063,"children":2064},{"style":204},[2065],{"type":37,"value":663},{"type":32,"tag":105,"props":2067,"children":2068},{"style":148},[2069],{"type":37,"value":212},{"type":32,"tag":105,"props":2071,"children":2072},{"style":112},[2073],{"type":37,"value":672},{"type":32,"tag":105,"props":2075,"children":2076},{"style":204},[2077],{"type":37,"value":719},{"type":32,"tag":105,"props":2079,"children":2080},{"style":148},[2081],{"type":37,"value":585},{"type":32,"tag":105,"props":2083,"children":2084},{"style":204},[2085],{"type":37,"value":686},{"type":32,"tag":105,"props":2087,"children":2088},{"style":148},[2089],{"type":37,"value":255},{"type":32,"tag":105,"props":2091,"children":2092},{"style":112},[2093],{"type":37,"value":227},{"type":32,"tag":105,"props":2095,"children":2096},{"style":148},[2097],{"type":37,"value":740},{"type":32,"tag":105,"props":2099,"children":2100},{"class":107,"line":281},[2101,2105,2109,2113,2117,2121,2125,2129,2133,2137,2141,2145,2149,2153,2157,2161,2165],{"type":32,"tag":105,"props":2102,"children":2103},{"style":148},[2104],{"type":37,"value":748},{"type":32,"tag":105,"props":2106,"children":2107},{"style":204},[2108],{"type":37,"value":753},{"type":32,"tag":105,"props":2110,"children":2111},{"style":148},[2112],{"type":37,"value":212},{"type":32,"tag":105,"props":2114,"children":2115},{"style":112},[2116],{"type":37,"value":672},{"type":32,"tag":105,"props":2118,"children":2119},{"style":204},[2120],{"type":37,"value":719},{"type":32,"tag":105,"props":2122,"children":2123},{"style":148},[2124],{"type":37,"value":585},{"type":32,"tag":105,"props":2126,"children":2127},{"style":204},[2128],{"type":37,"value":686},{"type":32,"tag":105,"props":2130,"children":2131},{"style":148},[2132],{"type":37,"value":778},{"type":32,"tag":105,"props":2134,"children":2135},{"style":204},[2136],{"type":37,"value":753},{"type":32,"tag":105,"props":2138,"children":2139},{"style":148},[2140],{"type":37,"value":212},{"type":32,"tag":105,"props":2142,"children":2143},{"style":112},[2144],{"type":37,"value":672},{"type":32,"tag":105,"props":2146,"children":2147},{"style":204},[2148],{"type":37,"value":677},{"type":32,"tag":105,"props":2150,"children":2151},{"style":148},[2152],{"type":37,"value":585},{"type":32,"tag":105,"props":2154,"children":2155},{"style":204},[2156],{"type":37,"value":686},{"type":32,"tag":105,"props":2158,"children":2159},{"style":148},[2160],{"type":37,"value":807},{"type":32,"tag":105,"props":2162,"children":2163},{"style":112},[2164],{"type":37,"value":227},{"type":32,"tag":105,"props":2166,"children":2167},{"style":148},[2168],{"type":37,"value":816},{"type":32,"tag":105,"props":2170,"children":2171},{"class":107,"line":334},[2172,2176,2180],{"type":32,"tag":105,"props":2173,"children":2174},{"style":112},[2175],{"type":37,"value":273},{"type":32,"tag":105,"props":2177,"children":2178},{"style":123},[2179],{"type":37,"value":828},{"type":32,"tag":105,"props":2181,"children":2182},{"style":148},[2183],{"type":37,"value":833},{"type":32,"tag":105,"props":2185,"children":2186},{"class":107,"line":958},[2187,2191,2195],{"type":32,"tag":105,"props":2188,"children":2189},{"style":112},[2190],{"type":37,"value":841},{"type":32,"tag":105,"props":2192,"children":2193},{"style":123},[2194],{"type":37,"value":846},{"type":32,"tag":105,"props":2196,"children":2197},{"style":148},[2198],{"type":37,"value":851},{"type":32,"tag":105,"props":2200,"children":2201},{"class":107,"line":983},[2202,2206,2210,2214,2218,2222,2226,2230],{"type":32,"tag":105,"props":2203,"children":2204},{"style":112},[2205],{"type":37,"value":859},{"type":32,"tag":105,"props":2207,"children":2208},{"style":204},[2209],{"type":37,"value":677},{"type":32,"tag":105,"props":2211,"children":2212},{"style":148},[2213],{"type":37,"value":585},{"type":32,"tag":105,"props":2215,"children":2216},{"style":204},[2217],{"type":37,"value":686},{"type":32,"tag":105,"props":2219,"children":2220},{"style":112},[2221],{"type":37,"value":876},{"type":32,"tag":105,"props":2223,"children":2224},{"style":204},[2225],{"type":37,"value":719},{"type":32,"tag":105,"props":2227,"children":2228},{"style":148},[2229],{"type":37,"value":585},{"type":32,"tag":105,"props":2231,"children":2232},{"style":204},[2233],{"type":37,"value":889},{"type":32,"tag":105,"props":2235,"children":2236},{"class":107,"line":1330},[2237,2241,2245,2249,2253,2257,2261,2265],{"type":32,"tag":105,"props":2238,"children":2239},{"style":112},[2240],{"type":37,"value":897},{"type":32,"tag":105,"props":2242,"children":2243},{"style":204},[2244],{"type":37,"value":719},{"type":32,"tag":105,"props":2246,"children":2247},{"style":148},[2248],{"type":37,"value":585},{"type":32,"tag":105,"props":2250,"children":2251},{"style":204},[2252],{"type":37,"value":616},{"type":32,"tag":105,"props":2254,"children":2255},{"style":112},[2256],{"type":37,"value":914},{"type":32,"tag":105,"props":2258,"children":2259},{"style":204},[2260],{"type":37,"value":677},{"type":32,"tag":105,"props":2262,"children":2263},{"style":148},[2264],{"type":37,"value":585},{"type":32,"tag":105,"props":2266,"children":2267},{"style":204},[2268],{"type":37,"value":927},{"type":32,"tag":105,"props":2270,"children":2271},{"class":107,"line":1362},[2272,2276,2280,2284,2288],{"type":32,"tag":105,"props":2273,"children":2274},{"style":112},[2275],{"type":37,"value":340},{"type":32,"tag":105,"props":2277,"children":2278},{"style":204},[2279],{"type":37,"value":677},{"type":32,"tag":105,"props":2281,"children":2282},{"style":148},[2283],{"type":37,"value":585},{"type":32,"tag":105,"props":2285,"children":2286},{"style":204},[2287],{"type":37,"value":356},{"type":32,"tag":105,"props":2289,"children":2290},{"style":148},[2291],{"type":37,"value":1006},{"type":32,"tag":33,"props":2293,"children":2294},{},[2295],{"type":37,"value":2296},"Эта таблица хранит предварительно вычисленный коэффициент удержания для каждой комбинации когорты-дня. Размер таблицы ~100 МБ (10 миллионов пользователей × 90 дней = 900 миллионов строк → после агрегирования ~50,000 строк). Дашборд читает эту таблицу, не выполняя join, время запроса \u003C1 секунда, стоимость ~$0.001.",{"type":32,"tag":33,"props":2298,"children":2299},{},[2300],{"type":37,"value":2301},"При оптимизации сто",{"type":32,"tag":2303,"props":2304,"children":2305},"style",{},[2306],{"type":37,"value":2307},"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":154,"depth":154,"links":2309},[2310,2311,2312,2313,2314],{"id":42,"depth":129,"text":45},{"id":72,"depth":129,"text":75},{"id":1014,"depth":129,"text":1017},{"id":1088,"depth":129,"text":1091},{"id":1849,"depth":129,"text":1852},"markdown","content:ru:data:arkhitektura-tablitsy-kohorty-masshtabirovanie-analiza-drzhaniia-v-proizvodstve.md","content","ru\u002Fdata\u002Farkhitektura-tablitsy-kohorty-masshtabirovanie-analiza-drzhaniia-v-proizvodstve.md","ru\u002Fdata\u002Farkhitektura-tablitsy-kohorty-masshtabirovanie-analiza-drzhaniia-v-proizvodstve","md",1786860295166]