[{"data":1,"prerenderedAt":1975},["ShallowReactive",2],{"article-alternates":3,"article-\u002Ffr\u002Fdata\u002Farchitecture-table-cohort-analyse-retention":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-production-retention-scaling","\u002Fen\u002Fdata\u002Fcohort-table-architecture-scaling-retention-analysis-production","\u002Fes\u002Fdata\u002Farquitectura-tabla-cohorte-escalando-analisis-retencion","\u002Ffr\u002Fdata\u002Farchitecture-table-cohort-analyse-retention","\u002Fit\u002Fdata\u002Farchitettura-tabella-cohort-scalabilita-retention-analysis-production","\u002Fru\u002Fdata\u002Farkhitektura-tablitsy-kogort-masshtabirovanie-analiza-sokhraneniya-v-production","\u002Ftr\u002Fdata\u002Fcohort-tablo-mimarisi-retention-analizinin-productionda-olceklenmesi",{"_path":9,"_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":1969,"_id":1970,"_source":1971,"_file":1972,"_stem":1973,"_extension":1974},"data",false,"","Architecture de Table Cohort : Mise à l'Échelle de l'Analyse de Rétention en Production","Materialized views, partitionnement et optimisation des coûts de requête pour dimensionner l'analyse cohort en production. Architecture de table concrète sur BigQuery et dbt.","2026-07-12",[21,22,23,24,25],"cohort-analysis","bigquery","materialized-views","query-optimization","retention",9,"Roibase",{"type":29,"children":30,"toc":1958},"root",[31,39,46,51,56,61,84,103,121,136,162,347,353,358,378,391,1451,1456,1463,1468,1473,1509,1522,1528,1533,1543,1553,1565,1570,1576,1581,1619,1778,1783,1882,1888,1893,1942,1947,1952],{"type":32,"tag":33,"props":34,"children":35},"element","p",{},[36],{"type":37,"value":38},"text","L'analyse de rétention est l'une des métriques les plus critiques des données marketing. Comprendre quel groupe d'utilisateurs reste actif pendant combien de temps, quelle campagne crée une valeur durable — cela exige des tables de cohort robustes. Le problème : les requêtes cohort classiques re-exécutées chaque fois sur des dizaines de millions de lignes de données d'événements font exploser les coûts de requête en production. Construire une architecture cohort qui se met à jour chaque matin, qui retourne les résultats en 3 secondes lorsqu'un analyste lance une requête, tout en minimisant les coûts grâce à une stratégie de partitionnement adéquate — c'est un problème d'ingénierie distinct. Cet article explique pas à pas une architecture de table cohort concrète sur BigQuery et dbt, une stratégie de materialized view et une optimisation des coûts de requête.",{"type":32,"tag":40,"props":41,"children":43},"h2",{"id":42},"pourquoi-une-table-cohort-doit-être-séparée",[44],{"type":37,"value":45},"Pourquoi une table cohort doit être séparée",{"type":32,"tag":33,"props":47,"children":48},{},[49],{"type":37,"value":50},"Le calcul de la rétention ne peut pas être effectué à chaque fois à partir de la table d'événements bruts. Si une entreprise e-commerce génère 50 millions d'événements par jour, répondre à la question « Quel est le taux d'activité au jour 30 pour les utilisateurs inscrits en janvier 2026 ? » exige que BigQuery scanne 1,5 milliard de lignes. Cette requête prend 10-15 secondes et traite 200-300 GB. Si l'analyste extrait 20 segments de cohort différents par jour, le coût mensuel des requêtes dépasse $500.",{"type":32,"tag":33,"props":52,"children":53},{},[54],{"type":37,"value":55},"Une table cohort résout ce problème : vous pré-agrégez les données d'événements par groupe et pré-calculez les métriques de chaque cohort pour chaque jour. Ainsi, lorsque l'analyste lance une requête, BigQuery ne scanne que la table cohort, jamais les données d'événements brutes. 1000 cohorts × 90 jours × 5 métriques = 450 000 lignes. Une requête sur cette table prend 200 ms et traite 5 MB.",{"type":32,"tag":33,"props":57,"children":58},{},[59],{"type":37,"value":60},"Mais cette approche elle-même crée un nouveau problème : comment la table cohort est-elle mise à jour ? Chaque jour, lorsque de nouveaux événements arrivent, recalculez-vous toute l'historique ? Travaillez-vous de façon incrémentale ? Quelle stratégie de partitionnement optimise à la fois la performance des requêtes et le coût de mise à jour ? Les réponses à ces questions se trouvent dans la conception de materialized views et de modèles dbt incrémentiels.",{"type":32,"tag":40,"props":62,"children":64},{"id":63},"stratégie-de-partitionnement-cohort_date-ou-observation_date",[65,67,74,76,82],{"type":37,"value":66},"Stratégie de partitionnement : ",{"type":32,"tag":68,"props":69,"children":71},"code",{"className":70},[],[72],{"type":37,"value":73},"cohort_date",{"type":37,"value":75}," ou ",{"type":32,"tag":68,"props":77,"children":79},{"className":78},[],[80],{"type":37,"value":81},"observation_date",{"type":37,"value":83}," ?",{"type":32,"tag":33,"props":85,"children":86},{},[87,89,94,96,101],{"type":37,"value":88},"Le choix de la clé de partitionnement de la table cohort est critique. Vous avez deux options : la date de création de la cohort (",{"type":32,"tag":68,"props":90,"children":92},{"className":91},[],[93],{"type":37,"value":73},{"type":37,"value":95},") et la date d'observation (",{"type":32,"tag":68,"props":97,"children":99},{"className":98},[],[100],{"type":37,"value":81},{"type":37,"value":102},").",{"type":32,"tag":33,"props":104,"children":105},{},[106,119],{"type":32,"tag":107,"props":108,"children":109},"strong",{},[110,112,117],{"type":37,"value":111},"Partition ",{"type":32,"tag":68,"props":113,"children":115},{"className":114},[],[116],{"type":37,"value":73},{"type":37,"value":118}," :",{"type":37,"value":120}," Partitionne selon la date de la première activité de l'utilisateur. La cohort de janvier 2026 en une partition, février en une autre. Avantage : lorsqu'une nouvelle cohort est créée, vous n'écrivez que dans cette partition, sans toucher aux anciennes. Inconvénient : récupérer 90 jours de données de rétention pour une même cohort oblige BigQuery à scanner 90 partitions différentes. La performance des requêtes diminue.",{"type":32,"tag":33,"props":122,"children":123},{},[124,134],{"type":32,"tag":107,"props":125,"children":126},{},[127,128,133],{"type":37,"value":111},{"type":32,"tag":68,"props":129,"children":131},{"className":130},[],[132],{"type":37,"value":81},{"type":37,"value":118},{"type":37,"value":135}," Une partition par jour. Pour le 12 juillet, la partition du 12 juillet contient toutes les métriques d'aujourd'hui pour tous les cohorts. Avantage : répondre à des requêtes comme « Tendance de rétention sur les 7 derniers jours » ne scanne que 7 partitions. Inconvénient : vous êtes obligé de mettre à jour tous les cohorts chaque jour, le coût de mise à jour incrémentale est élevé.",{"type":32,"tag":33,"props":137,"children":138},{},[139,141,146,148,153,155,160],{"type":37,"value":140},"La bonne réponse est une ",{"type":32,"tag":107,"props":142,"children":143},{},[144],{"type":37,"value":145},"architecture hybride avec deux tables",{"type":37,"value":147}," : une « snapshot table » (partitionnée par ",{"type":32,"tag":68,"props":149,"children":151},{"className":150},[],[152],{"type":37,"value":81},{"type":37,"value":154},") et une « aggregated table » (partitionnée par ",{"type":32,"tag":68,"props":156,"children":158},{"className":157},[],[159],{"type":37,"value":73},{"type":37,"value":161},"). La table snapshot est mise à jour quotidiennement, elle alimente les dashboards de l'analyste. La table agrégée est mise à jour hebdomadairement, elle est utilisée pour des comparaisons de cohorts approfondies. Cette structure suit les bonnes pratiques BigQuery : séparation des tables narrow et wide.",{"type":32,"tag":163,"props":164,"children":168},"pre",{"className":165,"code":166,"language":167,"meta":16,"style":16},"language-sql shiki shiki-themes github-dark","-- Schéma de la table snapshot (partitionnée par observation_date)\nCREATE TABLE `analytics.cohort_retention_snapshot`\nPARTITION BY observation_date\nCLUSTER BY cohort_date, channel, device_category\nAS\nSELECT\n  observation_date,\n  cohort_date,\n  channel,\n  device_category,\n  cohort_size,\n  day_n,\n  active_users,\n  retention_rate\nFROM ...\n","sql",[169],{"type":32,"tag":68,"props":170,"children":171},{"__ignoreMap":16},[172,184,205,225,244,253,262,271,280,288,297,306,315,324,333],{"type":32,"tag":173,"props":174,"children":177},"span",{"class":175,"line":176},"line",1,[178],{"type":32,"tag":173,"props":179,"children":181},{"style":180},"--shiki-default:#6A737D",[182],{"type":37,"value":183},"-- Schéma de la table snapshot (partitionnée par observation_date)\n",{"type":32,"tag":173,"props":185,"children":187},{"class":175,"line":186},2,[188,194,199],{"type":32,"tag":173,"props":189,"children":191},{"style":190},"--shiki-default:#F97583",[192],{"type":37,"value":193},"CREATE",{"type":32,"tag":173,"props":195,"children":196},{"style":190},[197],{"type":37,"value":198}," TABLE",{"type":32,"tag":173,"props":200,"children":202},{"style":201},"--shiki-default:#9ECBFF",[203],{"type":37,"value":204}," `analytics.cohort_retention_snapshot`\n",{"type":32,"tag":173,"props":206,"children":208},{"class":175,"line":207},3,[209,214,219],{"type":32,"tag":173,"props":210,"children":211},{"style":190},[212],{"type":37,"value":213},"PARTITION",{"type":32,"tag":173,"props":215,"children":216},{"style":190},[217],{"type":37,"value":218}," BY",{"type":32,"tag":173,"props":220,"children":222},{"style":221},"--shiki-default:#E1E4E8",[223],{"type":37,"value":224}," observation_date\n",{"type":32,"tag":173,"props":226,"children":228},{"class":175,"line":227},4,[229,234,239],{"type":32,"tag":173,"props":230,"children":231},{"style":221},[232],{"type":37,"value":233},"CLUSTER ",{"type":32,"tag":173,"props":235,"children":236},{"style":190},[237],{"type":37,"value":238},"BY",{"type":32,"tag":173,"props":240,"children":241},{"style":221},[242],{"type":37,"value":243}," cohort_date, channel, device_category\n",{"type":32,"tag":173,"props":245,"children":247},{"class":175,"line":246},5,[248],{"type":32,"tag":173,"props":249,"children":250},{"style":190},[251],{"type":37,"value":252},"AS\n",{"type":32,"tag":173,"props":254,"children":256},{"class":175,"line":255},6,[257],{"type":32,"tag":173,"props":258,"children":259},{"style":190},[260],{"type":37,"value":261},"SELECT\n",{"type":32,"tag":173,"props":263,"children":265},{"class":175,"line":264},7,[266],{"type":32,"tag":173,"props":267,"children":268},{"style":221},[269],{"type":37,"value":270},"  observation_date,\n",{"type":32,"tag":173,"props":272,"children":274},{"class":175,"line":273},8,[275],{"type":32,"tag":173,"props":276,"children":277},{"style":221},[278],{"type":37,"value":279},"  cohort_date,\n",{"type":32,"tag":173,"props":281,"children":282},{"class":175,"line":26},[283],{"type":32,"tag":173,"props":284,"children":285},{"style":221},[286],{"type":37,"value":287},"  channel,\n",{"type":32,"tag":173,"props":289,"children":291},{"class":175,"line":290},10,[292],{"type":32,"tag":173,"props":293,"children":294},{"style":221},[295],{"type":37,"value":296},"  device_category,\n",{"type":32,"tag":173,"props":298,"children":300},{"class":175,"line":299},11,[301],{"type":32,"tag":173,"props":302,"children":303},{"style":221},[304],{"type":37,"value":305},"  cohort_size,\n",{"type":32,"tag":173,"props":307,"children":309},{"class":175,"line":308},12,[310],{"type":32,"tag":173,"props":311,"children":312},{"style":221},[313],{"type":37,"value":314},"  day_n,\n",{"type":32,"tag":173,"props":316,"children":318},{"class":175,"line":317},13,[319],{"type":32,"tag":173,"props":320,"children":321},{"style":221},[322],{"type":37,"value":323},"  active_users,\n",{"type":32,"tag":173,"props":325,"children":327},{"class":175,"line":326},14,[328],{"type":32,"tag":173,"props":329,"children":330},{"style":221},[331],{"type":37,"value":332},"  retention_rate\n",{"type":32,"tag":173,"props":334,"children":336},{"class":175,"line":335},15,[337,342],{"type":32,"tag":173,"props":338,"children":339},{"style":190},[340],{"type":37,"value":341},"FROM",{"type":32,"tag":173,"props":343,"children":344},{"style":221},[345],{"type":37,"value":346}," ...\n",{"type":32,"tag":40,"props":348,"children":350},{"id":349},"trade-off-entre-materialized-view-et-modèle-incrémental",[351],{"type":37,"value":352},"Trade-off entre materialized view et modèle incrémental",{"type":32,"tag":33,"props":354,"children":355},{},[356],{"type":37,"value":357},"Dans BigQuery, une materialized view (MV) effectue un refresh incrémental automatique — lorsque de nouveaux événements arrivent, elle re-exécute la requête de base et cache le résultat. Mais une MV a 3 limitations : nombre de jointures (max 5), utilisation de window functions (non supportée), et gestion des partitions (pas manuelle).",{"type":32,"tag":33,"props":359,"children":360},{},[361,363,369,370,376],{"type":37,"value":362},"Le calcul cohort implique généralement 3+ jointures (tables users, events, subscriptions) et nécessite des window functions comme ",{"type":32,"tag":68,"props":364,"children":366},{"className":365},[],[367],{"type":37,"value":368},"LAG()",{"type":37,"value":75},{"type":32,"tag":68,"props":371,"children":373},{"className":372},[],[374],{"type":37,"value":375},"FIRST_VALUE()",{"type":37,"value":377},". Dans ce cas, une MV ne peut pas être utilisée. Alternativement : modèle dbt incrémental.",{"type":32,"tag":33,"props":379,"children":380},{},[381,383,389],{"type":37,"value":382},"Un modèle dbt incrémental vous permet de définir une stratégie de fusion personnalisée. Chaque jour, vous ne mettez à jour que les partitions des 7 derniers jours (",{"type":32,"tag":68,"props":384,"children":386},{"className":385},[],[387],{"type":37,"value":388},"WHERE observation_date >= CURRENT_DATE() - 7",{"type":37,"value":390},"). Cette approche réduit le coût des requêtes de 85 %. Exemple de modèle dbt :",{"type":32,"tag":163,"props":392,"children":394},{"className":165,"code":393,"language":167,"meta":16,"style":16},"{{ config(\n    materialized='incremental',\n    partition_by={\n      \"field\": \"observation_date\",\n      \"data_type\": \"date\"\n    },\n    cluster_by=['cohort_date', 'channel'],\n    incremental_strategy='insert_overwrite'\n) }}\n\nWITH daily_cohorts AS (\n  SELECT\n    DATE(first_seen_at) AS cohort_date,\n    user_id,\n    acquisition_channel AS channel\n  FROM {{ ref('users') }}\n  WHERE first_seen_at IS NOT NULL\n),\n\ndaily_activity AS (\n  SELECT\n    DATE(event_timestamp) AS activity_date,\n    user_id,\n    COUNT(*) AS event_count\n  FROM {{ ref('events') }}\n  WHERE event_name IN ('page_view', 'purchase')\n  {% if is_incremental() %}\n    AND DATE(event_timestamp) >= CURRENT_DATE() - 7\n  {% endif %}\n  GROUP BY 1, 2\n)\n\nSELECT\n  a.activity_date AS observation_date,\n  c.cohort_date,\n  c.channel,\n  DATE_DIFF(a.activity_date, c.cohort_date, DAY) AS day_n,\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 daily_cohorts c\nLEFT JOIN daily_activity a\n  ON c.user_id = a.user_id\nWHERE a.activity_date >= c.cohort_date\n{% if is_incremental() %}\n  AND a.activity_date >= CURRENT_DATE() - 7\n{% endif %}\nGROUP BY 1, 2, 3, 4\n",[395],{"type":32,"tag":68,"props":396,"children":397},{"__ignoreMap":16},[398,406,429,446,468,485,493,510,527,535,544,567,575,597,605,622,645,664,673,681,698,706,728,736,770,791,834,853,891,900,923,931,939,947,976,997,1018,1079,1124,1166,1243,1256,1270,1309,1348,1365,1402,1411],{"type":32,"tag":173,"props":399,"children":400},{"class":175,"line":176},[401],{"type":32,"tag":173,"props":402,"children":403},{"style":221},[404],{"type":37,"value":405},"{{ config(\n",{"type":32,"tag":173,"props":407,"children":408},{"class":175,"line":186},[409,414,419,424],{"type":32,"tag":173,"props":410,"children":411},{"style":221},[412],{"type":37,"value":413},"    materialized",{"type":32,"tag":173,"props":415,"children":416},{"style":190},[417],{"type":37,"value":418},"=",{"type":32,"tag":173,"props":420,"children":421},{"style":201},[422],{"type":37,"value":423},"'incremental'",{"type":32,"tag":173,"props":425,"children":426},{"style":221},[427],{"type":37,"value":428},",\n",{"type":32,"tag":173,"props":430,"children":431},{"class":175,"line":207},[432,437,441],{"type":32,"tag":173,"props":433,"children":434},{"style":221},[435],{"type":37,"value":436},"    partition_by",{"type":32,"tag":173,"props":438,"children":439},{"style":190},[440],{"type":37,"value":418},{"type":32,"tag":173,"props":442,"children":443},{"style":221},[444],{"type":37,"value":445},"{\n",{"type":32,"tag":173,"props":447,"children":448},{"class":175,"line":227},[449,454,459,464],{"type":32,"tag":173,"props":450,"children":451},{"style":201},[452],{"type":37,"value":453},"      \"field\"",{"type":32,"tag":173,"props":455,"children":456},{"style":221},[457],{"type":37,"value":458},": ",{"type":32,"tag":173,"props":460,"children":461},{"style":201},[462],{"type":37,"value":463},"\"observation_date\"",{"type":32,"tag":173,"props":465,"children":466},{"style":221},[467],{"type":37,"value":428},{"type":32,"tag":173,"props":469,"children":470},{"class":175,"line":246},[471,476,480],{"type":32,"tag":173,"props":472,"children":473},{"style":201},[474],{"type":37,"value":475},"      \"data_type\"",{"type":32,"tag":173,"props":477,"children":478},{"style":221},[479],{"type":37,"value":458},{"type":32,"tag":173,"props":481,"children":482},{"style":201},[483],{"type":37,"value":484},"\"date\"\n",{"type":32,"tag":173,"props":486,"children":487},{"class":175,"line":255},[488],{"type":32,"tag":173,"props":489,"children":490},{"style":221},[491],{"type":37,"value":492},"    },\n",{"type":32,"tag":173,"props":494,"children":495},{"class":175,"line":264},[496,501,505],{"type":32,"tag":173,"props":497,"children":498},{"style":221},[499],{"type":37,"value":500},"    cluster_by",{"type":32,"tag":173,"props":502,"children":503},{"style":190},[504],{"type":37,"value":418},{"type":32,"tag":173,"props":506,"children":507},{"style":221},[508],{"type":37,"value":509},"['cohort_date', 'channel'],\n",{"type":32,"tag":173,"props":511,"children":512},{"class":175,"line":273},[513,518,522],{"type":32,"tag":173,"props":514,"children":515},{"style":221},[516],{"type":37,"value":517},"    incremental_strategy",{"type":32,"tag":173,"props":519,"children":520},{"style":190},[521],{"type":37,"value":418},{"type":32,"tag":173,"props":523,"children":524},{"style":201},[525],{"type":37,"value":526},"'insert_overwrite'\n",{"type":32,"tag":173,"props":528,"children":529},{"class":175,"line":26},[530],{"type":32,"tag":173,"props":531,"children":532},{"style":221},[533],{"type":37,"value":534},") }}\n",{"type":32,"tag":173,"props":536,"children":537},{"class":175,"line":290},[538],{"type":32,"tag":173,"props":539,"children":541},{"emptyLinePlaceholder":540},true,[542],{"type":37,"value":543},"\n",{"type":32,"tag":173,"props":545,"children":546},{"class":175,"line":299},[547,552,557,562],{"type":32,"tag":173,"props":548,"children":549},{"style":190},[550],{"type":37,"value":551},"WITH",{"type":32,"tag":173,"props":553,"children":554},{"style":221},[555],{"type":37,"value":556}," daily_cohorts ",{"type":32,"tag":173,"props":558,"children":559},{"style":190},[560],{"type":37,"value":561},"AS",{"type":32,"tag":173,"props":563,"children":564},{"style":221},[565],{"type":37,"value":566}," (\n",{"type":32,"tag":173,"props":568,"children":569},{"class":175,"line":308},[570],{"type":32,"tag":173,"props":571,"children":572},{"style":190},[573],{"type":37,"value":574},"  SELECT\n",{"type":32,"tag":173,"props":576,"children":577},{"class":175,"line":317},[578,583,588,592],{"type":32,"tag":173,"props":579,"children":580},{"style":190},[581],{"type":37,"value":582},"    DATE",{"type":32,"tag":173,"props":584,"children":585},{"style":221},[586],{"type":37,"value":587},"(first_seen_at) ",{"type":32,"tag":173,"props":589,"children":590},{"style":190},[591],{"type":37,"value":561},{"type":32,"tag":173,"props":593,"children":594},{"style":221},[595],{"type":37,"value":596}," cohort_date,\n",{"type":32,"tag":173,"props":598,"children":599},{"class":175,"line":326},[600],{"type":32,"tag":173,"props":601,"children":602},{"style":221},[603],{"type":37,"value":604},"    user_id,\n",{"type":32,"tag":173,"props":606,"children":607},{"class":175,"line":335},[608,613,617],{"type":32,"tag":173,"props":609,"children":610},{"style":221},[611],{"type":37,"value":612},"    acquisition_channel ",{"type":32,"tag":173,"props":614,"children":615},{"style":190},[616],{"type":37,"value":561},{"type":32,"tag":173,"props":618,"children":619},{"style":221},[620],{"type":37,"value":621}," channel\n",{"type":32,"tag":173,"props":623,"children":625},{"class":175,"line":624},16,[626,631,636,641],{"type":32,"tag":173,"props":627,"children":628},{"style":190},[629],{"type":37,"value":630},"  FROM",{"type":32,"tag":173,"props":632,"children":633},{"style":221},[634],{"type":37,"value":635}," {{ ref(",{"type":32,"tag":173,"props":637,"children":638},{"style":201},[639],{"type":37,"value":640},"'users'",{"type":32,"tag":173,"props":642,"children":643},{"style":221},[644],{"type":37,"value":534},{"type":32,"tag":173,"props":646,"children":648},{"class":175,"line":647},17,[649,654,659],{"type":32,"tag":173,"props":650,"children":651},{"style":190},[652],{"type":37,"value":653},"  WHERE",{"type":32,"tag":173,"props":655,"children":656},{"style":221},[657],{"type":37,"value":658}," first_seen_at ",{"type":32,"tag":173,"props":660,"children":661},{"style":190},[662],{"type":37,"value":663},"IS NOT NULL\n",{"type":32,"tag":173,"props":665,"children":667},{"class":175,"line":666},18,[668],{"type":32,"tag":173,"props":669,"children":670},{"style":221},[671],{"type":37,"value":672},"),\n",{"type":32,"tag":173,"props":674,"children":676},{"class":175,"line":675},19,[677],{"type":32,"tag":173,"props":678,"children":679},{"emptyLinePlaceholder":540},[680],{"type":37,"value":543},{"type":32,"tag":173,"props":682,"children":684},{"class":175,"line":683},20,[685,690,694],{"type":32,"tag":173,"props":686,"children":687},{"style":221},[688],{"type":37,"value":689},"daily_activity ",{"type":32,"tag":173,"props":691,"children":692},{"style":190},[693],{"type":37,"value":561},{"type":32,"tag":173,"props":695,"children":696},{"style":221},[697],{"type":37,"value":566},{"type":32,"tag":173,"props":699,"children":701},{"class":175,"line":700},21,[702],{"type":32,"tag":173,"props":703,"children":704},{"style":190},[705],{"type":37,"value":574},{"type":32,"tag":173,"props":707,"children":709},{"class":175,"line":708},22,[710,714,719,723],{"type":32,"tag":173,"props":711,"children":712},{"style":190},[713],{"type":37,"value":582},{"type":32,"tag":173,"props":715,"children":716},{"style":221},[717],{"type":37,"value":718},"(event_timestamp) ",{"type":32,"tag":173,"props":720,"children":721},{"style":190},[722],{"type":37,"value":561},{"type":32,"tag":173,"props":724,"children":725},{"style":221},[726],{"type":37,"value":727}," activity_date,\n",{"type":32,"tag":173,"props":729,"children":731},{"class":175,"line":730},23,[732],{"type":32,"tag":173,"props":733,"children":734},{"style":221},[735],{"type":37,"value":604},{"type":32,"tag":173,"props":737,"children":739},{"class":175,"line":738},24,[740,746,751,756,761,765],{"type":32,"tag":173,"props":741,"children":743},{"style":742},"--shiki-default:#79B8FF",[744],{"type":37,"value":745},"    COUNT",{"type":32,"tag":173,"props":747,"children":748},{"style":221},[749],{"type":37,"value":750},"(",{"type":32,"tag":173,"props":752,"children":753},{"style":190},[754],{"type":37,"value":755},"*",{"type":32,"tag":173,"props":757,"children":758},{"style":221},[759],{"type":37,"value":760},") ",{"type":32,"tag":173,"props":762,"children":763},{"style":190},[764],{"type":37,"value":561},{"type":32,"tag":173,"props":766,"children":767},{"style":221},[768],{"type":37,"value":769}," event_count\n",{"type":32,"tag":173,"props":771,"children":773},{"class":175,"line":772},25,[774,778,782,787],{"type":32,"tag":173,"props":775,"children":776},{"style":190},[777],{"type":37,"value":630},{"type":32,"tag":173,"props":779,"children":780},{"style":221},[781],{"type":37,"value":635},{"type":32,"tag":173,"props":783,"children":784},{"style":201},[785],{"type":37,"value":786},"'events'",{"type":32,"tag":173,"props":788,"children":789},{"style":221},[790],{"type":37,"value":534},{"type":32,"tag":173,"props":792,"children":794},{"class":175,"line":793},26,[795,799,804,809,814,819,824,829],{"type":32,"tag":173,"props":796,"children":797},{"style":190},[798],{"type":37,"value":653},{"type":32,"tag":173,"props":800,"children":801},{"style":221},[802],{"type":37,"value":803}," event_name ",{"type":32,"tag":173,"props":805,"children":806},{"style":190},[807],{"type":37,"value":808},"IN",{"type":32,"tag":173,"props":810,"children":811},{"style":221},[812],{"type":37,"value":813}," (",{"type":32,"tag":173,"props":815,"children":816},{"style":201},[817],{"type":37,"value":818},"'page_view'",{"type":32,"tag":173,"props":820,"children":821},{"style":221},[822],{"type":37,"value":823},", ",{"type":32,"tag":173,"props":825,"children":826},{"style":201},[827],{"type":37,"value":828},"'purchase'",{"type":32,"tag":173,"props":830,"children":831},{"style":221},[832],{"type":37,"value":833},")\n",{"type":32,"tag":173,"props":835,"children":837},{"class":175,"line":836},27,[838,843,848],{"type":32,"tag":173,"props":839,"children":840},{"style":221},[841],{"type":37,"value":842},"  {% ",{"type":32,"tag":173,"props":844,"children":845},{"style":190},[846],{"type":37,"value":847},"if",{"type":32,"tag":173,"props":849,"children":850},{"style":221},[851],{"type":37,"value":852}," is_incremental() %}\n",{"type":32,"tag":173,"props":854,"children":856},{"class":175,"line":855},28,[857,862,867,871,876,881,886],{"type":32,"tag":173,"props":858,"children":859},{"style":190},[860],{"type":37,"value":861},"    AND",{"type":32,"tag":173,"props":863,"children":864},{"style":190},[865],{"type":37,"value":866}," DATE",{"type":32,"tag":173,"props":868,"children":869},{"style":221},[870],{"type":37,"value":718},{"type":32,"tag":173,"props":872,"children":873},{"style":190},[874],{"type":37,"value":875},">=",{"type":32,"tag":173,"props":877,"children":878},{"style":221},[879],{"type":37,"value":880}," CURRENT_DATE() ",{"type":32,"tag":173,"props":882,"children":883},{"style":190},[884],{"type":37,"value":885},"-",{"type":32,"tag":173,"props":887,"children":888},{"style":742},[889],{"type":37,"value":890}," 7\n",{"type":32,"tag":173,"props":892,"children":894},{"class":175,"line":893},29,[895],{"type":32,"tag":173,"props":896,"children":897},{"style":221},[898],{"type":37,"value":899},"  {% endif %}\n",{"type":32,"tag":173,"props":901,"children":903},{"class":175,"line":902},30,[904,909,914,918],{"type":32,"tag":173,"props":905,"children":906},{"style":190},[907],{"type":37,"value":908},"  GROUP BY",{"type":32,"tag":173,"props":910,"children":911},{"style":742},[912],{"type":37,"value":913}," 1",{"type":32,"tag":173,"props":915,"children":916},{"style":221},[917],{"type":37,"value":823},{"type":32,"tag":173,"props":919,"children":920},{"style":742},[921],{"type":37,"value":922},"2\n",{"type":32,"tag":173,"props":924,"children":926},{"class":175,"line":925},31,[927],{"type":32,"tag":173,"props":928,"children":929},{"style":221},[930],{"type":37,"value":833},{"type":32,"tag":173,"props":932,"children":934},{"class":175,"line":933},32,[935],{"type":32,"tag":173,"props":936,"children":937},{"emptyLinePlaceholder":540},[938],{"type":37,"value":543},{"type":32,"tag":173,"props":940,"children":942},{"class":175,"line":941},33,[943],{"type":32,"tag":173,"props":944,"children":945},{"style":190},[946],{"type":37,"value":261},{"type":32,"tag":173,"props":948,"children":950},{"class":175,"line":949},34,[951,956,961,966,971],{"type":32,"tag":173,"props":952,"children":953},{"style":742},[954],{"type":37,"value":955},"  a",{"type":32,"tag":173,"props":957,"children":958},{"style":221},[959],{"type":37,"value":960},".",{"type":32,"tag":173,"props":962,"children":963},{"style":742},[964],{"type":37,"value":965},"activity_date",{"type":32,"tag":173,"props":967,"children":968},{"style":190},[969],{"type":37,"value":970}," AS",{"type":32,"tag":173,"props":972,"children":973},{"style":221},[974],{"type":37,"value":975}," observation_date,\n",{"type":32,"tag":173,"props":977,"children":979},{"class":175,"line":978},35,[980,985,989,993],{"type":32,"tag":173,"props":981,"children":982},{"style":742},[983],{"type":37,"value":984},"  c",{"type":32,"tag":173,"props":986,"children":987},{"style":221},[988],{"type":37,"value":960},{"type":32,"tag":173,"props":990,"children":991},{"style":742},[992],{"type":37,"value":73},{"type":32,"tag":173,"props":994,"children":995},{"style":221},[996],{"type":37,"value":428},{"type":32,"tag":173,"props":998,"children":1000},{"class":175,"line":999},36,[1001,1005,1009,1014],{"type":32,"tag":173,"props":1002,"children":1003},{"style":742},[1004],{"type":37,"value":984},{"type":32,"tag":173,"props":1006,"children":1007},{"style":221},[1008],{"type":37,"value":960},{"type":32,"tag":173,"props":1010,"children":1011},{"style":742},[1012],{"type":37,"value":1013},"channel",{"type":32,"tag":173,"props":1015,"children":1016},{"style":221},[1017],{"type":37,"value":428},{"type":32,"tag":173,"props":1019,"children":1021},{"class":175,"line":1020},37,[1022,1027,1032,1036,1040,1044,1049,1053,1057,1061,1066,1070,1074],{"type":32,"tag":173,"props":1023,"children":1024},{"style":221},[1025],{"type":37,"value":1026},"  DATE_DIFF(",{"type":32,"tag":173,"props":1028,"children":1029},{"style":742},[1030],{"type":37,"value":1031},"a",{"type":32,"tag":173,"props":1033,"children":1034},{"style":221},[1035],{"type":37,"value":960},{"type":32,"tag":173,"props":1037,"children":1038},{"style":742},[1039],{"type":37,"value":965},{"type":32,"tag":173,"props":1041,"children":1042},{"style":221},[1043],{"type":37,"value":823},{"type":32,"tag":173,"props":1045,"children":1046},{"style":742},[1047],{"type":37,"value":1048},"c",{"type":32,"tag":173,"props":1050,"children":1051},{"style":221},[1052],{"type":37,"value":960},{"type":32,"tag":173,"props":1054,"children":1055},{"style":742},[1056],{"type":37,"value":73},{"type":32,"tag":173,"props":1058,"children":1059},{"style":221},[1060],{"type":37,"value":823},{"type":32,"tag":173,"props":1062,"children":1063},{"style":190},[1064],{"type":37,"value":1065},"DAY",{"type":32,"tag":173,"props":1067,"children":1068},{"style":221},[1069],{"type":37,"value":760},{"type":32,"tag":173,"props":1071,"children":1072},{"style":190},[1073],{"type":37,"value":561},{"type":32,"tag":173,"props":1075,"children":1076},{"style":221},[1077],{"type":37,"value":1078}," day_n,\n",{"type":32,"tag":173,"props":1080,"children":1082},{"class":175,"line":1081},38,[1083,1088,1092,1097,1102,1106,1111,1115,1119],{"type":32,"tag":173,"props":1084,"children":1085},{"style":742},[1086],{"type":37,"value":1087},"  COUNT",{"type":32,"tag":173,"props":1089,"children":1090},{"style":221},[1091],{"type":37,"value":750},{"type":32,"tag":173,"props":1093,"children":1094},{"style":190},[1095],{"type":37,"value":1096},"DISTINCT",{"type":32,"tag":173,"props":1098,"children":1099},{"style":742},[1100],{"type":37,"value":1101}," c",{"type":32,"tag":173,"props":1103,"children":1104},{"style":221},[1105],{"type":37,"value":960},{"type":32,"tag":173,"props":1107,"children":1108},{"style":742},[1109],{"type":37,"value":1110},"user_id",{"type":32,"tag":173,"props":1112,"children":1113},{"style":221},[1114],{"type":37,"value":760},{"type":32,"tag":173,"props":1116,"children":1117},{"style":190},[1118],{"type":37,"value":561},{"type":32,"tag":173,"props":1120,"children":1121},{"style":221},[1122],{"type":37,"value":1123}," cohort_size,\n",{"type":32,"tag":173,"props":1125,"children":1127},{"class":175,"line":1126},39,[1128,1132,1136,1140,1145,1149,1153,1157,1161],{"type":32,"tag":173,"props":1129,"children":1130},{"style":742},[1131],{"type":37,"value":1087},{"type":32,"tag":173,"props":1133,"children":1134},{"style":221},[1135],{"type":37,"value":750},{"type":32,"tag":173,"props":1137,"children":1138},{"style":190},[1139],{"type":37,"value":1096},{"type":32,"tag":173,"props":1141,"children":1142},{"style":742},[1143],{"type":37,"value":1144}," a",{"type":32,"tag":173,"props":1146,"children":1147},{"style":221},[1148],{"type":37,"value":960},{"type":32,"tag":173,"props":1150,"children":1151},{"style":742},[1152],{"type":37,"value":1110},{"type":32,"tag":173,"props":1154,"children":1155},{"style":221},[1156],{"type":37,"value":760},{"type":32,"tag":173,"props":1158,"children":1159},{"style":190},[1160],{"type":37,"value":561},{"type":32,"tag":173,"props":1162,"children":1163},{"style":221},[1164],{"type":37,"value":1165}," active_users,\n",{"type":32,"tag":173,"props":1167,"children":1169},{"class":175,"line":1168},40,[1170,1175,1180,1184,1188,1192,1196,1200,1205,1209,1213,1217,1221,1225,1229,1234,1238],{"type":32,"tag":173,"props":1171,"children":1172},{"style":221},[1173],{"type":37,"value":1174},"  SAFE_DIVIDE(",{"type":32,"tag":173,"props":1176,"children":1177},{"style":742},[1178],{"type":37,"value":1179},"COUNT",{"type":32,"tag":173,"props":1181,"children":1182},{"style":221},[1183],{"type":37,"value":750},{"type":32,"tag":173,"props":1185,"children":1186},{"style":190},[1187],{"type":37,"value":1096},{"type":32,"tag":173,"props":1189,"children":1190},{"style":742},[1191],{"type":37,"value":1144},{"type":32,"tag":173,"props":1193,"children":1194},{"style":221},[1195],{"type":37,"value":960},{"type":32,"tag":173,"props":1197,"children":1198},{"style":742},[1199],{"type":37,"value":1110},{"type":32,"tag":173,"props":1201,"children":1202},{"style":221},[1203],{"type":37,"value":1204},"), ",{"type":32,"tag":173,"props":1206,"children":1207},{"style":742},[1208],{"type":37,"value":1179},{"type":32,"tag":173,"props":1210,"children":1211},{"style":221},[1212],{"type":37,"value":750},{"type":32,"tag":173,"props":1214,"children":1215},{"style":190},[1216],{"type":37,"value":1096},{"type":32,"tag":173,"props":1218,"children":1219},{"style":742},[1220],{"type":37,"value":1101},{"type":32,"tag":173,"props":1222,"children":1223},{"style":221},[1224],{"type":37,"value":960},{"type":32,"tag":173,"props":1226,"children":1227},{"style":742},[1228],{"type":37,"value":1110},{"type":32,"tag":173,"props":1230,"children":1231},{"style":221},[1232],{"type":37,"value":1233},")) ",{"type":32,"tag":173,"props":1235,"children":1236},{"style":190},[1237],{"type":37,"value":561},{"type":32,"tag":173,"props":1239,"children":1240},{"style":221},[1241],{"type":37,"value":1242}," retention_rate\n",{"type":32,"tag":173,"props":1244,"children":1246},{"class":175,"line":1245},41,[1247,1251],{"type":32,"tag":173,"props":1248,"children":1249},{"style":190},[1250],{"type":37,"value":341},{"type":32,"tag":173,"props":1252,"children":1253},{"style":221},[1254],{"type":37,"value":1255}," daily_cohorts c\n",{"type":32,"tag":173,"props":1257,"children":1259},{"class":175,"line":1258},42,[1260,1265],{"type":32,"tag":173,"props":1261,"children":1262},{"style":190},[1263],{"type":37,"value":1264},"LEFT JOIN",{"type":32,"tag":173,"props":1266,"children":1267},{"style":221},[1268],{"type":37,"value":1269}," daily_activity a\n",{"type":32,"tag":173,"props":1271,"children":1273},{"class":175,"line":1272},43,[1274,1279,1283,1287,1291,1296,1300,1304],{"type":32,"tag":173,"props":1275,"children":1276},{"style":190},[1277],{"type":37,"value":1278},"  ON",{"type":32,"tag":173,"props":1280,"children":1281},{"style":742},[1282],{"type":37,"value":1101},{"type":32,"tag":173,"props":1284,"children":1285},{"style":221},[1286],{"type":37,"value":960},{"type":32,"tag":173,"props":1288,"children":1289},{"style":742},[1290],{"type":37,"value":1110},{"type":32,"tag":173,"props":1292,"children":1293},{"style":190},[1294],{"type":37,"value":1295}," =",{"type":32,"tag":173,"props":1297,"children":1298},{"style":742},[1299],{"type":37,"value":1144},{"type":32,"tag":173,"props":1301,"children":1302},{"style":221},[1303],{"type":37,"value":960},{"type":32,"tag":173,"props":1305,"children":1306},{"style":742},[1307],{"type":37,"value":1308},"user_id\n",{"type":32,"tag":173,"props":1310,"children":1312},{"class":175,"line":1311},44,[1313,1318,1322,1326,1330,1335,1339,1343],{"type":32,"tag":173,"props":1314,"children":1315},{"style":190},[1316],{"type":37,"value":1317},"WHERE",{"type":32,"tag":173,"props":1319,"children":1320},{"style":742},[1321],{"type":37,"value":1144},{"type":32,"tag":173,"props":1323,"children":1324},{"style":221},[1325],{"type":37,"value":960},{"type":32,"tag":173,"props":1327,"children":1328},{"style":742},[1329],{"type":37,"value":965},{"type":32,"tag":173,"props":1331,"children":1332},{"style":190},[1333],{"type":37,"value":1334}," >=",{"type":32,"tag":173,"props":1336,"children":1337},{"style":742},[1338],{"type":37,"value":1101},{"type":32,"tag":173,"props":1340,"children":1341},{"style":221},[1342],{"type":37,"value":960},{"type":32,"tag":173,"props":1344,"children":1345},{"style":742},[1346],{"type":37,"value":1347},"cohort_date\n",{"type":32,"tag":173,"props":1349,"children":1351},{"class":175,"line":1350},45,[1352,1357,1361],{"type":32,"tag":173,"props":1353,"children":1354},{"style":221},[1355],{"type":37,"value":1356},"{% ",{"type":32,"tag":173,"props":1358,"children":1359},{"style":190},[1360],{"type":37,"value":847},{"type":32,"tag":173,"props":1362,"children":1363},{"style":221},[1364],{"type":37,"value":852},{"type":32,"tag":173,"props":1366,"children":1368},{"class":175,"line":1367},46,[1369,1374,1378,1382,1386,1390,1394,1398],{"type":32,"tag":173,"props":1370,"children":1371},{"style":190},[1372],{"type":37,"value":1373},"  AND",{"type":32,"tag":173,"props":1375,"children":1376},{"style":742},[1377],{"type":37,"value":1144},{"type":32,"tag":173,"props":1379,"children":1380},{"style":221},[1381],{"type":37,"value":960},{"type":32,"tag":173,"props":1383,"children":1384},{"style":742},[1385],{"type":37,"value":965},{"type":32,"tag":173,"props":1387,"children":1388},{"style":190},[1389],{"type":37,"value":1334},{"type":32,"tag":173,"props":1391,"children":1392},{"style":221},[1393],{"type":37,"value":880},{"type":32,"tag":173,"props":1395,"children":1396},{"style":190},[1397],{"type":37,"value":885},{"type":32,"tag":173,"props":1399,"children":1400},{"style":742},[1401],{"type":37,"value":890},{"type":32,"tag":173,"props":1403,"children":1405},{"class":175,"line":1404},47,[1406],{"type":32,"tag":173,"props":1407,"children":1408},{"style":221},[1409],{"type":37,"value":1410},"{% endif %}\n",{"type":32,"tag":173,"props":1412,"children":1414},{"class":175,"line":1413},48,[1415,1420,1424,1428,1433,1437,1442,1446],{"type":32,"tag":173,"props":1416,"children":1417},{"style":190},[1418],{"type":37,"value":1419},"GROUP BY",{"type":32,"tag":173,"props":1421,"children":1422},{"style":742},[1423],{"type":37,"value":913},{"type":32,"tag":173,"props":1425,"children":1426},{"style":221},[1427],{"type":37,"value":823},{"type":32,"tag":173,"props":1429,"children":1430},{"style":742},[1431],{"type":37,"value":1432},"2",{"type":32,"tag":173,"props":1434,"children":1435},{"style":221},[1436],{"type":37,"value":823},{"type":32,"tag":173,"props":1438,"children":1439},{"style":742},[1440],{"type":37,"value":1441},"3",{"type":32,"tag":173,"props":1443,"children":1444},{"style":221},[1445],{"type":37,"value":823},{"type":32,"tag":173,"props":1447,"children":1448},{"style":742},[1449],{"type":37,"value":1450},"4\n",{"type":32,"tag":33,"props":1452,"children":1453},{},[1454],{"type":37,"value":1455},"Lorsque ce modèle s'exécute chaque jour, il écrase seulement les partitions des 7 derniers jours. Le coût de traitement BigQuery diminue de 20 GB par jour à 2 GB. Économie annuelle : $2400+ en coûts de requête.",{"type":32,"tag":1457,"props":1458,"children":1460},"h3",{"id":1459},"sélection-de-la-clé-de-clustering",[1461],{"type":37,"value":1462},"Sélection de la clé de clustering",{"type":32,"tag":33,"props":1464,"children":1465},{},[1466],{"type":37,"value":1467},"Le partitionnement seul ne suffit pas, le clustering est également nécessaire. Une table cohort peut être filtrée sur 3 dimensions : cohort_date (temps), channel (source), device_category (appareil). Dans BigQuery, l'ordre de la clé de clustering est important : le champ avec la cardinalité la plus élevée doit être en premier.",{"type":32,"tag":33,"props":1469,"children":1470},{},[1471],{"type":37,"value":1472},"Analyse de cardinalité :",{"type":32,"tag":1474,"props":1475,"children":1476},"ul",{},[1477,1488,1498],{"type":32,"tag":1478,"props":1479,"children":1480},"li",{},[1481,1486],{"type":32,"tag":68,"props":1482,"children":1484},{"className":1483},[],[1485],{"type":37,"value":73},{"type":37,"value":1487}," : 365 valeurs (1 an)",{"type":32,"tag":1478,"props":1489,"children":1490},{},[1491,1496],{"type":32,"tag":68,"props":1492,"children":1494},{"className":1493},[],[1495],{"type":37,"value":1013},{"type":37,"value":1497}," : 15-20 valeurs (organic, paid_search, social, email...)",{"type":32,"tag":1478,"props":1499,"children":1500},{},[1501,1507],{"type":32,"tag":68,"props":1502,"children":1504},{"className":1503},[],[1505],{"type":37,"value":1506},"device_category",{"type":37,"value":1508}," : 3-4 valeurs (desktop, mobile, tablet)",{"type":32,"tag":33,"props":1510,"children":1511},{},[1512,1514,1520],{"type":37,"value":1513},"Ordre correct : ",{"type":32,"tag":68,"props":1515,"children":1517},{"className":1516},[],[1518],{"type":37,"value":1519},"CLUSTER BY cohort_date, channel, device_category",{"type":37,"value":1521},". Cet ordre accélère 10x les requêtes comme « Taux de rétention au jour 30 pour les utilisateurs mobiles d'Instagram du Q4 2025 ».",{"type":32,"tag":40,"props":1523,"children":1525},{"id":1524},"optimisation-des-coûts-de-requête-profondeur-de-pré-agrégation",[1526],{"type":37,"value":1527},"Optimisation des coûts de requête : profondeur de pré-agrégation",{"type":32,"tag":33,"props":1529,"children":1530},{},[1531],{"type":37,"value":1532},"Le niveau de granularité de la table cohort détermine également l'équilibre coût-performance. Stockez-vous une ligne séparée pour chaque combinaison cohort × channel × device × day_n, ou seulement un total général ?",{"type":32,"tag":33,"props":1534,"children":1535},{},[1536,1541],{"type":32,"tag":107,"props":1537,"children":1538},{},[1539],{"type":37,"value":1540},"Option 1 : Table granulaire",{"type":37,"value":1542}," — chaque combinaison cohort × channel × device × day_n en ligne séparée. Nombre total de lignes : 365 cohorts × 20 channels × 4 devices × 90 jours = 2,6 millions de lignes. Avantage : l'analyste peut effectuer un pivot sur le segment souhaité. Inconvénient : coût de stockage plus élevé ($50\u002FTB → ~$0,15 par mois).",{"type":32,"tag":33,"props":1544,"children":1545},{},[1546,1551],{"type":32,"tag":107,"props":1547,"children":1548},{},[1549],{"type":37,"value":1550},"Option 2 : Table agrégée",{"type":37,"value":1552}," — seulement cohort × day_n, sans ventilation par channel ou device. Nombre total de lignes : 365 × 90 = 32 850 lignes. Avantage : stockage et coûts de requête minimaux. Inconvénient : impossible de ventiler par channel.",{"type":32,"tag":33,"props":1554,"children":1555},{},[1556,1558,1563],{"type":37,"value":1557},"La bonne approche est une ",{"type":32,"tag":107,"props":1559,"children":1560},{},[1561],{"type":37,"value":1562},"architecture à deux niveaux",{"type":37,"value":1564}," : métriques core granulaires (avec ventilation par channel et device), métriques extended agrégées (seulement cohort_date × day_n). Cette structure optimise le stockage tout en maintenant la flexibilité analytique. La table core metrics alimente les dashboards, la table extended metrics est utilisée pour l'analyse ad-hoc.",{"type":32,"tag":33,"props":1566,"children":1567},{},[1568],{"type":37,"value":1569},"Définissez également une politique d'expiration de partition BigQuery : les partitions de plus de 90 jours sont automatiquement supprimées. L'analyse de rétention ne regarde généralement pas au-delà de 90 jours, cette politique réduit le coût annuel de stockage de 60 %.",{"type":32,"tag":40,"props":1571,"children":1573},{"id":1572},"résoudre-le-problème-de-résolution-didentité-au-niveau-cohort",[1574],{"type":37,"value":1575},"Résoudre le problème de résolution d'identité au niveau cohort",{"type":32,"tag":33,"props":1577,"children":1578},{},[1579],{"type":37,"value":1580},"Le point le plus obscur de l'analyse cohort : les collisions d'user_id et la résolution d'identité. Si un utilisateur s'inscrit sur desktop et effectue des transactions sur mobile, deux user_id différents sont créés. Si la table cohort ne fusionne pas ces deux identités, la rétention est calculée 20 % plus basse.",{"type":32,"tag":33,"props":1582,"children":1583},{},[1584,1586,1592,1594,1602,1604,1610,1612,1618],{"type":37,"value":1585},"La solution : avant de créer la table cohort, fusionnez avec la table de graphe d'identité. Le sélecteur ",{"type":32,"tag":68,"props":1587,"children":1589},{"className":1588},[],[1590],{"type":37,"value":1591},"canonical_user_id",{"type":37,"value":1593}," que vous avez configuré dans votre processus ",{"type":32,"tag":1031,"props":1595,"children":1599},{"href":1596,"rel":1597},"https:\u002F\u002Fwww.roibase.com.tr\u002Ffr\u002Ffirstparty",[1598],"nofollow",[1600],{"type":37,"value":1601},"Données First-Party & Architecture de Mesure",{"type":37,"value":1603}," entre en jeu ici. Dans le modèle dbt, utilisez la vue ",{"type":32,"tag":68,"props":1605,"children":1607},{"className":1606},[],[1608],{"type":37,"value":1609},"users_unified",{"type":37,"value":1611}," plutôt que la table ",{"type":32,"tag":68,"props":1613,"children":1615},{"className":1614},[],[1616],{"type":37,"value":1617},"users",{"type":37,"value":960},{"type":32,"tag":163,"props":1620,"children":1622},{"className":165,"code":1621,"language":167,"meta":16,"style":16},"WITH unified_users AS (\n  SELECT\n    canonical_user_id,\n    MIN(first_seen_at) AS cohort_date,\n    ARRAY_AGG(DISTINCT acquisition_channel IGNORE NULLS ORDER BY first_seen_at LIMIT 1)[OFFSET(0)] AS channel\n  FROM {{ ref('users_unified') }}\n  GROUP BY 1\n)\n",[1623],{"type":32,"tag":68,"props":1624,"children":1625},{"__ignoreMap":16},[1626,1646,1653,1661,1681,1739,1759,1771],{"type":32,"tag":173,"props":1627,"children":1628},{"class":175,"line":176},[1629,1633,1638,1642],{"type":32,"tag":173,"props":1630,"children":1631},{"style":190},[1632],{"type":37,"value":551},{"type":32,"tag":173,"props":1634,"children":1635},{"style":221},[1636],{"type":37,"value":1637}," unified_users ",{"type":32,"tag":173,"props":1639,"children":1640},{"style":190},[1641],{"type":37,"value":561},{"type":32,"tag":173,"props":1643,"children":1644},{"style":221},[1645],{"type":37,"value":566},{"type":32,"tag":173,"props":1647,"children":1648},{"class":175,"line":186},[1649],{"type":32,"tag":173,"props":1650,"children":1651},{"style":190},[1652],{"type":37,"value":574},{"type":32,"tag":173,"props":1654,"children":1655},{"class":175,"line":207},[1656],{"type":32,"tag":173,"props":1657,"children":1658},{"style":221},[1659],{"type":37,"value":1660},"    canonical_user_id,\n",{"type":32,"tag":173,"props":1662,"children":1663},{"class":175,"line":227},[1664,1669,1673,1677],{"type":32,"tag":173,"props":1665,"children":1666},{"style":742},[1667],{"type":37,"value":1668},"    MIN",{"type":32,"tag":173,"props":1670,"children":1671},{"style":221},[1672],{"type":37,"value":587},{"type":32,"tag":173,"props":1674,"children":1675},{"style":190},[1676],{"type":37,"value":561},{"type":32,"tag":173,"props":1678,"children":1679},{"style":221},[1680],{"type":37,"value":596},{"type":32,"tag":173,"props":1682,"children":1683},{"class":175,"line":246},[1684,1689,1693,1698,1703,1708,1713,1717,1722,1726,1731,1735],{"type":32,"tag":173,"props":1685,"children":1686},{"style":221},[1687],{"type":37,"value":1688},"    ARRAY_AGG(",{"type":32,"tag":173,"props":1690,"children":1691},{"style":190},[1692],{"type":37,"value":1096},{"type":32,"tag":173,"props":1694,"children":1695},{"style":221},[1696],{"type":37,"value":1697}," acquisition_channel ",{"type":32,"tag":173,"props":1699,"children":1700},{"style":190},[1701],{"type":37,"value":1702},"IGNORE",{"type":32,"tag":173,"props":1704,"children":1705},{"style":190},[1706],{"type":37,"value":1707}," NULLS",{"type":32,"tag":173,"props":1709,"children":1710},{"style":190},[1711],{"type":37,"value":1712}," ORDER BY",{"type":32,"tag":173,"props":1714,"children":1715},{"style":221},[1716],{"type":37,"value":658},{"type":32,"tag":173,"props":1718,"children":1719},{"style":190},[1720],{"type":37,"value":1721},"LIMIT",{"type":32,"tag":173,"props":1723,"children":1724},{"style":742},[1725],{"type":37,"value":913},{"type":32,"tag":173,"props":1727,"children":1728},{"style":221},[1729],{"type":37,"value":1730},")[OFFSET(0)] ",{"type":32,"tag":173,"props":1732,"children":1733},{"style":190},[1734],{"type":37,"value":561},{"type":32,"tag":173,"props":1736,"children":1737},{"style":221},[1738],{"type":37,"value":621},{"type":32,"tag":173,"props":1740,"children":1741},{"class":175,"line":255},[1742,1746,1750,1755],{"type":32,"tag":173,"props":1743,"children":1744},{"style":190},[1745],{"type":37,"value":630},{"type":32,"tag":173,"props":1747,"children":1748},{"style":221},[1749],{"type":37,"value":635},{"type":32,"tag":173,"props":1751,"children":1752},{"style":201},[1753],{"type":37,"value":1754},"'users_unified'",{"type":32,"tag":173,"props":1756,"children":1757},{"style":221},[1758],{"type":37,"value":534},{"type":32,"tag":173,"props":1760,"children":1761},{"class":175,"line":264},[1762,1766],{"type":32,"tag":173,"props":1763,"children":1764},{"style":190},[1765],{"type":37,"value":908},{"type":32,"tag":173,"props":1767,"children":1768},{"style":742},[1769],{"type":37,"value":1770}," 1\n",{"type":32,"tag":173,"props":1772,"children":1773},{"class":175,"line":273},[1774],{"type":32,"tag":173,"props":1775,"children":1776},{"style":221},[1777],{"type":37,"value":833},{"type":32,"tag":33,"props":1779,"children":1780},{},[1781],{"type":37,"value":1782},"Cette approche calcule correctement la rétention cross-device. En production, elle génère une différence de 15-25 % sur la rétention. Lorsque la table de résolution d'identité est mise à jour, la table cohort doit également être rématérialisée — c'est pourquoi vous devez définir une dépendance dans le DAG dbt :",{"type":32,"tag":163,"props":1784,"children":1788},{"className":1785,"code":1786,"language":1787,"meta":16,"style":16},"language-yaml shiki shiki-themes github-dark","models:\n  - name: cohort_retention_snapshot\n    config:\n      materialized: incremental\n    depends_on:\n      - ref('users_unified')\n","yaml",[1789],{"type":32,"tag":68,"props":1790,"children":1791},{"__ignoreMap":16},[1792,1806,1828,1840,1857,1869],{"type":32,"tag":173,"props":1793,"children":1794},{"class":175,"line":176},[1795,1801],{"type":32,"tag":173,"props":1796,"children":1798},{"style":1797},"--shiki-default:#85E89D",[1799],{"type":37,"value":1800},"models",{"type":32,"tag":173,"props":1802,"children":1803},{"style":221},[1804],{"type":37,"value":1805},":\n",{"type":32,"tag":173,"props":1807,"children":1808},{"class":175,"line":186},[1809,1814,1819,1823],{"type":32,"tag":173,"props":1810,"children":1811},{"style":221},[1812],{"type":37,"value":1813},"  - ",{"type":32,"tag":173,"props":1815,"children":1816},{"style":1797},[1817],{"type":37,"value":1818},"name",{"type":32,"tag":173,"props":1820,"children":1821},{"style":221},[1822],{"type":37,"value":458},{"type":32,"tag":173,"props":1824,"children":1825},{"style":201},[1826],{"type":37,"value":1827},"cohort_retention_snapshot\n",{"type":32,"tag":173,"props":1829,"children":1830},{"class":175,"line":207},[1831,1836],{"type":32,"tag":173,"props":1832,"children":1833},{"style":1797},[1834],{"type":37,"value":1835},"    config",{"type":32,"tag":173,"props":1837,"children":1838},{"style":221},[1839],{"type":37,"value":1805},{"type":32,"tag":173,"props":1841,"children":1842},{"class":175,"line":227},[1843,1848,1852],{"type":32,"tag":173,"props":1844,"children":1845},{"style":1797},[1846],{"type":37,"value":1847},"      materialized",{"type":32,"tag":173,"props":1849,"children":1850},{"style":221},[1851],{"type":37,"value":458},{"type":32,"tag":173,"props":1853,"children":1854},{"style":201},[1855],{"type":37,"value":1856},"incremental\n",{"type":32,"tag":173,"props":1858,"children":1859},{"class":175,"line":246},[1860,1865],{"type":32,"tag":173,"props":1861,"children":1862},{"style":1797},[1863],{"type":37,"value":1864},"    depends_on",{"type":32,"tag":173,"props":1866,"children":1867},{"style":221},[1868],{"type":37,"value":1805},{"type":32,"tag":173,"props":1870,"children":1871},{"class":175,"line":255},[1872,1877],{"type":32,"tag":173,"props":1873,"children":1874},{"style":221},[1875],{"type":37,"value":1876},"      - ",{"type":32,"tag":173,"props":1878,"children":1879},{"style":201},[1880],{"type":37,"value":1881},"ref('users_unified')\n",{"type":32,"tag":40,"props":1883,"children":1885},{"id":1884},"checklist-de-production-monitoring-et-alerting",[1886],{"type":37,"value":1887},"Checklist de production : monitoring et alerting",{"type":32,"tag":33,"props":1889,"children":1890},{},[1891],{"type":37,"value":1892},"Lorsque la table cohort est déployée en production, surveillez continuellement 3 métriques :",{"type":32,"tag":1894,"props":1895,"children":1896},"ol",{},[1897,1915,1932],{"type":32,"tag":1478,"props":1898,"children":1899},{},[1900,1905,1907,1913],{"type":32,"tag":107,"props":1901,"children":1902},{},[1903],{"type":37,"value":1904},"Fraîcheur (Freshness) :",{"type":37,"value":1906}," Quand la dernière partition a-t-elle été mise à jour ? Définissez un test ",{"type":32,"tag":68,"props":1908,"children":1910},{"className":1909},[],[1911],{"type":37,"value":1912},"freshness",{"type":37,"value":1914}," dans dbt-core, envoyez une alerte Slack si une partition est plus ancienne que 24 heures.",{"type":32,"tag":1478,"props":1916,"children":1917},{},[1918,1923,1925,1931],{"type":32,"tag":107,"props":1919,"children":1920},{},[1921],{"type":37,"value":1922},"Dérive du nombre de lignes :",{"type":37,"value":1924}," Si la cohort_size d'aujourd'hui diffère de celle d'hier de plus de 30 %, il y a un problème dans le pipeline de données. Utilisez une requête BigQuery programmée pour vérifier ",{"type":32,"tag":68,"props":1926,"children":1928},{"className":1927},[],[1929],{"type":37,"value":1930},"STDDEV()",{"type":37,"value":960},{"type":32,"tag":1478,"props":1933,"children":1934},{},[1935,1940],{"type":32,"tag":107,"props":1936,"children":1937},{},[1938],{"type":37,"value":1939},"Pic de coûts de requête :",{"type":37,"value":1941}," Si le coût moyen des requêtes sur la table cohort passe de $0,01 à $0,10, c'est que le partition pruning ne fonctionne pas. Vérifiez la table INFORMATION_SCHEMA.JOBS.",{"type":32,"tag":33,"props":1943,"children":1944},{},[1945],{"type":37,"value":1946},"Créez un dashboard Google Cloud Monitoring pour ces 3 métriques. Déclenchez une intégration PagerDuty si un seuil est dépassé. L'architecture cohort de production n'est pas un système « build and forget », il demande une surveillance continue.",{"type":32,"tag":33,"props":1948,"children":1949},{},[1950],{"type":37,"value":1951},"Lorsqu'une architecture de table cohort est correctement configurée, l'analyse de rétention devient un produit d'ingénierie : elle se met à jour chaque matin, l'analyste extrait des insights en 3 secondes, les coûts de requête sont prévisibles. La stratégie de partition BigQuery, le modèle dbt incrémental et l'intégration de résolution d'identité sont les 3 piliers de cette architecture. Pour une analyse cohort scalable en production, il faut creuser profondément la technique — mais en retour, vous obtenez des économies mesurables : $5000+ d'économie annuelle en coûts de requête et des métriques de rétention 20 % plus précises.",{"type":32,"tag":1953,"props":1954,"children":1955},"style",{},[1956],{"type":37,"value":1957},"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":207,"depth":207,"links":1959},[1960,1961,1963,1966,1967,1968],{"id":42,"depth":186,"text":45},{"id":63,"depth":186,"text":1962},"Stratégie de partitionnement : cohort_date ou observation_date ?",{"id":349,"depth":186,"text":352,"children":1964},[1965],{"id":1459,"depth":207,"text":1462},{"id":1524,"depth":186,"text":1527},{"id":1572,"depth":186,"text":1575},{"id":1884,"depth":186,"text":1887},"markdown","content:fr:data:architecture-table-cohort-analyse-retention.md","content","fr\u002Fdata\u002Farchitecture-table-cohort-analyse-retention.md","fr\u002Fdata\u002Farchitecture-table-cohort-analyse-retention","md",1785103524754]