[{"data":1,"prerenderedAt":2900},["ShallowReactive",2],{"article-alternates":3,"article-\u002Fes\u002Fdata\u002Farquitectura-tabla-cohorte":13},{"i18nKey":4,"paths":5},"data-007-2026-07",{"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-tabla-cohorte-escalando-analisis-retencion","\u002Ffr\u002Fdata\u002Farchitecture-table-cohort-retention-optimisation-production","\u002Fit\u002Fdata\u002Farchitettura-tabella-cohort-scalabilita-retention-analysis-production","\u002Fru\u002Fdata\u002Fcohort-table-architecture-scaling-retention","\u002Ftr\u002Fdata\u002Fcohort-tablo-mimarisi-retention-analizinin-productionda-olceklenmesi",{"_path":14,"_dir":15,"_draft":16,"_partial":16,"_locale":17,"title":18,"description":19,"publishedAt":20,"modifiedAt":20,"category":15,"i18nKey":4,"tags":21,"readingTime":27,"author":28,"body":29,"_type":2894,"_id":2895,"_source":2896,"_file":2897,"_stem":2898,"_extension":2899},"\u002Fes\u002Fdata\u002Farquitectura-tabla-cohorte","data",false,"","Arquitectura de Tabla Cohorte: Escalado del Análisis de Retención en Producción","Aprende a escalar tablas de análisis de cohorte en producción usando materialized views, particionamiento y optimización de costos de consultas.","2026-07-28",[22,23,24,25,26],"analisis-cohorte","bigquery","materialized-views","data-engineering","retention",8,"Roibase",{"type":30,"children":31,"toc":2878},"root",[32,49,56,84,511,524,529,536,541,624,644,670,675,681,700,889,894,936,941,1192,1212,1218,1230,1546,1551,1557,1569,1896,1900,1947,1960,1966,1986,1994,2020,2028,2052,2068,2074,2079,2132,2145,2172,2177,2194,2200,2213,2218,2254,2275,2281,2286,2309,2320,2367,2384,2395,2433,2450,2469,2475,2480,2488,2579,2596,2604,2872],{"type":33,"tag":34,"props":35,"children":36},"element","p",{},[37,40,47],{"type":38,"value":39},"text","Toda organización que realiza análisis de retención termina en el mismo punto: las consultas de cohorte en producción tardan 30 segundos o la factura de BigQuery se acerca a los $8.000 mensuales. Esa consulta que funcionaba perfecto con 100K usuarios en testing (",{"type":33,"tag":41,"props":42,"children":44},"code",{"className":43},[],[45],{"type":38,"value":46},"GROUP BY user_id, cohort_week",{"type":38,"value":48},") se colapsa cuando se enfrenta a 50M usuarios y 2 años de logs de eventos. La solución no es simple — no se trata solo de añadir índices o activar caché, sino rediseñar la arquitectura de tablas desde cero para una carga de trabajo de retención.",{"type":33,"tag":50,"props":51,"children":53},"h2",{"id":52},"por-qué-el-análisis-de-cohorte-requiere-una-arquitectura-diferente",[54],{"type":38,"value":55},"Por Qué el Análisis de Cohorte Requiere una Arquitectura Diferente",{"type":33,"tag":34,"props":57,"children":58},{},[59,61,67,69,75,76,82],{"type":38,"value":60},"Una tabla de logs de eventos clásica se construye sobre ",{"type":33,"tag":41,"props":62,"children":64},{"className":63},[],[65],{"type":38,"value":66},"user_id",{"type":38,"value":68},", ",{"type":33,"tag":41,"props":70,"children":72},{"className":71},[],[73],{"type":38,"value":74},"event_time",{"type":38,"value":68},{"type":33,"tag":41,"props":77,"children":79},{"className":78},[],[80],{"type":38,"value":81},"event_name",{"type":38,"value":83},". Cada consulta de cohorte escanea miles de millones de filas históricamente, agrupando usuarios por su fecha de primer evento. En BigQuery, la consulta se ve así:",{"type":33,"tag":85,"props":86,"children":90},"pre",{"className":87,"code":88,"language":89,"meta":17,"style":17},"language-sql shiki shiki-themes github-dark","WITH cohorts AS (\n  SELECT user_id, DATE_TRUNC(MIN(event_time), WEEK) AS cohort_week\n  FROM events\n  GROUP BY user_id\n),\nretention AS (\n  SELECT \n    c.cohort_week,\n    DATE_DIFF(DATE_TRUNC(e.event_time, WEEK), c.cohort_week, WEEK) AS weeks_since_cohort,\n    COUNT(DISTINCT e.user_id) AS active_users\n  FROM cohorts c\n  JOIN events e ON c.user_id = e.user_id\n  GROUP BY 1, 2\n)\nSELECT * FROM retention ORDER BY 1, 2;\n","sql",[91],{"type":33,"tag":41,"props":92,"children":93},{"__ignoreMap":17},[94,122,166,180,194,203,220,233,256,325,370,383,433,455,464],{"type":33,"tag":95,"props":96,"children":99},"span",{"class":97,"line":98},"line",1,[100,106,112,117],{"type":33,"tag":95,"props":101,"children":103},{"style":102},"--shiki-default:#F97583",[104],{"type":38,"value":105},"WITH",{"type":33,"tag":95,"props":107,"children":109},{"style":108},"--shiki-default:#E1E4E8",[110],{"type":38,"value":111}," cohorts ",{"type":33,"tag":95,"props":113,"children":114},{"style":102},[115],{"type":38,"value":116},"AS",{"type":33,"tag":95,"props":118,"children":119},{"style":108},[120],{"type":38,"value":121}," (\n",{"type":33,"tag":95,"props":123,"children":125},{"class":97,"line":124},2,[126,131,136,142,147,152,157,161],{"type":33,"tag":95,"props":127,"children":128},{"style":102},[129],{"type":38,"value":130},"  SELECT",{"type":33,"tag":95,"props":132,"children":133},{"style":108},[134],{"type":38,"value":135}," user_id, DATE_TRUNC(",{"type":33,"tag":95,"props":137,"children":139},{"style":138},"--shiki-default:#79B8FF",[140],{"type":38,"value":141},"MIN",{"type":33,"tag":95,"props":143,"children":144},{"style":108},[145],{"type":38,"value":146},"(event_time), ",{"type":33,"tag":95,"props":148,"children":149},{"style":102},[150],{"type":38,"value":151},"WEEK",{"type":33,"tag":95,"props":153,"children":154},{"style":108},[155],{"type":38,"value":156},") ",{"type":33,"tag":95,"props":158,"children":159},{"style":102},[160],{"type":38,"value":116},{"type":33,"tag":95,"props":162,"children":163},{"style":108},[164],{"type":38,"value":165}," cohort_week\n",{"type":33,"tag":95,"props":167,"children":169},{"class":97,"line":168},3,[170,175],{"type":33,"tag":95,"props":171,"children":172},{"style":102},[173],{"type":38,"value":174},"  FROM",{"type":33,"tag":95,"props":176,"children":177},{"style":108},[178],{"type":38,"value":179}," events\n",{"type":33,"tag":95,"props":181,"children":183},{"class":97,"line":182},4,[184,189],{"type":33,"tag":95,"props":185,"children":186},{"style":102},[187],{"type":38,"value":188},"  GROUP BY",{"type":33,"tag":95,"props":190,"children":191},{"style":108},[192],{"type":38,"value":193}," user_id\n",{"type":33,"tag":95,"props":195,"children":197},{"class":97,"line":196},5,[198],{"type":33,"tag":95,"props":199,"children":200},{"style":108},[201],{"type":38,"value":202},"),\n",{"type":33,"tag":95,"props":204,"children":206},{"class":97,"line":205},6,[207,211,216],{"type":33,"tag":95,"props":208,"children":209},{"style":102},[210],{"type":38,"value":26},{"type":33,"tag":95,"props":212,"children":213},{"style":102},[214],{"type":38,"value":215}," AS",{"type":33,"tag":95,"props":217,"children":218},{"style":108},[219],{"type":38,"value":121},{"type":33,"tag":95,"props":221,"children":223},{"class":97,"line":222},7,[224,228],{"type":33,"tag":95,"props":225,"children":226},{"style":102},[227],{"type":38,"value":130},{"type":33,"tag":95,"props":229,"children":230},{"style":108},[231],{"type":38,"value":232}," \n",{"type":33,"tag":95,"props":234,"children":235},{"class":97,"line":27},[236,241,246,251],{"type":33,"tag":95,"props":237,"children":238},{"style":138},[239],{"type":38,"value":240},"    c",{"type":33,"tag":95,"props":242,"children":243},{"style":108},[244],{"type":38,"value":245},".",{"type":33,"tag":95,"props":247,"children":248},{"style":138},[249],{"type":38,"value":250},"cohort_week",{"type":33,"tag":95,"props":252,"children":253},{"style":108},[254],{"type":38,"value":255},",\n",{"type":33,"tag":95,"props":257,"children":259},{"class":97,"line":258},9,[260,265,270,274,278,282,286,291,296,300,304,308,312,316,320],{"type":33,"tag":95,"props":261,"children":262},{"style":108},[263],{"type":38,"value":264},"    DATE_DIFF(DATE_TRUNC(",{"type":33,"tag":95,"props":266,"children":267},{"style":138},[268],{"type":38,"value":269},"e",{"type":33,"tag":95,"props":271,"children":272},{"style":108},[273],{"type":38,"value":245},{"type":33,"tag":95,"props":275,"children":276},{"style":138},[277],{"type":38,"value":74},{"type":33,"tag":95,"props":279,"children":280},{"style":108},[281],{"type":38,"value":68},{"type":33,"tag":95,"props":283,"children":284},{"style":102},[285],{"type":38,"value":151},{"type":33,"tag":95,"props":287,"children":288},{"style":108},[289],{"type":38,"value":290},"), ",{"type":33,"tag":95,"props":292,"children":293},{"style":138},[294],{"type":38,"value":295},"c",{"type":33,"tag":95,"props":297,"children":298},{"style":108},[299],{"type":38,"value":245},{"type":33,"tag":95,"props":301,"children":302},{"style":138},[303],{"type":38,"value":250},{"type":33,"tag":95,"props":305,"children":306},{"style":108},[307],{"type":38,"value":68},{"type":33,"tag":95,"props":309,"children":310},{"style":102},[311],{"type":38,"value":151},{"type":33,"tag":95,"props":313,"children":314},{"style":108},[315],{"type":38,"value":156},{"type":33,"tag":95,"props":317,"children":318},{"style":102},[319],{"type":38,"value":116},{"type":33,"tag":95,"props":321,"children":322},{"style":108},[323],{"type":38,"value":324}," weeks_since_cohort,\n",{"type":33,"tag":95,"props":326,"children":328},{"class":97,"line":327},10,[329,334,339,344,349,353,357,361,365],{"type":33,"tag":95,"props":330,"children":331},{"style":138},[332],{"type":38,"value":333},"    COUNT",{"type":33,"tag":95,"props":335,"children":336},{"style":108},[337],{"type":38,"value":338},"(",{"type":33,"tag":95,"props":340,"children":341},{"style":102},[342],{"type":38,"value":343},"DISTINCT",{"type":33,"tag":95,"props":345,"children":346},{"style":138},[347],{"type":38,"value":348}," e",{"type":33,"tag":95,"props":350,"children":351},{"style":108},[352],{"type":38,"value":245},{"type":33,"tag":95,"props":354,"children":355},{"style":138},[356],{"type":38,"value":66},{"type":33,"tag":95,"props":358,"children":359},{"style":108},[360],{"type":38,"value":156},{"type":33,"tag":95,"props":362,"children":363},{"style":102},[364],{"type":38,"value":116},{"type":33,"tag":95,"props":366,"children":367},{"style":108},[368],{"type":38,"value":369}," active_users\n",{"type":33,"tag":95,"props":371,"children":373},{"class":97,"line":372},11,[374,378],{"type":33,"tag":95,"props":375,"children":376},{"style":102},[377],{"type":38,"value":174},{"type":33,"tag":95,"props":379,"children":380},{"style":108},[381],{"type":38,"value":382}," cohorts c\n",{"type":33,"tag":95,"props":384,"children":386},{"class":97,"line":385},12,[387,392,397,402,407,411,415,420,424,428],{"type":33,"tag":95,"props":388,"children":389},{"style":102},[390],{"type":38,"value":391},"  JOIN",{"type":33,"tag":95,"props":393,"children":394},{"style":108},[395],{"type":38,"value":396}," events e ",{"type":33,"tag":95,"props":398,"children":399},{"style":102},[400],{"type":38,"value":401},"ON",{"type":33,"tag":95,"props":403,"children":404},{"style":138},[405],{"type":38,"value":406}," c",{"type":33,"tag":95,"props":408,"children":409},{"style":108},[410],{"type":38,"value":245},{"type":33,"tag":95,"props":412,"children":413},{"style":138},[414],{"type":38,"value":66},{"type":33,"tag":95,"props":416,"children":417},{"style":102},[418],{"type":38,"value":419}," =",{"type":33,"tag":95,"props":421,"children":422},{"style":138},[423],{"type":38,"value":348},{"type":33,"tag":95,"props":425,"children":426},{"style":108},[427],{"type":38,"value":245},{"type":33,"tag":95,"props":429,"children":430},{"style":138},[431],{"type":38,"value":432},"user_id\n",{"type":33,"tag":95,"props":434,"children":436},{"class":97,"line":435},13,[437,441,446,450],{"type":33,"tag":95,"props":438,"children":439},{"style":102},[440],{"type":38,"value":188},{"type":33,"tag":95,"props":442,"children":443},{"style":138},[444],{"type":38,"value":445}," 1",{"type":33,"tag":95,"props":447,"children":448},{"style":108},[449],{"type":38,"value":68},{"type":33,"tag":95,"props":451,"children":452},{"style":138},[453],{"type":38,"value":454},"2\n",{"type":33,"tag":95,"props":456,"children":458},{"class":97,"line":457},14,[459],{"type":33,"tag":95,"props":460,"children":461},{"style":108},[462],{"type":38,"value":463},")\n",{"type":33,"tag":95,"props":465,"children":467},{"class":97,"line":466},15,[468,473,478,483,488,493,497,501,506],{"type":33,"tag":95,"props":469,"children":470},{"style":102},[471],{"type":38,"value":472},"SELECT",{"type":33,"tag":95,"props":474,"children":475},{"style":102},[476],{"type":38,"value":477}," *",{"type":33,"tag":95,"props":479,"children":480},{"style":102},[481],{"type":38,"value":482}," FROM",{"type":33,"tag":95,"props":484,"children":485},{"style":102},[486],{"type":38,"value":487}," retention",{"type":33,"tag":95,"props":489,"children":490},{"style":102},[491],{"type":38,"value":492}," ORDER BY",{"type":33,"tag":95,"props":494,"children":495},{"style":138},[496],{"type":38,"value":445},{"type":33,"tag":95,"props":498,"children":499},{"style":108},[500],{"type":38,"value":68},{"type":33,"tag":95,"props":502,"children":503},{"style":138},[504],{"type":38,"value":505},"2",{"type":33,"tag":95,"props":507,"children":508},{"style":108},[509],{"type":38,"value":510},";\n",{"type":33,"tag":34,"props":512,"children":513},{},[514,516,522],{"type":38,"value":515},"Cada ejecución de esta consulta lee la tabla completa de ",{"type":33,"tag":41,"props":517,"children":519},{"className":518},[],[520],{"type":38,"value":521},"events",{"type":38,"value":523},". 500M filas × 16 bytes promedio = 8 GB de escaneo. En BigQuery, 1 TB de escaneo cuesta $6.25, entonces 1.000 consultas = $50. Si el dashboard se actualiza cada 5 minutos, son 8.640 consultas al mes = $432 solo para el widget de cohorte. Añade 10 analistas más al equipo, bots de Slack disparan queries, y el costo se dispara.",{"type":33,"tag":34,"props":525,"children":526},{},[527],{"type":38,"value":528},"El problema real ni siquiera es el costo — es la latencia. Un JOIN con 500M filas tarda 15-30 segundos. El usuario cambia un filtro en el dashboard y espera 20 segundos por nuevos datos de cohorte. El análisis de retención no puede ser iterativo con esa demora.",{"type":33,"tag":530,"props":531,"children":533},"h3",{"id":532},"materialized-view-es-un-primer-paso-pero-insuficiente",[534],{"type":38,"value":535},"Materialized View es un Primer Paso, Pero Insuficiente",{"type":33,"tag":34,"props":537,"children":538},{},[539],{"type":38,"value":540},"Una materialized view de BigQuery precomputa la consulta de cohorte:",{"type":33,"tag":85,"props":542,"children":544},{"className":87,"code":543,"language":89,"meta":17,"style":17},"CREATE MATERIALIZED VIEW cohort_retention AS\nSELECT \n  cohort_week,\n  weeks_since_cohort,\n  active_users\nFROM retention; -- resultado del CTE anterior\n",[545],{"type":33,"tag":41,"props":546,"children":547},{"__ignoreMap":17},[548,566,577,585,593,601],{"type":33,"tag":95,"props":549,"children":550},{"class":97,"line":98},[551,556,561],{"type":33,"tag":95,"props":552,"children":553},{"style":102},[554],{"type":38,"value":555},"CREATE",{"type":33,"tag":95,"props":557,"children":558},{"style":108},[559],{"type":38,"value":560}," MATERIALIZED VIEW cohort_retention ",{"type":33,"tag":95,"props":562,"children":563},{"style":102},[564],{"type":38,"value":565},"AS\n",{"type":33,"tag":95,"props":567,"children":568},{"class":97,"line":124},[569,573],{"type":33,"tag":95,"props":570,"children":571},{"style":102},[572],{"type":38,"value":472},{"type":33,"tag":95,"props":574,"children":575},{"style":108},[576],{"type":38,"value":232},{"type":33,"tag":95,"props":578,"children":579},{"class":97,"line":168},[580],{"type":33,"tag":95,"props":581,"children":582},{"style":108},[583],{"type":38,"value":584},"  cohort_week,\n",{"type":33,"tag":95,"props":586,"children":587},{"class":97,"line":182},[588],{"type":33,"tag":95,"props":589,"children":590},{"style":108},[591],{"type":38,"value":592},"  weeks_since_cohort,\n",{"type":33,"tag":95,"props":594,"children":595},{"class":97,"line":196},[596],{"type":33,"tag":95,"props":597,"children":598},{"style":108},[599],{"type":38,"value":600},"  active_users\n",{"type":33,"tag":95,"props":602,"children":603},{"class":97,"line":205},[604,609,613,618],{"type":33,"tag":95,"props":605,"children":606},{"style":102},[607],{"type":38,"value":608},"FROM",{"type":33,"tag":95,"props":610,"children":611},{"style":102},[612],{"type":38,"value":487},{"type":33,"tag":95,"props":614,"children":615},{"style":108},[616],{"type":38,"value":617},"; ",{"type":33,"tag":95,"props":619,"children":621},{"style":620},"--shiki-default:#6A737D",[622],{"type":38,"value":623},"-- resultado del CTE anterior\n",{"type":33,"tag":34,"props":625,"children":626},{},[627,629,635,637,642],{"type":38,"value":628},"Ahora el dashboard lee la tabla ",{"type":33,"tag":41,"props":630,"children":632},{"className":631},[],[633],{"type":38,"value":634},"cohort_retention",{"type":38,"value":636},", no ",{"type":33,"tag":41,"props":638,"children":640},{"className":639},[],[641],{"type":38,"value":521},{"type":38,"value":643},". El escaneo es 8 GB en lugar de 80 MB. La latencia es 800 ms en lugar de 20 segundos. Pero hay dos limitaciones:",{"type":33,"tag":645,"props":646,"children":647},"ol",{},[648,660],{"type":33,"tag":649,"props":650,"children":651},"li",{},[652,658],{"type":33,"tag":653,"props":654,"children":655},"strong",{},[656],{"type":38,"value":657},"Costo de actualización:",{"type":38,"value":659}," Cada refresh de la materialized view ejecuta la consulta base nuevamente. Es decir, otro escaneo de 8 GB. Si actualizas la view cada hora, 24 × 8 GB = 192 GB\u002Fdía = 5,8 TB al mes. El costo no bajó, solo la latencia.",{"type":33,"tag":649,"props":661,"children":662},{},[663,668],{"type":33,"tag":653,"props":664,"children":665},{},[666],{"type":38,"value":667},"Falta de flexibilidad:",{"type":38,"value":669}," La materialized view es estática. El usuario añade un filtro \"retención de cohorte Android\", la view necesita recalcularse. No puedes prefiltrarlo porque modificar la consulta requiere recrear la view.",{"type":33,"tag":34,"props":671,"children":672},{},[673],{"type":38,"value":674},"Por eso la arquitectura de cohorte debe ser de tres capas: logs de eventos sin procesar → tabla de asignación de cohorte → tabla de retención agregada.",{"type":33,"tag":50,"props":676,"children":678},{"id":677},"separar-la-tabla-de-asignación-de-cohorte",[679],{"type":38,"value":680},"Separar la Tabla de Asignación de Cohorte",{"type":33,"tag":34,"props":682,"children":683},{},[684,686,691,693,698],{"type":38,"value":685},"El primer paso: crear una tabla separada que asigne cada usuario a su cohorte. Esta tabla contiene solo ",{"type":33,"tag":41,"props":687,"children":689},{"className":688},[],[690],{"type":38,"value":66},{"type":38,"value":692}," y ",{"type":33,"tag":41,"props":694,"children":696},{"className":695},[],[697],{"type":38,"value":250},{"type":38,"value":699},", derivada del log de eventos pero calculada una vez al día:",{"type":33,"tag":85,"props":701,"children":703},{"className":87,"code":702,"language":89,"meta":17,"style":17},"CREATE OR REPLACE TABLE cohort_assignments\nPARTITION BY cohort_week\nCLUSTER BY user_id\nAS\nSELECT \n  user_id,\n  DATE_TRUNC(MIN(event_time), WEEK) AS cohort_week,\n  MIN(event_time) AS first_seen_at\nFROM events\nWHERE event_time >= '2024-01-01'\nGROUP BY user_id;\n",[704],{"type":33,"tag":41,"props":705,"children":706},{"__ignoreMap":17},[707,726,743,760,767,778,786,819,841,852,876],{"type":33,"tag":95,"props":708,"children":709},{"class":97,"line":98},[710,715,720],{"type":33,"tag":95,"props":711,"children":712},{"style":102},[713],{"type":38,"value":714},"CREATE OR REPLACE",{"type":33,"tag":95,"props":716,"children":717},{"style":102},[718],{"type":38,"value":719}," TABLE",{"type":33,"tag":95,"props":721,"children":723},{"style":722},"--shiki-default:#B392F0",[724],{"type":38,"value":725}," cohort_assignments\n",{"type":33,"tag":95,"props":727,"children":728},{"class":97,"line":124},[729,734,739],{"type":33,"tag":95,"props":730,"children":731},{"style":102},[732],{"type":38,"value":733},"PARTITION",{"type":33,"tag":95,"props":735,"children":736},{"style":102},[737],{"type":38,"value":738}," BY",{"type":33,"tag":95,"props":740,"children":741},{"style":108},[742],{"type":38,"value":165},{"type":33,"tag":95,"props":744,"children":745},{"class":97,"line":168},[746,751,756],{"type":33,"tag":95,"props":747,"children":748},{"style":108},[749],{"type":38,"value":750},"CLUSTER ",{"type":33,"tag":95,"props":752,"children":753},{"style":102},[754],{"type":38,"value":755},"BY",{"type":33,"tag":95,"props":757,"children":758},{"style":108},[759],{"type":38,"value":193},{"type":33,"tag":95,"props":761,"children":762},{"class":97,"line":182},[763],{"type":33,"tag":95,"props":764,"children":765},{"style":102},[766],{"type":38,"value":565},{"type":33,"tag":95,"props":768,"children":769},{"class":97,"line":196},[770,774],{"type":33,"tag":95,"props":771,"children":772},{"style":102},[773],{"type":38,"value":472},{"type":33,"tag":95,"props":775,"children":776},{"style":108},[777],{"type":38,"value":232},{"type":33,"tag":95,"props":779,"children":780},{"class":97,"line":205},[781],{"type":33,"tag":95,"props":782,"children":783},{"style":108},[784],{"type":38,"value":785},"  user_id,\n",{"type":33,"tag":95,"props":787,"children":788},{"class":97,"line":222},[789,794,798,802,806,810,814],{"type":33,"tag":95,"props":790,"children":791},{"style":108},[792],{"type":38,"value":793},"  DATE_TRUNC(",{"type":33,"tag":95,"props":795,"children":796},{"style":138},[797],{"type":38,"value":141},{"type":33,"tag":95,"props":799,"children":800},{"style":108},[801],{"type":38,"value":146},{"type":33,"tag":95,"props":803,"children":804},{"style":102},[805],{"type":38,"value":151},{"type":33,"tag":95,"props":807,"children":808},{"style":108},[809],{"type":38,"value":156},{"type":33,"tag":95,"props":811,"children":812},{"style":102},[813],{"type":38,"value":116},{"type":33,"tag":95,"props":815,"children":816},{"style":108},[817],{"type":38,"value":818}," cohort_week,\n",{"type":33,"tag":95,"props":820,"children":821},{"class":97,"line":27},[822,827,832,836],{"type":33,"tag":95,"props":823,"children":824},{"style":138},[825],{"type":38,"value":826},"  MIN",{"type":33,"tag":95,"props":828,"children":829},{"style":108},[830],{"type":38,"value":831},"(event_time) ",{"type":33,"tag":95,"props":833,"children":834},{"style":102},[835],{"type":38,"value":116},{"type":33,"tag":95,"props":837,"children":838},{"style":108},[839],{"type":38,"value":840}," first_seen_at\n",{"type":33,"tag":95,"props":842,"children":843},{"class":97,"line":258},[844,848],{"type":33,"tag":95,"props":845,"children":846},{"style":102},[847],{"type":38,"value":608},{"type":33,"tag":95,"props":849,"children":850},{"style":108},[851],{"type":38,"value":179},{"type":33,"tag":95,"props":853,"children":854},{"class":97,"line":327},[855,860,865,870],{"type":33,"tag":95,"props":856,"children":857},{"style":102},[858],{"type":38,"value":859},"WHERE",{"type":33,"tag":95,"props":861,"children":862},{"style":108},[863],{"type":38,"value":864}," event_time ",{"type":33,"tag":95,"props":866,"children":867},{"style":102},[868],{"type":38,"value":869},">=",{"type":33,"tag":95,"props":871,"children":873},{"style":872},"--shiki-default:#9ECBFF",[874],{"type":38,"value":875}," '2024-01-01'\n",{"type":33,"tag":95,"props":877,"children":878},{"class":97,"line":372},[879,884],{"type":33,"tag":95,"props":880,"children":881},{"style":102},[882],{"type":38,"value":883},"GROUP BY",{"type":33,"tag":95,"props":885,"children":886},{"style":108},[887],{"type":38,"value":888}," user_id;\n",{"type":33,"tag":34,"props":890,"children":891},{},[892],{"type":38,"value":893},"Esta tabla:",{"type":33,"tag":895,"props":896,"children":897},"ul",{},[898,916,926],{"type":33,"tag":649,"props":899,"children":900},{},[901,906,908,914],{"type":33,"tag":653,"props":902,"children":903},{},[904],{"type":38,"value":905},"Particionada por cohort_week:",{"type":38,"value":907}," BigQuery crea bloques de archivo separados para cada semana. Un filtro como ",{"type":33,"tag":41,"props":909,"children":911},{"className":910},[],[912],{"type":38,"value":913},"WHERE cohort_week = '2026-01-05'",{"type":38,"value":915}," lee solo 1 partición.",{"type":33,"tag":649,"props":917,"children":918},{},[919,924],{"type":33,"tag":653,"props":920,"children":921},{},[922],{"type":38,"value":923},"Agrupada por user_id:",{"type":38,"value":925}," Dentro de cada partición, el almacenamiento se ordena por user_id. Los JOINs se aceleran.",{"type":33,"tag":649,"props":927,"children":928},{},[929,934],{"type":33,"tag":653,"props":930,"children":931},{},[932],{"type":38,"value":933},"Tamaño:",{"type":38,"value":935}," 50M usuarios × 3 columnas × 16 bytes = ~2,4 GB. Si el log de eventos es 500 GB, la tabla de cohorte es 200× más pequeña.",{"type":33,"tag":34,"props":937,"children":938},{},[939],{"type":38,"value":940},"Ahora la consulta de retención usa esta tabla:",{"type":33,"tag":85,"props":942,"children":944},{"className":87,"code":943,"language":89,"meta":17,"style":17},"SELECT \n  c.cohort_week,\n  DATE_DIFF(DATE_TRUNC(e.event_time, WEEK), c.cohort_week, WEEK) AS weeks_since,\n  COUNT(DISTINCT e.user_id) AS active_users\nFROM cohort_assignments c\nJOIN events e ON c.user_id = e.user_id\nWHERE c.cohort_week >= '2026-01-01'\nGROUP BY 1, 2;\n",[945],{"type":33,"tag":41,"props":946,"children":947},{"__ignoreMap":17},[948,959,979,1044,1084,1096,1140,1169],{"type":33,"tag":95,"props":949,"children":950},{"class":97,"line":98},[951,955],{"type":33,"tag":95,"props":952,"children":953},{"style":102},[954],{"type":38,"value":472},{"type":33,"tag":95,"props":956,"children":957},{"style":108},[958],{"type":38,"value":232},{"type":33,"tag":95,"props":960,"children":961},{"class":97,"line":124},[962,967,971,975],{"type":33,"tag":95,"props":963,"children":964},{"style":138},[965],{"type":38,"value":966},"  c",{"type":33,"tag":95,"props":968,"children":969},{"style":108},[970],{"type":38,"value":245},{"type":33,"tag":95,"props":972,"children":973},{"style":138},[974],{"type":38,"value":250},{"type":33,"tag":95,"props":976,"children":977},{"style":108},[978],{"type":38,"value":255},{"type":33,"tag":95,"props":980,"children":981},{"class":97,"line":168},[982,987,991,995,999,1003,1007,1011,1015,1019,1023,1027,1031,1035,1039],{"type":33,"tag":95,"props":983,"children":984},{"style":108},[985],{"type":38,"value":986},"  DATE_DIFF(DATE_TRUNC(",{"type":33,"tag":95,"props":988,"children":989},{"style":138},[990],{"type":38,"value":269},{"type":33,"tag":95,"props":992,"children":993},{"style":108},[994],{"type":38,"value":245},{"type":33,"tag":95,"props":996,"children":997},{"style":138},[998],{"type":38,"value":74},{"type":33,"tag":95,"props":1000,"children":1001},{"style":108},[1002],{"type":38,"value":68},{"type":33,"tag":95,"props":1004,"children":1005},{"style":102},[1006],{"type":38,"value":151},{"type":33,"tag":95,"props":1008,"children":1009},{"style":108},[1010],{"type":38,"value":290},{"type":33,"tag":95,"props":1012,"children":1013},{"style":138},[1014],{"type":38,"value":295},{"type":33,"tag":95,"props":1016,"children":1017},{"style":108},[1018],{"type":38,"value":245},{"type":33,"tag":95,"props":1020,"children":1021},{"style":138},[1022],{"type":38,"value":250},{"type":33,"tag":95,"props":1024,"children":1025},{"style":108},[1026],{"type":38,"value":68},{"type":33,"tag":95,"props":1028,"children":1029},{"style":102},[1030],{"type":38,"value":151},{"type":33,"tag":95,"props":1032,"children":1033},{"style":108},[1034],{"type":38,"value":156},{"type":33,"tag":95,"props":1036,"children":1037},{"style":102},[1038],{"type":38,"value":116},{"type":33,"tag":95,"props":1040,"children":1041},{"style":108},[1042],{"type":38,"value":1043}," weeks_since,\n",{"type":33,"tag":95,"props":1045,"children":1046},{"class":97,"line":182},[1047,1052,1056,1060,1064,1068,1072,1076,1080],{"type":33,"tag":95,"props":1048,"children":1049},{"style":138},[1050],{"type":38,"value":1051},"  COUNT",{"type":33,"tag":95,"props":1053,"children":1054},{"style":108},[1055],{"type":38,"value":338},{"type":33,"tag":95,"props":1057,"children":1058},{"style":102},[1059],{"type":38,"value":343},{"type":33,"tag":95,"props":1061,"children":1062},{"style":138},[1063],{"type":38,"value":348},{"type":33,"tag":95,"props":1065,"children":1066},{"style":108},[1067],{"type":38,"value":245},{"type":33,"tag":95,"props":1069,"children":1070},{"style":138},[1071],{"type":38,"value":66},{"type":33,"tag":95,"props":1073,"children":1074},{"style":108},[1075],{"type":38,"value":156},{"type":33,"tag":95,"props":1077,"children":1078},{"style":102},[1079],{"type":38,"value":116},{"type":33,"tag":95,"props":1081,"children":1082},{"style":108},[1083],{"type":38,"value":369},{"type":33,"tag":95,"props":1085,"children":1086},{"class":97,"line":196},[1087,1091],{"type":33,"tag":95,"props":1088,"children":1089},{"style":102},[1090],{"type":38,"value":608},{"type":33,"tag":95,"props":1092,"children":1093},{"style":108},[1094],{"type":38,"value":1095}," cohort_assignments c\n",{"type":33,"tag":95,"props":1097,"children":1098},{"class":97,"line":205},[1099,1104,1108,1112,1116,1120,1124,1128,1132,1136],{"type":33,"tag":95,"props":1100,"children":1101},{"style":102},[1102],{"type":38,"value":1103},"JOIN",{"type":33,"tag":95,"props":1105,"children":1106},{"style":108},[1107],{"type":38,"value":396},{"type":33,"tag":95,"props":1109,"children":1110},{"style":102},[1111],{"type":38,"value":401},{"type":33,"tag":95,"props":1113,"children":1114},{"style":138},[1115],{"type":38,"value":406},{"type":33,"tag":95,"props":1117,"children":1118},{"style":108},[1119],{"type":38,"value":245},{"type":33,"tag":95,"props":1121,"children":1122},{"style":138},[1123],{"type":38,"value":66},{"type":33,"tag":95,"props":1125,"children":1126},{"style":102},[1127],{"type":38,"value":419},{"type":33,"tag":95,"props":1129,"children":1130},{"style":138},[1131],{"type":38,"value":348},{"type":33,"tag":95,"props":1133,"children":1134},{"style":108},[1135],{"type":38,"value":245},{"type":33,"tag":95,"props":1137,"children":1138},{"style":138},[1139],{"type":38,"value":432},{"type":33,"tag":95,"props":1141,"children":1142},{"class":97,"line":222},[1143,1147,1151,1155,1159,1164],{"type":33,"tag":95,"props":1144,"children":1145},{"style":102},[1146],{"type":38,"value":859},{"type":33,"tag":95,"props":1148,"children":1149},{"style":138},[1150],{"type":38,"value":406},{"type":33,"tag":95,"props":1152,"children":1153},{"style":108},[1154],{"type":38,"value":245},{"type":33,"tag":95,"props":1156,"children":1157},{"style":138},[1158],{"type":38,"value":250},{"type":33,"tag":95,"props":1160,"children":1161},{"style":102},[1162],{"type":38,"value":1163}," >=",{"type":33,"tag":95,"props":1165,"children":1166},{"style":872},[1167],{"type":38,"value":1168}," '2026-01-01'\n",{"type":33,"tag":95,"props":1170,"children":1171},{"class":97,"line":27},[1172,1176,1180,1184,1188],{"type":33,"tag":95,"props":1173,"children":1174},{"style":102},[1175],{"type":38,"value":883},{"type":33,"tag":95,"props":1177,"children":1178},{"style":138},[1179],{"type":38,"value":445},{"type":33,"tag":95,"props":1181,"children":1182},{"style":108},[1183],{"type":38,"value":68},{"type":33,"tag":95,"props":1185,"children":1186},{"style":138},[1187],{"type":38,"value":505},{"type":33,"tag":95,"props":1189,"children":1190},{"style":108},[1191],{"type":38,"value":510},{"type":33,"tag":34,"props":1193,"children":1194},{},[1195,1197,1203,1205,1210],{"type":38,"value":1196},"Con partition pruning en ",{"type":33,"tag":41,"props":1198,"children":1200},{"className":1199},[],[1201],{"type":38,"value":1202},"cohort_assignments",{"type":38,"value":1204},", si lees 4 semanas de datos, el escaneo es 200 MB. El JOIN todavía escanea la tabla completa de ",{"type":33,"tag":41,"props":1206,"children":1208},{"className":1207},[],[1209],{"type":38,"value":521},{"type":38,"value":1211},", pero comienza en un estado filtrado — no hay usuarios innecesarios.",{"type":33,"tag":530,"props":1213,"children":1215},{"id":1214},"actualización-incremental",[1216],{"type":38,"value":1217},"Actualización Incremental",{"type":33,"tag":34,"props":1219,"children":1220},{},[1221,1223,1228],{"type":38,"value":1222},"La tabla ",{"type":33,"tag":41,"props":1224,"children":1226},{"className":1225},[],[1227],{"type":38,"value":1202},{"type":38,"value":1229}," se actualiza diariamente, pero no se recalcula desde cero cada vez. Usa un modelo incremental de dbt:",{"type":33,"tag":85,"props":1231,"children":1233},{"className":87,"code":1232,"language":89,"meta":17,"style":17},"{{\n  config(\n    materialized='incremental',\n    partition_by={'field': 'cohort_week', 'data_type': 'date'},\n    cluster_by=['user_id']\n  )\n}}\n\nSELECT \n  user_id,\n  DATE_TRUNC(MIN(event_time), WEEK) AS cohort_week,\n  MIN(event_time) AS first_seen_at\nFROM {{ ref('events') }}\n{% if is_incremental() %}\n  WHERE event_time > (SELECT MAX(first_seen_at) FROM {{ this }})\n{% endif %}\nGROUP BY user_id\n",[1234],{"type":33,"tag":41,"props":1235,"children":1236},{"__ignoreMap":17},[1237,1245,1253,1275,1330,1347,1355,1363,1372,1383,1390,1421,1440,1462,1480,1525,1534],{"type":33,"tag":95,"props":1238,"children":1239},{"class":97,"line":98},[1240],{"type":33,"tag":95,"props":1241,"children":1242},{"style":108},[1243],{"type":38,"value":1244},"{{\n",{"type":33,"tag":95,"props":1246,"children":1247},{"class":97,"line":124},[1248],{"type":33,"tag":95,"props":1249,"children":1250},{"style":108},[1251],{"type":38,"value":1252},"  config(\n",{"type":33,"tag":95,"props":1254,"children":1255},{"class":97,"line":168},[1256,1261,1266,1271],{"type":33,"tag":95,"props":1257,"children":1258},{"style":108},[1259],{"type":38,"value":1260},"    materialized",{"type":33,"tag":95,"props":1262,"children":1263},{"style":102},[1264],{"type":38,"value":1265},"=",{"type":33,"tag":95,"props":1267,"children":1268},{"style":872},[1269],{"type":38,"value":1270},"'incremental'",{"type":33,"tag":95,"props":1272,"children":1273},{"style":108},[1274],{"type":38,"value":255},{"type":33,"tag":95,"props":1276,"children":1277},{"class":97,"line":182},[1278,1283,1287,1292,1297,1302,1307,1311,1316,1320,1325],{"type":33,"tag":95,"props":1279,"children":1280},{"style":108},[1281],{"type":38,"value":1282},"    partition_by",{"type":33,"tag":95,"props":1284,"children":1285},{"style":102},[1286],{"type":38,"value":1265},{"type":33,"tag":95,"props":1288,"children":1289},{"style":108},[1290],{"type":38,"value":1291},"{",{"type":33,"tag":95,"props":1293,"children":1294},{"style":872},[1295],{"type":38,"value":1296},"'field'",{"type":33,"tag":95,"props":1298,"children":1299},{"style":108},[1300],{"type":38,"value":1301},": ",{"type":33,"tag":95,"props":1303,"children":1304},{"style":872},[1305],{"type":38,"value":1306},"'cohort_week'",{"type":33,"tag":95,"props":1308,"children":1309},{"style":108},[1310],{"type":38,"value":68},{"type":33,"tag":95,"props":1312,"children":1313},{"style":872},[1314],{"type":38,"value":1315},"'data_type'",{"type":33,"tag":95,"props":1317,"children":1318},{"style":108},[1319],{"type":38,"value":1301},{"type":33,"tag":95,"props":1321,"children":1322},{"style":872},[1323],{"type":38,"value":1324},"'date'",{"type":33,"tag":95,"props":1326,"children":1327},{"style":108},[1328],{"type":38,"value":1329},"},\n",{"type":33,"tag":95,"props":1331,"children":1332},{"class":97,"line":196},[1333,1338,1342],{"type":33,"tag":95,"props":1334,"children":1335},{"style":108},[1336],{"type":38,"value":1337},"    cluster_by",{"type":33,"tag":95,"props":1339,"children":1340},{"style":102},[1341],{"type":38,"value":1265},{"type":33,"tag":95,"props":1343,"children":1344},{"style":108},[1345],{"type":38,"value":1346},"['user_id']\n",{"type":33,"tag":95,"props":1348,"children":1349},{"class":97,"line":205},[1350],{"type":33,"tag":95,"props":1351,"children":1352},{"style":108},[1353],{"type":38,"value":1354},"  )\n",{"type":33,"tag":95,"props":1356,"children":1357},{"class":97,"line":222},[1358],{"type":33,"tag":95,"props":1359,"children":1360},{"style":108},[1361],{"type":38,"value":1362},"}}\n",{"type":33,"tag":95,"props":1364,"children":1365},{"class":97,"line":27},[1366],{"type":33,"tag":95,"props":1367,"children":1369},{"emptyLinePlaceholder":1368},true,[1370],{"type":38,"value":1371},"\n",{"type":33,"tag":95,"props":1373,"children":1374},{"class":97,"line":258},[1375,1379],{"type":33,"tag":95,"props":1376,"children":1377},{"style":102},[1378],{"type":38,"value":472},{"type":33,"tag":95,"props":1380,"children":1381},{"style":108},[1382],{"type":38,"value":232},{"type":33,"tag":95,"props":1384,"children":1385},{"class":97,"line":327},[1386],{"type":33,"tag":95,"props":1387,"children":1388},{"style":108},[1389],{"type":38,"value":785},{"type":33,"tag":95,"props":1391,"children":1392},{"class":97,"line":372},[1393,1397,1401,1405,1409,1413,1417],{"type":33,"tag":95,"props":1394,"children":1395},{"style":108},[1396],{"type":38,"value":793},{"type":33,"tag":95,"props":1398,"children":1399},{"style":138},[1400],{"type":38,"value":141},{"type":33,"tag":95,"props":1402,"children":1403},{"style":108},[1404],{"type":38,"value":146},{"type":33,"tag":95,"props":1406,"children":1407},{"style":102},[1408],{"type":38,"value":151},{"type":33,"tag":95,"props":1410,"children":1411},{"style":108},[1412],{"type":38,"value":156},{"type":33,"tag":95,"props":1414,"children":1415},{"style":102},[1416],{"type":38,"value":116},{"type":33,"tag":95,"props":1418,"children":1419},{"style":108},[1420],{"type":38,"value":818},{"type":33,"tag":95,"props":1422,"children":1423},{"class":97,"line":385},[1424,1428,1432,1436],{"type":33,"tag":95,"props":1425,"children":1426},{"style":138},[1427],{"type":38,"value":826},{"type":33,"tag":95,"props":1429,"children":1430},{"style":108},[1431],{"type":38,"value":831},{"type":33,"tag":95,"props":1433,"children":1434},{"style":102},[1435],{"type":38,"value":116},{"type":33,"tag":95,"props":1437,"children":1438},{"style":108},[1439],{"type":38,"value":840},{"type":33,"tag":95,"props":1441,"children":1442},{"class":97,"line":435},[1443,1447,1452,1457],{"type":33,"tag":95,"props":1444,"children":1445},{"style":102},[1446],{"type":38,"value":608},{"type":33,"tag":95,"props":1448,"children":1449},{"style":108},[1450],{"type":38,"value":1451}," {{ ref(",{"type":33,"tag":95,"props":1453,"children":1454},{"style":872},[1455],{"type":38,"value":1456},"'events'",{"type":33,"tag":95,"props":1458,"children":1459},{"style":108},[1460],{"type":38,"value":1461},") }}\n",{"type":33,"tag":95,"props":1463,"children":1464},{"class":97,"line":457},[1465,1470,1475],{"type":33,"tag":95,"props":1466,"children":1467},{"style":108},[1468],{"type":38,"value":1469},"{% ",{"type":33,"tag":95,"props":1471,"children":1472},{"style":102},[1473],{"type":38,"value":1474},"if",{"type":33,"tag":95,"props":1476,"children":1477},{"style":108},[1478],{"type":38,"value":1479}," is_incremental() %}\n",{"type":33,"tag":95,"props":1481,"children":1482},{"class":97,"line":466},[1483,1488,1492,1497,1502,1506,1511,1516,1520],{"type":33,"tag":95,"props":1484,"children":1485},{"style":102},[1486],{"type":38,"value":1487},"  WHERE",{"type":33,"tag":95,"props":1489,"children":1490},{"style":108},[1491],{"type":38,"value":864},{"type":33,"tag":95,"props":1493,"children":1494},{"style":102},[1495],{"type":38,"value":1496},">",{"type":33,"tag":95,"props":1498,"children":1499},{"style":108},[1500],{"type":38,"value":1501}," (",{"type":33,"tag":95,"props":1503,"children":1504},{"style":102},[1505],{"type":38,"value":472},{"type":33,"tag":95,"props":1507,"children":1508},{"style":138},[1509],{"type":38,"value":1510}," MAX",{"type":33,"tag":95,"props":1512,"children":1513},{"style":108},[1514],{"type":38,"value":1515},"(first_seen_at) ",{"type":33,"tag":95,"props":1517,"children":1518},{"style":102},[1519],{"type":38,"value":608},{"type":33,"tag":95,"props":1521,"children":1522},{"style":108},[1523],{"type":38,"value":1524}," {{ this }})\n",{"type":33,"tag":95,"props":1526,"children":1528},{"class":97,"line":1527},16,[1529],{"type":33,"tag":95,"props":1530,"children":1531},{"style":108},[1532],{"type":38,"value":1533},"{% endif %}\n",{"type":33,"tag":95,"props":1535,"children":1537},{"class":97,"line":1536},17,[1538,1542],{"type":33,"tag":95,"props":1539,"children":1540},{"style":102},[1541],{"type":38,"value":883},{"type":33,"tag":95,"props":1543,"children":1544},{"style":108},[1545],{"type":38,"value":193},{"type":33,"tag":34,"props":1547,"children":1548},{},[1549],{"type":38,"value":1550},"Este modelo procesa todos los datos en la primera ejecución, después solo añade usuarios nuevos. El escaneo es 500 GB inicialmente, luego 2 GB diarios.",{"type":33,"tag":50,"props":1552,"children":1554},{"id":1553},"tabla-de-retención-agregada-precomputar-métricas-a-nivel-semanal",[1555],{"type":38,"value":1556},"Tabla de Retención Agregada: Precomputar Métricas a Nivel Semanal",{"type":33,"tag":34,"props":1558,"children":1559},{},[1560,1562,1567],{"type":38,"value":1561},"La tabla de asignación de cohorte aceleró la consulta de retención, pero el dashboard aún ejecuta un JOIN contra ",{"type":33,"tag":41,"props":1563,"children":1565},{"className":1564},[],[1566],{"type":38,"value":521},{"type":38,"value":1568}," cada solicitud. Un paso más: precomputa las métricas de retención semanalmente y guárdalas en una tabla separada.",{"type":33,"tag":85,"props":1570,"children":1572},{"className":87,"code":1571,"language":89,"meta":17,"style":17},"CREATE TABLE cohort_retention_weekly\nPARTITION BY cohort_week\nCLUSTER BY weeks_since_cohort\nAS\nSELECT \n  c.cohort_week,\n  DATE_DIFF(DATE_TRUNC(e.event_time, WEEK), c.cohort_week, WEEK) AS weeks_since_cohort,\n  COUNT(DISTINCT e.user_id) AS active_users,\n  COUNT(*) AS total_events,\n  APPROX_QUANTILES(session_duration, 100)[OFFSET(50)] AS median_session_duration\nFROM cohort_assignments c\nJOIN events e ON c.user_id = e.user_id\nGROUP BY 1, 2;\n",[1573],{"type":33,"tag":41,"props":1574,"children":1575},{"__ignoreMap":17},[1576,1592,1607,1623,1630,1641,1660,1723,1763,1792,1819,1830,1873],{"type":33,"tag":95,"props":1577,"children":1578},{"class":97,"line":98},[1579,1583,1587],{"type":33,"tag":95,"props":1580,"children":1581},{"style":102},[1582],{"type":38,"value":555},{"type":33,"tag":95,"props":1584,"children":1585},{"style":102},[1586],{"type":38,"value":719},{"type":33,"tag":95,"props":1588,"children":1589},{"style":722},[1590],{"type":38,"value":1591}," cohort_retention_weekly\n",{"type":33,"tag":95,"props":1593,"children":1594},{"class":97,"line":124},[1595,1599,1603],{"type":33,"tag":95,"props":1596,"children":1597},{"style":102},[1598],{"type":38,"value":733},{"type":33,"tag":95,"props":1600,"children":1601},{"style":102},[1602],{"type":38,"value":738},{"type":33,"tag":95,"props":1604,"children":1605},{"style":108},[1606],{"type":38,"value":165},{"type":33,"tag":95,"props":1608,"children":1609},{"class":97,"line":168},[1610,1614,1618],{"type":33,"tag":95,"props":1611,"children":1612},{"style":108},[1613],{"type":38,"value":750},{"type":33,"tag":95,"props":1615,"children":1616},{"style":102},[1617],{"type":38,"value":755},{"type":33,"tag":95,"props":1619,"children":1620},{"style":108},[1621],{"type":38,"value":1622}," weeks_since_cohort\n",{"type":33,"tag":95,"props":1624,"children":1625},{"class":97,"line":182},[1626],{"type":33,"tag":95,"props":1627,"children":1628},{"style":102},[1629],{"type":38,"value":565},{"type":33,"tag":95,"props":1631,"children":1632},{"class":97,"line":196},[1633,1637],{"type":33,"tag":95,"props":1634,"children":1635},{"style":102},[1636],{"type":38,"value":472},{"type":33,"tag":95,"props":1638,"children":1639},{"style":108},[1640],{"type":38,"value":232},{"type":33,"tag":95,"props":1642,"children":1643},{"class":97,"line":205},[1644,1648,1652,1656],{"type":33,"tag":95,"props":1645,"children":1646},{"style":138},[1647],{"type":38,"value":966},{"type":33,"tag":95,"props":1649,"children":1650},{"style":108},[1651],{"type":38,"value":245},{"type":33,"tag":95,"props":1653,"children":1654},{"style":138},[1655],{"type":38,"value":250},{"type":33,"tag":95,"props":1657,"children":1658},{"style":108},[1659],{"type":38,"value":255},{"type":33,"tag":95,"props":1661,"children":1662},{"class":97,"line":222},[1663,1667,1671,1675,1679,1683,1687,1691,1695,1699,1703,1707,1711,1715,1719],{"type":33,"tag":95,"props":1664,"children":1665},{"style":108},[1666],{"type":38,"value":986},{"type":33,"tag":95,"props":1668,"children":1669},{"style":138},[1670],{"type":38,"value":269},{"type":33,"tag":95,"props":1672,"children":1673},{"style":108},[1674],{"type":38,"value":245},{"type":33,"tag":95,"props":1676,"children":1677},{"style":138},[1678],{"type":38,"value":74},{"type":33,"tag":95,"props":1680,"children":1681},{"style":108},[1682],{"type":38,"value":68},{"type":33,"tag":95,"props":1684,"children":1685},{"style":102},[1686],{"type":38,"value":151},{"type":33,"tag":95,"props":1688,"children":1689},{"style":108},[1690],{"type":38,"value":290},{"type":33,"tag":95,"props":1692,"children":1693},{"style":138},[1694],{"type":38,"value":295},{"type":33,"tag":95,"props":1696,"children":1697},{"style":108},[1698],{"type":38,"value":245},{"type":33,"tag":95,"props":1700,"children":1701},{"style":138},[1702],{"type":38,"value":250},{"type":33,"tag":95,"props":1704,"children":1705},{"style":108},[1706],{"type":38,"value":68},{"type":33,"tag":95,"props":1708,"children":1709},{"style":102},[1710],{"type":38,"value":151},{"type":33,"tag":95,"props":1712,"children":1713},{"style":108},[1714],{"type":38,"value":156},{"type":33,"tag":95,"props":1716,"children":1717},{"style":102},[1718],{"type":38,"value":116},{"type":33,"tag":95,"props":1720,"children":1721},{"style":108},[1722],{"type":38,"value":324},{"type":33,"tag":95,"props":1724,"children":1725},{"class":97,"line":27},[1726,1730,1734,1738,1742,1746,1750,1754,1758],{"type":33,"tag":95,"props":1727,"children":1728},{"style":138},[1729],{"type":38,"value":1051},{"type":33,"tag":95,"props":1731,"children":1732},{"style":108},[1733],{"type":38,"value":338},{"type":33,"tag":95,"props":1735,"children":1736},{"style":102},[1737],{"type":38,"value":343},{"type":33,"tag":95,"props":1739,"children":1740},{"style":138},[1741],{"type":38,"value":348},{"type":33,"tag":95,"props":1743,"children":1744},{"style":108},[1745],{"type":38,"value":245},{"type":33,"tag":95,"props":1747,"children":1748},{"style":138},[1749],{"type":38,"value":66},{"type":33,"tag":95,"props":1751,"children":1752},{"style":108},[1753],{"type":38,"value":156},{"type":33,"tag":95,"props":1755,"children":1756},{"style":102},[1757],{"type":38,"value":116},{"type":33,"tag":95,"props":1759,"children":1760},{"style":108},[1761],{"type":38,"value":1762}," active_users,\n",{"type":33,"tag":95,"props":1764,"children":1765},{"class":97,"line":258},[1766,1770,1774,1779,1783,1787],{"type":33,"tag":95,"props":1767,"children":1768},{"style":138},[1769],{"type":38,"value":1051},{"type":33,"tag":95,"props":1771,"children":1772},{"style":108},[1773],{"type":38,"value":338},{"type":33,"tag":95,"props":1775,"children":1776},{"style":102},[1777],{"type":38,"value":1778},"*",{"type":33,"tag":95,"props":1780,"children":1781},{"style":108},[1782],{"type":38,"value":156},{"type":33,"tag":95,"props":1784,"children":1785},{"style":102},[1786],{"type":38,"value":116},{"type":33,"tag":95,"props":1788,"children":1789},{"style":108},[1790],{"type":38,"value":1791}," total_events,\n",{"type":33,"tag":95,"props":1793,"children":1794},{"class":97,"line":327},[1795,1800,1805,1810,1814],{"type":33,"tag":95,"props":1796,"children":1797},{"style":108},[1798],{"type":38,"value":1799},"  APPROX_QUANTILES(session_duration, ",{"type":33,"tag":95,"props":1801,"children":1802},{"style":138},[1803],{"type":38,"value":1804},"100",{"type":33,"tag":95,"props":1806,"children":1807},{"style":108},[1808],{"type":38,"value":1809},")[OFFSET(50)] ",{"type":33,"tag":95,"props":1811,"children":1812},{"style":102},[1813],{"type":38,"value":116},{"type":33,"tag":95,"props":1815,"children":1816},{"style":108},[1817],{"type":38,"value":1818}," median_session_duration\n",{"type":33,"tag":95,"props":1820,"children":1821},{"class":97,"line":372},[1822,1826],{"type":33,"tag":95,"props":1823,"children":1824},{"style":102},[1825],{"type":38,"value":608},{"type":33,"tag":95,"props":1827,"children":1828},{"style":108},[1829],{"type":38,"value":1095},{"type":33,"tag":95,"props":1831,"children":1832},{"class":97,"line":385},[1833,1837,1841,1845,1849,1853,1857,1861,1865,1869],{"type":33,"tag":95,"props":1834,"children":1835},{"style":102},[1836],{"type":38,"value":1103},{"type":33,"tag":95,"props":1838,"children":1839},{"style":108},[1840],{"type":38,"value":396},{"type":33,"tag":95,"props":1842,"children":1843},{"style":102},[1844],{"type":38,"value":401},{"type":33,"tag":95,"props":1846,"children":1847},{"style":138},[1848],{"type":38,"value":406},{"type":33,"tag":95,"props":1850,"children":1851},{"style":108},[1852],{"type":38,"value":245},{"type":33,"tag":95,"props":1854,"children":1855},{"style":138},[1856],{"type":38,"value":66},{"type":33,"tag":95,"props":1858,"children":1859},{"style":102},[1860],{"type":38,"value":419},{"type":33,"tag":95,"props":1862,"children":1863},{"style":138},[1864],{"type":38,"value":348},{"type":33,"tag":95,"props":1866,"children":1867},{"style":108},[1868],{"type":38,"value":245},{"type":33,"tag":95,"props":1870,"children":1871},{"style":138},[1872],{"type":38,"value":432},{"type":33,"tag":95,"props":1874,"children":1875},{"class":97,"line":435},[1876,1880,1884,1888,1892],{"type":33,"tag":95,"props":1877,"children":1878},{"style":102},[1879],{"type":38,"value":883},{"type":33,"tag":95,"props":1881,"children":1882},{"style":138},[1883],{"type":38,"value":445},{"type":33,"tag":95,"props":1885,"children":1886},{"style":108},[1887],{"type":38,"value":68},{"type":33,"tag":95,"props":1889,"children":1890},{"style":138},[1891],{"type":38,"value":505},{"type":33,"tag":95,"props":1893,"children":1894},{"style":108},[1895],{"type":38,"value":510},{"type":33,"tag":34,"props":1897,"children":1898},{},[1899],{"type":38,"value":893},{"type":33,"tag":895,"props":1901,"children":1902},{},[1903,1912,1937],{"type":33,"tag":649,"props":1904,"children":1905},{},[1906,1910],{"type":33,"tag":653,"props":1907,"children":1908},{},[1909],{"type":38,"value":933},{"type":38,"value":1911}," 52 semanas × 52 weeks_since × 3 métricas = ~8.100 filas (para datos de 1 año). Nivel de kilobytes.",{"type":33,"tag":649,"props":1913,"children":1914},{},[1915,1920,1922,1928,1930,1935],{"type":33,"tag":653,"props":1916,"children":1917},{},[1918],{"type":38,"value":1919},"Escaneo:",{"type":38,"value":1921}," El dashboard lee ",{"type":33,"tag":41,"props":1923,"children":1925},{"className":1924},[],[1926],{"type":38,"value":1927},"cohort_retention_weekly",{"type":38,"value":1929},", sin leer ",{"type":33,"tag":41,"props":1931,"children":1933},{"className":1932},[],[1934],{"type":38,"value":521},{"type":38,"value":1936},". Escaneo \u003C 1 MB.",{"type":33,"tag":649,"props":1938,"children":1939},{},[1940,1945],{"type":33,"tag":653,"props":1941,"children":1942},{},[1943],{"type":38,"value":1944},"Latencia:",{"type":38,"value":1946}," BigQuery lee 1 MB de datos en 80 ms. El dashboard ahora es sub-segundo.",{"type":33,"tag":34,"props":1948,"children":1949},{},[1950,1952,1958],{"type":38,"value":1951},"El tradeoff: la tabla debe actualizarse una vez al día. Si los datos no actualizado no son aceptables, actualiza cada hora (schedule dbt ",{"type":33,"tag":41,"props":1953,"children":1955},{"className":1954},[],[1956],{"type":38,"value":1957},"0 * * * *",{"type":38,"value":1959},"). El costo de actualización: JOIN de cohort_assignments contra events, ~10 GB de escaneo. 24 veces al día = 240 GB, ~7.2 TB al mes. Comparación: si el dashboard ejecutara 1.000 consultas de cohorte sin tablas preaagregadas, sería 8 TB de escaneo. Así que la tabla agregada reduce el escaneo del dashboard en ~10%, pero la latencia baja de 20 segundos a 80 ms.",{"type":33,"tag":530,"props":1961,"children":1963},{"id":1962},"estrategia-de-particionamiento-cohort_week-vs-event_week",[1964],{"type":38,"value":1965},"Estrategia de Particionamiento: cohort_week vs event_week",{"type":33,"tag":34,"props":1967,"children":1968},{},[1969,1971,1976,1978,1984],{"type":38,"value":1970},"¿Particionar la tabla de retención de cohorte por ",{"type":33,"tag":41,"props":1972,"children":1974},{"className":1973},[],[1975],{"type":38,"value":250},{"type":38,"value":1977}," o por ",{"type":33,"tag":41,"props":1979,"children":1981},{"className":1980},[],[1982],{"type":38,"value":1983},"event_week",{"type":38,"value":1985},"? Hay dos enfoques:",{"type":33,"tag":34,"props":1987,"children":1988},{},[1989],{"type":33,"tag":653,"props":1990,"children":1991},{},[1992],{"type":38,"value":1993},"Particionar por cohort_week:",{"type":33,"tag":895,"props":1995,"children":1996},{},[1997,2002,2015],{"type":33,"tag":649,"props":1998,"children":1999},{},[2000],{"type":38,"value":2001},"Caso de uso: \"¿Cuál es la curva de retención de la cohorte 2026-W03?\"",{"type":33,"tag":649,"props":2003,"children":2004},{},[2005,2007,2013],{"type":38,"value":2006},"Pruning: ",{"type":33,"tag":41,"props":2008,"children":2010},{"className":2009},[],[2011],{"type":38,"value":2012},"WHERE cohort_week = '2026-01-13'",{"type":38,"value":2014}," → se lee 1 partición",{"type":33,"tag":649,"props":2016,"children":2017},{},[2018],{"type":38,"value":2019},"Dificultad: Si el dashboard pregunta \"¿cuál es la retención total de las últimas 4 semanas?\", se leen 4 particiones. Pero como la mayoría del análisis de retención es cohort-céntrico, es óptimo.",{"type":33,"tag":34,"props":2021,"children":2022},{},[2023],{"type":33,"tag":653,"props":2024,"children":2025},{},[2026],{"type":38,"value":2027},"Particionar por event_week:",{"type":33,"tag":895,"props":2029,"children":2030},{},[2031,2036,2047],{"type":33,"tag":649,"props":2032,"children":2033},{},[2034],{"type":38,"value":2035},"Caso de uso: \"¿Qué cohortes fueron activas esta semana?\"",{"type":33,"tag":649,"props":2037,"children":2038},{},[2039,2040,2046],{"type":38,"value":2006},{"type":33,"tag":41,"props":2041,"children":2043},{"className":2042},[],[2044],{"type":38,"value":2045},"WHERE event_week = '2026-07-21'",{"type":38,"value":2014},{"type":33,"tag":649,"props":2048,"children":2049},{},[2050],{"type":38,"value":2051},"Dificultad: Si añades un filtro de cohorte, el pruning no funciona, se leen todas las particiones.",{"type":33,"tag":34,"props":2053,"children":2054},{},[2055,2057,2066],{"type":38,"value":2056},"Roibase en proyectos de ",{"type":33,"tag":2058,"props":2059,"children":2063},"a",{"href":2060,"rel":2061},"https:\u002F\u002Fwww.roibase.com.tr\u002Fes\u002Fverianalizi",[2062],"nofollow",[2064],{"type":38,"value":2065},"análisis de datos",{"type":38,"value":2067}," particiona la tabla de retención por cohort_week, porque el 80% de las consultas de retención siguen el formato \"cohorte X en la semana N\".",{"type":33,"tag":50,"props":2069,"children":2071},{"id":2070},"optimización-de-costos-de-consulta-clustering-y-bi-engine",[2072],{"type":38,"value":2073},"Optimización de Costos de Consulta: Clustering y BI Engine",{"type":33,"tag":34,"props":2075,"children":2076},{},[2077],{"type":38,"value":2078},"El particionamiento hace pruning de arriba a abajo (qué bloques de archivo leer), el clustering ordena de izquierda a derecha (qué filas dentro del bloque leer). Ambos juntos minimizan el escaneo.",{"type":33,"tag":85,"props":2080,"children":2082},{"className":87,"code":2081,"language":89,"meta":17,"style":17},"CREATE TABLE cohort_retention_weekly\nPARTITION BY cohort_week\nCLUSTER BY weeks_since_cohort, platform, country;\n",[2083],{"type":33,"tag":41,"props":2084,"children":2085},{"__ignoreMap":17},[2086,2101,2116],{"type":33,"tag":95,"props":2087,"children":2088},{"class":97,"line":98},[2089,2093,2097],{"type":33,"tag":95,"props":2090,"children":2091},{"style":102},[2092],{"type":38,"value":555},{"type":33,"tag":95,"props":2094,"children":2095},{"style":102},[2096],{"type":38,"value":719},{"type":33,"tag":95,"props":2098,"children":2099},{"style":722},[2100],{"type":38,"value":1591},{"type":33,"tag":95,"props":2102,"children":2103},{"class":97,"line":124},[2104,2108,2112],{"type":33,"tag":95,"props":2105,"children":2106},{"style":102},[2107],{"type":38,"value":733},{"type":33,"tag":95,"props":2109,"children":2110},{"style":102},[2111],{"type":38,"value":738},{"type":33,"tag":95,"props":2113,"children":2114},{"style":108},[2115],{"type":38,"value":165},{"type":33,"tag":95,"props":2117,"children":2118},{"class":97,"line":168},[2119,2123,2127],{"type":33,"tag":95,"props":2120,"children":2121},{"style":108},[2122],{"type":38,"value":750},{"type":33,"tag":95,"props":2124,"children":2125},{"style":102},[2126],{"type":38,"value":755},{"type":33,"tag":95,"props":2128,"children":2129},{"style":108},[2130],{"type":38,"value":2131}," weeks_since_cohort, platform, country;\n",{"type":33,"tag":34,"props":2133,"children":2134},{},[2135,2137,2143],{"type":38,"value":2136},"Si la consulta es ",{"type":33,"tag":41,"props":2138,"children":2140},{"className":2139},[],[2141],{"type":38,"value":2142},"WHERE weeks_since_cohort = 4 AND platform = 'iOS'",{"type":38,"value":2144},":",{"type":33,"tag":645,"props":2146,"children":2147},{},[2148,2153],{"type":33,"tag":649,"props":2149,"children":2150},{},[2151],{"type":38,"value":2152},"Partition pruning → solo particiones de cohort_week relevantes",{"type":33,"tag":649,"props":2154,"children":2155},{},[2156,2158,2164,2166],{"type":38,"value":2157},"Clustering → dentro de la partición, primero filas con ",{"type":33,"tag":41,"props":2159,"children":2161},{"className":2160},[],[2162],{"type":38,"value":2163},"weeks_since_cohort = 4",{"type":38,"value":2165},", luego filas con ",{"type":33,"tag":41,"props":2167,"children":2169},{"className":2168},[],[2170],{"type":38,"value":2171},"platform = 'iOS'",{"type":33,"tag":34,"props":2173,"children":2174},{},[2175],{"type":38,"value":2176},"BigQuery acepta máximo 4 columnas de clustering. El orden importa: pon la columna más filtrada primero.",{"type":33,"tag":34,"props":2178,"children":2179},{},[2180,2185,2187,2192],{"type":33,"tag":653,"props":2181,"children":2182},{},[2183],{"type":38,"value":2184},"BI Engine:",{"type":38,"value":2186}," La capa de caché en memoria de BigQuery. Si reservas 100 GB de BI Engine, las tablas usadas frecuentemente se mantienen en RAM. Si la tabla ",{"type":33,"tag":41,"props":2188,"children":2190},{"className":2189},[],[2191],{"type":38,"value":1927},{"type":38,"value":2193}," es 50 MB, cabe completamente en BI Engine, el escaneo es 0 (cache hit). Costo: 100 GB × $100\u002Fmes. Beneficio: ~10 TB de escaneo ahorrado = $62.50. ROI positivo.",{"type":33,"tag":530,"props":2195,"children":2197},{"id":2196},"funciones-de-aproximación-métricas-que-no-necesitan-exactitud-total",[2198],{"type":38,"value":2199},"Funciones de Aproximación: Métricas que No Necesitan Exactitud Total",{"type":33,"tag":34,"props":2201,"children":2202},{},[2203,2205,2211],{"type":38,"value":2204},"En el cálculo de retención de cohorte, algunas métricas deben ser exactas (",{"type":33,"tag":41,"props":2206,"children":2208},{"className":2207},[],[2209],{"type":38,"value":2210},"COUNT(DISTINCT user_id)",{"type":38,"value":2212},"), otras pueden ser aproximadas (duración mediana de sesión, percentil).",{"type":33,"tag":34,"props":2214,"children":2215},{},[2216],{"type":38,"value":2217},"Funciones aproximadas de BigQuery:",{"type":33,"tag":895,"props":2219,"children":2220},{},[2221,2232,2243],{"type":33,"tag":649,"props":2222,"children":2223},{},[2224,2230],{"type":33,"tag":41,"props":2225,"children":2227},{"className":2226},[],[2228],{"type":38,"value":2229},"APPROX_COUNT_DISTINCT(user_id)",{"type":38,"value":2231}," → margen de error del 2%, 10× más rápido",{"type":33,"tag":649,"props":2233,"children":2234},{},[2235,2241],{"type":33,"tag":41,"props":2236,"children":2238},{"className":2237},[],[2239],{"type":38,"value":2240},"APPROX_QUANTILES(value, 100)[OFFSET(50)]",{"type":38,"value":2242}," → mediana, margen del 1%",{"type":33,"tag":649,"props":2244,"children":2245},{},[2246,2252],{"type":33,"tag":41,"props":2247,"children":2249},{"className":2248},[],[2250],{"type":38,"value":2251},"APPROX_TOP_COUNT(event_name, 10)",{"type":38,"value":2253}," → top 10 eventos, aproximado",{"type":33,"tag":34,"props":2255,"children":2256},{},[2257,2259,2265,2267,2273],{"type":38,"value":2258},"Ejemplo: para 50M usuarios, ",{"type":33,"tag":41,"props":2260,"children":2262},{"className":2261},[],[2263],{"type":38,"value":2264},"COUNT(DISTINCT ...)",{"type":38,"value":2266}," exacto tarda 8 segundos, ",{"type":33,"tag":41,"props":2268,"children":2270},{"className":2269},[],[2271],{"type":38,"value":2272},"APPROX_COUNT_DISTINCT",{"type":38,"value":2274}," tarda 800 ms. Usa aproximación para filtros en tiempo real del dashboard, exactitud para reportes finales.",{"type":33,"tag":50,"props":2276,"children":2278},{"id":2277},"estrategia-de-actualización-incremental-event_time-vs-processing_time",[2279],{"type":38,"value":2280},"Estrategia de Actualización Incremental: event_time vs processing_time",{"type":33,"tag":34,"props":2282,"children":2283},{},[2284],{"type":38,"value":2285},"Mientras que la tabla de cohorte se actualiza una vez al día, ¿qué eventos debe procesar? Hay dos timestamps:",{"type":33,"tag":645,"props":2287,"children":2288},{},[2289,2299],{"type":33,"tag":649,"props":2290,"children":2291},{},[2292,2297],{"type":33,"tag":653,"props":2293,"children":2294},{},[2295],{"type":38,"value":2296},"event_time:",{"type":38,"value":2298}," Cuándo el usuario ejecutó realmente el evento (lado del cliente)",{"type":33,"tag":649,"props":2300,"children":2301},{},[2302,2307],{"type":33,"tag":653,"props":2303,"children":2304},{},[2305],{"type":38,"value":2306},"_PARTITIONTIME:",{"type":38,"value":2308}," Cuándo BigQuery guardó el evento (lado del servidor)",{"type":33,"tag":34,"props":2310,"children":2311},{},[2312,2314,2319],{"type":38,"value":2313},"Si la actualización incremental usa ",{"type":33,"tag":41,"props":2315,"children":2317},{"className":2316},[],[2318],{"type":38,"value":74},{"type":38,"value":2144},{"type":33,"tag":85,"props":2321,"children":2323},{"className":87,"code":2322,"language":89,"meta":17,"style":17},"WHERE event_time > (SELECT MAX(event_time) FROM cohort_assignments)\n",[2324],{"type":33,"tag":41,"props":2325,"children":2326},{"__ignoreMap":17},[2327],{"type":33,"tag":95,"props":2328,"children":2329},{"class":97,"line":98},[2330,2334,2338,2342,2346,2350,2354,2358,2362],{"type":33,"tag":95,"props":2331,"children":2332},{"style":102},[2333],{"type":38,"value":859},{"type":33,"tag":95,"props":2335,"children":2336},{"style":108},[2337],{"type":38,"value":864},{"type":33,"tag":95,"props":2339,"children":2340},{"style":102},[2341],{"type":38,"value":1496},{"type":33,"tag":95,"props":2343,"children":2344},{"style":108},[2345],{"type":38,"value":1501},{"type":33,"tag":95,"props":2347,"children":2348},{"style":102},[2349],{"type":38,"value":472},{"type":33,"tag":95,"props":2351,"children":2352},{"style":138},[2353],{"type":38,"value":1510},{"type":33,"tag":95,"props":2355,"children":2356},{"style":108},[2357],{"type":38,"value":831},{"type":33,"tag":95,"props":2359,"children":2360},{"style":102},[2361],{"type":38,"value":608},{"type":33,"tag":95,"props":2363,"children":2364},{"style":108},[2365],{"type":38,"value":2366}," cohort_assignments)\n",{"type":33,"tag":34,"props":2368,"children":2369},{},[2370,2375,2377,2382],{"type":33,"tag":653,"props":2371,"children":2372},{},[2373],{"type":38,"value":2374},"Problema:",{"type":38,"value":2376}," Eventos que llegan tarde. El usuario está offline 3 días, el evento se carga en batch después. Si ",{"type":33,"tag":41,"props":2378,"children":2380},{"className":2379},[],[2381],{"type":38,"value":74},{"type":38,"value":2383}," es de 3 días atrás, la consulta incremental lo pierde.",{"type":33,"tag":34,"props":2385,"children":2386},{},[2387,2388,2394],{"type":38,"value":2313},{"type":33,"tag":41,"props":2389,"children":2391},{"className":2390},[],[2392],{"type":38,"value":2393},"_PARTITIONTIME",{"type":38,"value":2144},{"type":33,"tag":85,"props":2396,"children":2398},{"className":87,"code":2397,"language":89,"meta":17,"style":17},"WHERE _PARTITIONTIME > CURRENT_DATE() - 7\n",[2399],{"type":33,"tag":41,"props":2400,"children":2401},{"__ignoreMap":17},[2402],{"type":33,"tag":95,"props":2403,"children":2404},{"class":97,"line":98},[2405,2409,2414,2418,2423,2428],{"type":33,"tag":95,"props":2406,"children":2407},{"style":102},[2408],{"type":38,"value":859},{"type":33,"tag":95,"props":2410,"children":2411},{"style":108},[2412],{"type":38,"value":2413}," _PARTITIONTIME ",{"type":33,"tag":95,"props":2415,"children":2416},{"style":102},[2417],{"type":38,"value":1496},{"type":33,"tag":95,"props":2419,"children":2420},{"style":108},[2421],{"type":38,"value":2422}," CURRENT_DATE() ",{"type":33,"tag":95,"props":2424,"children":2425},{"style":102},[2426],{"type":38,"value":2427},"-",{"type":33,"tag":95,"props":2429,"children":2430},{"style":138},[2431],{"type":38,"value":2432}," 7\n",{"type":33,"tag":34,"props":2434,"children":2435},{},[2436,2441,2443,2448],{"type":33,"tag":653,"props":2437,"children":2438},{},[2439],{"type":38,"value":2440},"Ventaja:",{"type":38,"value":2442}," Reprocesa los últimos 7 días cada vez, captura eventos que llegan tarde.\n",{"type":33,"tag":653,"props":2444,"children":2445},{},[2446],{"type":38,"value":2447},"Costo:",{"type":38,"value":2449}," 7 días de datos de eventos = ~14 GB de escaneo diario (en lugar de 2 GB).",{"type":33,"tag":34,"props":2451,"children":2452},{},[2453,2455,2460,2462,2467],{"type":38,"value":2454},"Tradeoff: si eventos atrasados son \u003C 1%, usa ",{"type":33,"tag":41,"props":2456,"children":2458},{"className":2457},[],[2459],{"type":38,"value":74},{"type":38,"value":2461}," (escaneo bajo). Si en apps móviles son ~5%, usa ",{"type":33,"tag":41,"props":2463,"children":2465},{"className":2464},[],[2466],{"type":38,"value":2393},{"type":38,"value":2468}," con lookback de 3 días.",{"type":33,"tag":50,"props":2470,"children":2472},{"id":2471},"segmentación-de-cohorte-filtros-dinámicos-vs-dimensiones-estáticas",[2473],{"type":38,"value":2474},"Segmentación de Cohorte: Filtros Dinámicos vs Dimensiones Estáticas",{"type":33,"tag":34,"props":2476,"children":2477},{},[2478],{"type":38,"value":2479},"El usuario añade un filtro en el dashboard: \"retención de cohorte iOS\". Dos métodos:",{"type":33,"tag":34,"props":2481,"children":2482},{},[2483],{"type":33,"tag":653,"props":2484,"children":2485},{},[2486],{"type":38,"value":2487},"Método 1: Filtro en tiempo de consulta",{"type":33,"tag":85,"props":2489,"children":2491},{"className":87,"code":2490,"language":89,"meta":17,"style":17},"SELECT cohort_week, weeks_since, active_users\nFROM cohort_retention_weekly\nWHERE user_id IN (SELECT user_id FROM users WHERE platform = 'iOS');\n",[2492],{"type":33,"tag":41,"props":2493,"children":2494},{"__ignoreMap":17},[2495,2507,2518],{"type":33,"tag":95,"props":2496,"children":2497},{"class":97,"line":98},[2498,2502],{"type":33,"tag":95,"props":2499,"children":2500},{"style":102},[2501],{"type":38,"value":472},{"type":33,"tag":95,"props":2503,"children":2504},{"style":108},[2505],{"type":38,"value":2506}," cohort_week, weeks_since, active_users\n",{"type":33,"tag":95,"props":2508,"children":2509},{"class":97,"line":124},[2510,2514],{"type":33,"tag":95,"props":2511,"children":2512},{"style":102},[2513],{"type":38,"value":608},{"type":33,"tag":95,"props":2515,"children":2516},{"style":108},[2517],{"type":38,"value":1591},{"type":33,"tag":95,"props":2519,"children":2520},{"class":97,"line":168},[2521,2525,2530,2535,2539,2543,2547,2551,2556,2560,2565,2569,2574],{"type":33,"tag":95,"props":2522,"children":2523},{"style":102},[2524],{"type":38,"value":859},{"type":33,"tag":95,"props":2526,"children":2527},{"style":108},[2528],{"type":38,"value":2529}," user_id ",{"type":33,"tag":95,"props":2531,"children":2532},{"style":102},[2533],{"type":38,"value":2534},"IN",{"type":33,"tag":95,"props":2536,"children":2537},{"style":108},[2538],{"type":38,"value":1501},{"type":33,"tag":95,"props":2540,"children":2541},{"style":102},[2542],{"type":38,"value":472},{"type":33,"tag":95,"props":2544,"children":2545},{"style":108},[2546],{"type":38,"value":2529},{"type":33,"tag":95,"props":2548,"children":2549},{"style":102},[2550],{"type":38,"value":608},{"type":33,"tag":95,"props":2552,"children":2553},{"style":108},[2554],{"type":38,"value":2555}," users ",{"type":33,"tag":95,"props":2557,"children":2558},{"style":102},[2559],{"type":38,"value":859},{"type":33,"tag":95,"props":2561,"children":2562},{"style":108},[2563],{"type":38,"value":2564}," platform ",{"type":33,"tag":95,"props":2566,"children":2567},{"style":102},[2568],{"type":38,"value":1265},{"type":33,"tag":95,"props":2570,"children":2571},{"style":872},[2572],{"type":38,"value":2573}," 'iOS'",{"type":33,"tag":95,"props":2575,"children":2576},{"style":108},[2577],{"type":38,"value":2578},");\n",{"type":33,"tag":34,"props":2580,"children":2581},{},[2582,2586,2588,2594],{"type":33,"tag":653,"props":2583,"children":2584},{},[2585],{"type":38,"value":2374},{"type":38,"value":2587}," La subconsulta escanea la tabla ",{"type":33,"tag":41,"props":2589,"children":2591},{"className":2590},[],[2592],{"type":38,"value":2593},"users",{"type":38,"value":2595}," cada vez. 50M usuarios = 1 GB de escaneo. 100 refreshes del dashboard = 100 GB.",{"type":33,"tag":34,"props":2597,"children":2598},{},[2599],{"type":33,"tag":653,"props":2600,"children":2601},{},[2602],{"type":38,"value":2603},"Método 2: Precomputar dimensiones",{"type":33,"tag":85,"props":2605,"children":2607},{"className":87,"code":2606,"language":89,"meta":17,"style":17},"CREATE TABLE cohort_retention_weekly\nAS\nSELECT \n  c.cohort_week,\n  weeks_since_cohort,\n  u.platform,\n  u.country,\n  COUNT(DISTINCT e.user_id) AS active_users\nFROM cohort_assignments c\nJOIN events e ON c.user_id = e.user_id\nJOIN users u ON e.user_id = u.user_id\nGROUP BY 1, 2, \n",[2608],{"type":33,"tag":41,"props":2609,"children":2610},{"__ignoreMap":17},[2611,2626,2633,2644,2663,2670,2691,2711,2750,2761,2804,2849],{"type":33,"tag":95,"props":2612,"children":2613},{"class":97,"line":98},[2614,2618,2622],{"type":33,"tag":95,"props":2615,"children":2616},{"style":102},[2617],{"type":38,"value":555},{"type":33,"tag":95,"props":2619,"children":2620},{"style":102},[2621],{"type":38,"value":719},{"type":33,"tag":95,"props":2623,"children":2624},{"style":722},[2625],{"type":38,"value":1591},{"type":33,"tag":95,"props":2627,"children":2628},{"class":97,"line":124},[2629],{"type":33,"tag":95,"props":2630,"children":2631},{"style":102},[2632],{"type":38,"value":565},{"type":33,"tag":95,"props":2634,"children":2635},{"class":97,"line":168},[2636,2640],{"type":33,"tag":95,"props":2637,"children":2638},{"style":102},[2639],{"type":38,"value":472},{"type":33,"tag":95,"props":2641,"children":2642},{"style":108},[2643],{"type":38,"value":232},{"type":33,"tag":95,"props":2645,"children":2646},{"class":97,"line":182},[2647,2651,2655,2659],{"type":33,"tag":95,"props":2648,"children":2649},{"style":138},[2650],{"type":38,"value":966},{"type":33,"tag":95,"props":2652,"children":2653},{"style":108},[2654],{"type":38,"value":245},{"type":33,"tag":95,"props":2656,"children":2657},{"style":138},[2658],{"type":38,"value":250},{"type":33,"tag":95,"props":2660,"children":2661},{"style":108},[2662],{"type":38,"value":255},{"type":33,"tag":95,"props":2664,"children":2665},{"class":97,"line":196},[2666],{"type":33,"tag":95,"props":2667,"children":2668},{"style":108},[2669],{"type":38,"value":592},{"type":33,"tag":95,"props":2671,"children":2672},{"class":97,"line":205},[2673,2678,2682,2687],{"type":33,"tag":95,"props":2674,"children":2675},{"style":138},[2676],{"type":38,"value":2677},"  u",{"type":33,"tag":95,"props":2679,"children":2680},{"style":108},[2681],{"type":38,"value":245},{"type":33,"tag":95,"props":2683,"children":2684},{"style":138},[2685],{"type":38,"value":2686},"platform",{"type":33,"tag":95,"props":2688,"children":2689},{"style":108},[2690],{"type":38,"value":255},{"type":33,"tag":95,"props":2692,"children":2693},{"class":97,"line":222},[2694,2698,2702,2707],{"type":33,"tag":95,"props":2695,"children":2696},{"style":138},[2697],{"type":38,"value":2677},{"type":33,"tag":95,"props":2699,"children":2700},{"style":108},[2701],{"type":38,"value":245},{"type":33,"tag":95,"props":2703,"children":2704},{"style":138},[2705],{"type":38,"value":2706},"country",{"type":33,"tag":95,"props":2708,"children":2709},{"style":108},[2710],{"type":38,"value":255},{"type":33,"tag":95,"props":2712,"children":2713},{"class":97,"line":27},[2714,2718,2722,2726,2730,2734,2738,2742,2746],{"type":33,"tag":95,"props":2715,"children":2716},{"style":138},[2717],{"type":38,"value":1051},{"type":33,"tag":95,"props":2719,"children":2720},{"style":108},[2721],{"type":38,"value":338},{"type":33,"tag":95,"props":2723,"children":2724},{"style":102},[2725],{"type":38,"value":343},{"type":33,"tag":95,"props":2727,"children":2728},{"style":138},[2729],{"type":38,"value":348},{"type":33,"tag":95,"props":2731,"children":2732},{"style":108},[2733],{"type":38,"value":245},{"type":33,"tag":95,"props":2735,"children":2736},{"style":138},[2737],{"type":38,"value":66},{"type":33,"tag":95,"props":2739,"children":2740},{"style":108},[2741],{"type":38,"value":156},{"type":33,"tag":95,"props":2743,"children":2744},{"style":102},[2745],{"type":38,"value":116},{"type":33,"tag":95,"props":2747,"children":2748},{"style":108},[2749],{"type":38,"value":369},{"type":33,"tag":95,"props":2751,"children":2752},{"class":97,"line":258},[2753,2757],{"type":33,"tag":95,"props":2754,"children":2755},{"style":102},[2756],{"type":38,"value":608},{"type":33,"tag":95,"props":2758,"children":2759},{"style":108},[2760],{"type":38,"value":1095},{"type":33,"tag":95,"props":2762,"children":2763},{"class":97,"line":327},[2764,2768,2772,2776,2780,2784,2788,2792,2796,2800],{"type":33,"tag":95,"props":2765,"children":2766},{"style":102},[2767],{"type":38,"value":1103},{"type":33,"tag":95,"props":2769,"children":2770},{"style":108},[2771],{"type":38,"value":396},{"type":33,"tag":95,"props":2773,"children":2774},{"style":102},[2775],{"type":38,"value":401},{"type":33,"tag":95,"props":2777,"children":2778},{"style":138},[2779],{"type":38,"value":406},{"type":33,"tag":95,"props":2781,"children":2782},{"style":108},[2783],{"type":38,"value":245},{"type":33,"tag":95,"props":2785,"children":2786},{"style":138},[2787],{"type":38,"value":66},{"type":33,"tag":95,"props":2789,"children":2790},{"style":102},[2791],{"type":38,"value":419},{"type":33,"tag":95,"props":2793,"children":2794},{"style":138},[2795],{"type":38,"value":348},{"type":33,"tag":95,"props":2797,"children":2798},{"style":108},[2799],{"type":38,"value":245},{"type":33,"tag":95,"props":2801,"children":2802},{"style":138},[2803],{"type":38,"value":432},{"type":33,"tag":95,"props":2805,"children":2806},{"class":97,"line":372},[2807,2811,2816,2820,2824,2828,2832,2836,2841,2845],{"type":33,"tag":95,"props":2808,"children":2809},{"style":102},[2810],{"type":38,"value":1103},{"type":33,"tag":95,"props":2812,"children":2813},{"style":108},[2814],{"type":38,"value":2815}," users u ",{"type":33,"tag":95,"props":2817,"children":2818},{"style":102},[2819],{"type":38,"value":401},{"type":33,"tag":95,"props":2821,"children":2822},{"style":138},[2823],{"type":38,"value":348},{"type":33,"tag":95,"props":2825,"children":2826},{"style":108},[2827],{"type":38,"value":245},{"type":33,"tag":95,"props":2829,"children":2830},{"style":138},[2831],{"type":38,"value":66},{"type":33,"tag":95,"props":2833,"children":2834},{"style":102},[2835],{"type":38,"value":419},{"type":33,"tag":95,"props":2837,"children":2838},{"style":138},[2839],{"type":38,"value":2840}," u",{"type":33,"tag":95,"props":2842,"children":2843},{"style":108},[2844],{"type":38,"value":245},{"type":33,"tag":95,"props":2846,"children":2847},{"style":138},[2848],{"type":38,"value":432},{"type":33,"tag":95,"props":2850,"children":2851},{"class":97,"line":385},[2852,2856,2860,2864,2868],{"type":33,"tag":95,"props":2853,"children":2854},{"style":102},[2855],{"type":38,"value":883},{"type":33,"tag":95,"props":2857,"children":2858},{"style":138},[2859],{"type":38,"value":445},{"type":33,"tag":95,"props":2861,"children":2862},{"style":108},[2863],{"type":38,"value":68},{"type":33,"tag":95,"props":2865,"children":2866},{"style":138},[2867],{"type":38,"value":505},{"type":33,"tag":95,"props":2869,"children":2870},{"style":108},[2871],{"type":38,"value":255},{"type":33,"tag":2873,"props":2874,"children":2875},"style",{},[2876],{"type":38,"value":2877},"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":17,"searchDepth":168,"depth":168,"links":2879},[2880,2883,2886,2889,2892,2893],{"id":52,"depth":124,"text":55,"children":2881},[2882],{"id":532,"depth":168,"text":535},{"id":677,"depth":124,"text":680,"children":2884},[2885],{"id":1214,"depth":168,"text":1217},{"id":1553,"depth":124,"text":1556,"children":2887},[2888],{"id":1962,"depth":168,"text":1965},{"id":2070,"depth":124,"text":2073,"children":2890},[2891],{"id":2196,"depth":168,"text":2199},{"id":2277,"depth":124,"text":2280},{"id":2471,"depth":124,"text":2474},"markdown","content:es:data:arquitectura-tabla-cohorte.md","content","es\u002Fdata\u002Farquitectura-tabla-cohorte.md","es\u002Fdata\u002Farquitectura-tabla-cohorte","md",1785967481608]