一、 需求分析与设计目标
  1. 数据源

    • 用户基本信息:用户ID、性别、出生日期、注册时间、常驻地域(省、市、区)、职业等。

    • 用户体检报告:每次体检的报告ID、体检时间、各项指标(如血压、血糖、血脂、BMI等)。

    • 用户关注的保健品:用户ID、关注/浏览/收藏的保健品ID、行为时间、行为类型(点击、收藏、加购)、保健品品类等。

  2. 核心需求

    • 支持以用户为主体的 360° 视图查询。

    • 支持在时间(年、季度、月、周、日)和地域(国家、省、市)维度上进行灵活的上卷(Roll-up)和下钻(Drill-down)分析。

    • 支持对用户标签(如“高血压风险人群”、“VC补充剂潜在客户”)的快速群体圈选和统计分析。

    • 查询响应速度快,即使在大数据量下也能亚秒级响应。

  3. 设计目标

    • 高性能:利用 Doris 的预聚合、列式存储和索引技术实现极速查询。

    • 可扩展性:模型能够轻松应对数据量的持续增长。

    • 易维护性:表结构清晰,数据更新和ETL流程高效。


二、 技术选型与 Doris 特性利用

选择 Apache Doris 的原因及其核心特性的利用:

  • MPP 架构:天然支持大规模并行处理,适合复杂的分析查询。

  • 列式存储:高压缩比,查询时只需读取相关列,极大降低 I/O。

  • 智能预聚合(Aggregate 模型)本方案核心,可预先计算常用维度的汇总数据,使聚合查询速度极快。

  • 分区与分桶:支持按时间分区,便于数据管理(如淘汰旧数据)和查询时剪枝。结合分桶(Hash分桶)实现数据均匀分布和高效点查。

  • 物化视图(Materialized View)另一核心,可自动或手动为不同维度组合创建预聚合表,查询时路由到最优的物化视图,灵活支持上卷下钻。

  • Duplicate 模型:用于存储需要保留原始明细数据的表,如用户行为流水。

  • 高效数据导入:支持 Broker Load / Stream Load / Routine Load,便于从 Kafka、HDFS、MySQL 等数据源批量或实时导入数据。


三、 数据模型详细设计

建议采用维度建模的思想,构建雪花模型或星型模型。这里我们采用星型模型,以保持查询的简洁和高效。

1. ODS 层(操作数据层)

  • 目的:贴源数据层,结构与数据源保持一致。

  • 表设计:使用 Duplicate 模型,保留原始明细。

    • ods_user_basic (用户基本信息表)

    • ods_user_medical_report (用户体检报告表)

    • ods_user_behavior (用户保健品关注行为表)

  • 数据导入:使用 Routine Load 从 Kafka 实时接入用户行为数据,使用 Broker Load 每天批量导入体检报告和基本信息变更数据。

2. DWD 层(数据明细层)

  • 目的:对 ODS 层数据进行清洗、整合、轻度聚合,形成明细事实表和维度表。

  • 表设计:

    • 事实表

      • dwd_user_medical_fact (用户体检事实表)

        • 模型:Aggregate 模型

        • 分区:按 exam_date (体检日期) 进行 Range Partitioning(按月分区)。

        • 分桶:按 user_id 分桶。

        • 排序键:(user_id, exam_date)

        • Schema:

          sql

          CREATE TABLE dwd_user_medical_fact (`user_id` BIGINT,`exam_date` DATE,           -- 衍生自exam_time`exam_time` DATETIME,`province` VARCHAR(20),`city` VARCHAR(20),`blood_pressure_high` SMALLINT REPLACE_IF_NOT_NULL, -- 替换式聚合`blood_pressure_low` SMALLINT REPLACE_IF_NOT_NULL,`blood_sugar` FLOAT REPLACE_IF_NOT_NULL,`bmi` FLOAT REPLACE_IF_NOT_NULL,-- ... 其他指标`is_high_blood_pressure` BOOLEAN REPLACE, -- 是否高血压,根据指标计算得出`is_high_blood_sugar` BOOLEAN REPLACE     -- 是否高血糖
          ) ENGINE=OLAP
          AGGREGATE KEY(user_id, exam_date, exam_time, province, city)
          PARTITION BY RANGE(exam_date) (...)
          DISTRIBUTED BY HASH(user_id) BUCKETS 10;
      • dwd_user_behavior_fact (用户行为事实表)

        • 模型:Aggregate 模型

        • 分区:按 event_date (行为日期) 分区。

        • 分桶:按 user_id 分桶。

        • 排序键:(user_id, event_date,保健品品类)

        • Schema:

          sql

          CREATE TABLE dwd_user_behavior_fact (`user_id` BIGINT,`event_date` DATE,`event_time` DATETIME,`behavior_type` VARCHAR(20), -- 'click', 'favor', 'cart'`health_product_id` BIGINT,`product_category` VARCHAR(50),`click_count` BIGINT SUM,     -- 计数型聚合`is_latest_behavior` BOOLEAN REPLACE -- 是否为该商品最新行为
          ) ENGINE=OLAP
          AGGREGATE KEY(user_id, event_date, event_time, behavior_type, health_product_id, product_category)
          PARTITION BY RANGE(event_date) (...)
          DISTRIBUTED BY HASH(user_id) BUCKETS 10;
    • 维度表

      • dim_user (用户维度表)

        • 模型:Unique 模型(确保用户唯一性)

        • 分区:可按注册日期分区。

        • 分桶:按 user_id 分桶。

        • Schema:

          sql

          CREATE TABLE dim_user (`user_id` BIGINT,`gender` VARCHAR(10),`birth_date` DATE,`register_date` DATE,`常住省份` VARCHAR(20),`常住城市` VARCHAR(20),`occupation` VARCHAR(50),-- ... 其他属性
          ) ENGINE=OLAP
          UNIQUE KEY(user_id)
          DISTRIBUTED BY HASH(user_id) BUCKETS 10;
        • 时间维度表

CREATE TABLE dim_date (
`date_id` DATE,                           -- 代理键,也是自然键,格式 'YYYY-MM-DD'
`day` TINYINT,                            -- 本月中的第几天 (1-31)
`month` TINYINT,                          -- 年份中的第几月 (1-12)
`quarter` TINYINT,                        -- 年份中的第几季度 (1-4)
`year` SMALLINT,                          -- 年份 (e.g., 2023)
`day_of_week` TINYINT,                    -- 本周中的第几天 (1=Sunday, 7=Saturday)
`week_of_year` TINYINT,                   -- 年份中的第几周 (ISO标准 1-53)
`is_weekend` BOOLEAN,                     -- 是否是周末
`is_holiday` BOOLEAN,                     -- 是否是法定节假日
`holiday_name` VARCHAR(50),               -- 节假日名称 (e.g., '国庆节', '元旦')
`is_workday` BOOLEAN,                     -- 是否是工作日(考虑调休后)
`month_name` VARCHAR(10),                 -- 月份英文缩写 (e.g., 'Jan', 'Feb')
`quarter_name` VARCHAR(2),                -- 季度名称 (e.g., 'Q1', 'Q2')
`year_quarter` VARCHAR(7),                -- 年份季度 (e.g., '2023-Q1')
`year_month` VARCHAR(7),                  -- 年份月份 (e.g., '2023-01')
`year_week` VARCHAR(7),                   -- 年份周数 (e.g., '2023-W01')
`last_year_same_day` DATE,                -- 去年同一天
`last_month_same_day` DATE,               -- 上月同一天(可能为空)
`day_num_in_epoch` INT,                   -- 自某个固定日期(如1970-01-01)以来的天数
`week_begin_date` DATE,                   -- 本周第一天(周日或周一)
`week_end_date` DATE,                     -- 本周最后一天
`month_begin_date` DATE,                  -- 本月第一天
`month_end_date` DATE,                    -- 本月最后一天
`quarter_begin_date` DATE,                -- 本季度第一天
`quarter_end_date` DATE,                  -- 本季度最后一天
`year_begin_date` DATE,                   -- 本年第一天
`year_end_date` DATE                      -- 本年最后一天
) ENGINE=OLAP
DUPLICATE KEY(date_id)
COMMENT "时间维度表"
DISTRIBUTED BY HASH(date_id) BUCKETS 1
PROPERTIES (
"replication_num" = "3",
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "YEAR",
"dynamic_partition.start" = "-3", -- 动态创建过去3年和未来2年的分区
"dynamic_partition.end" = "2",
"dynamic_partition.prefix" = "p",
"dynamic_partition.buckets" = "1"
);

3. DWS 层(数据服务层 / 宽表层)

  • 目的:面向业务场景构建宽表,进一步聚合数据,减少多表关联,提升查询性能。这是支持用户画像上卷下钻的核心层

  • 表设计:使用 Aggregate 模型,并创建物化视图

    • dws_user_profile_wide (用户画像宽表)

      • 模型:Aggregate 模型

      • 分区:按 date (日期) 分区。

      • 分桶:按 user_id 分桶。

      • 排序键:(date, province, city, user_id)

      • Schema:

        sql

        CREATE TABLE dws_user_profile_wide (`date` DATE,                    -- 日期粒度`province` VARCHAR(20),`city` VARCHAR(20),`user_id` BIGINT,`age_group` VARCHAR(10) REPLACE, -- 年龄段,e.g., '20-30'`gender` VARCHAR(10) REPLACE,`latest_blood_pressure_status` VARCHAR(20) REPLACE, -- 最新血压状态`latest_blood_sugar_status` VARCHAR(20) REPLACE,`is_high_risk_cardio` BOOLEAN REPLACE, -- 是否心脑血管高风险`favorited_vc_product_count` BIGINT SUM, -- 收藏的VC类产品总数`clicked_protein_powder_count` BIGINT SUM, -- 点击的蛋白粉类产品次数-- ... 其他标签和聚合指标
        ) ENGINE=OLAP
        AGGREGATE KEY(date, province, city, user_id)
        PARTITION BY RANGE(date) (...)
        DISTRIBUTED BY HASH(user_id) BUCKETS 10;
      • 物化视图创建示例

        sql

        -- 为按省和日期聚合创建物化视图,加速上卷查询
        CREATE MATERIALIZED VIEW province_date_agg AS
        SELECT`date`,`province`,COUNT(DISTINCT user_id) AS total_users,SUM(CAST(is_high_risk_cardio AS INT)) AS high_risk_users,SUM(favorited_vc_product_count) AS total_vc_favorites
        FROM dws_user_profile_wide
        GROUP BY `date`, `province`;-- 为按市、性别和日期聚合创建物化视图,支持下钻查询
        CREATE MATERIALIZED VIEW city_gender_date_agg AS
        SELECT`date`,`province`,`city`,`gender`,COUNT(DISTINCT user_id) AS total_users,...
        FROM dws_user_profile_wide
        GROUP BY `date`, `province`, `city`, `gender`;

        Doris 的查询优化器会自动选择最优的物化视图来响应查询。


四、 ETL 数据处理流程
  1. 数据采集:用户行为数据通过埋点实时写入 Kafka。体检报告和用户信息通过业务数据库的 Binlog 或每日全量/增量导出文件到 HDFS。

  2. 数据导入

    • 实时:使用 Routine Load 任务持续消费 Kafka 中的行为数据,导入到 ods_user_behavior 表。

    • 批量:每天凌晨,使用 Broker Load 从 HDFS 拉取体检报告和用户信息的增量文件,导入到对应的 ODS 表。

  3. 数据加工
    * 通过INSERT INTO SELECT语句,定期(如每小时或每天)将 ODS 层数据清洗、转换、聚合到 DWD 层事实表和维度表。
    * 同样通过 INSERT INTO SELECT,将 DWD 层数据与维度表 JOIN 后,聚合到 DWS 宽表 dws_user_profile_wide。这个过程会计算用户标签(如 is_high_risk_cardio)和聚合指标。

  4. 数据服务:应用层直接通过 MySQL 协议查询 DWS 层的宽表及其物化视图,快速获取分析结果。


五、 示例查询
  1. 下钻分析:”2023年Q4,江苏省南京市,高血糖用户中最关注维生素C保健品的人群分布?“

    sql

    SELECTcity,gender,age_group,COUNT(DISTINCT user_id) AS user_count
    FROM dws_user_profile_wide
    WHERE`date` >= '2023-10-01' AND `date` <= '2023-12-31'AND province = '江苏省'AND city = '南京市'AND latest_blood_sugar_status = 'high' -- 高血糖标签AND favorited_vc_product_count > 0     -- 关注过VC产品
    GROUP BYcity, gender, age_group -- 下钻到市、性别、年龄
    ORDER BY user_count DESC;

    Doris 会尝试使用 province_date_agg 等物化视图快速定位到江苏省2023Q4的数据,然后再进行下钻计算。

  2. 上卷分析:”近一年,全国各季度,心脑血管高风险用户的比例趋势?“

    sql

    SELECTYEAR(date) AS year,QUARTER(date) AS quarter,SUM(CAST(is_high_risk_cardio AS INT)) / COUNT(DISTINCT user_id) AS risk_ratio
    FROM dws_user_profile_wide
    WHERE `date` >= DATE_SUB(CURRENT_DATE(), INTERVAL 1 YEAR)
    GROUP BY year, quarter
    ORDER BY year, quarter;

    此查询可能会直接命中按日期聚合的物化视图,效率极高。


六、 总结与优化建议
  • 优势:本方案充分利用了 Doris 的聚合模型、物化视图、分区分桶等核心特性,完美支撑了用户画像的多维分析需求,预计能达到极快的查询响应速度。

  • 监控与调优

    • 监控 dws_user_profile_wide 表的物化视图命中率,根据业务查询模式调整或增加物化视图。

    • 监控集群磁盘、内存、BE节点状态,随着数据增长水平扩展 Doris 集群。

    • 合理设置分桶数量,通常在10-100个之间,避免 Tablet 过多导致元数据压力过大。

  • 未来扩展

    • 可以引入更复杂的用户标签算法(如机器学习模型打分),通过 ETL 过程将结果写入用户宽表。

    • 可以探索使用 Doris 的 Array 类型存储用户的行为标签序列,进行用户行为路径分析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/99126.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/99126.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/99126.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python的深度学习

深入理解Python高级特性掌握Python的高级特性是进阶的关键&#xff0c;包括装饰器、生成器、上下文管理器、元类等。这些特性能够提升代码的灵活性和效率。例如&#xff0c;装饰器可以用于实现AOP&#xff08;面向切面编程&#xff09;&#xff0c;生成器可以处理大数据流而无需…

数据库范式(Normalization)

一个设计混乱的数据库就像一个杂乱的房间&#xff0c;用起来非常不方便&#xff1a;东西到处乱放&#xff08;数据冗余&#xff09;&#xff0c;找件东西要翻遍所有角落&#xff08;查询困难&#xff09;&#xff0c;扔掉一把旧椅子时&#xff0c;可能会把搭在上面的唯一一件外…

数据结构---循环队列

基于循环数组实现的循环队列解决了顺序队列中的假溢出导致的空间浪费问题操作&#xff1a;&#xff08;1&#xff09;初始化//循环队列 typedef struct {int *data;//指针模拟声明数组int head,tail;//队头&#xff0c;队尾 }Queue; //初始化 Queue *InitQueue() {Queue *q (Q…

深入理解线程模型

线程作为操作系统调度的基本执行单元&#xff0c;是实现高吞吐、低延迟系统的基础。一、进程与线程的体系结构对比核心概念&#xff1a;进程&#xff08;Process&#xff09;&#xff1a;操作系统资源分配的基本单位&#xff0c;拥有独立的虚拟地址空间、文件描述符表、环境变量…

TTC定时器中断——MPSOC实战3

开启TTC定时器&#xff0c;不同于7000系列的私有定时器此处设置LPD_LSBUS频率TTC频率取决于LPD_LSBUS可前往指定位置查看参数不使能填写对应宏可前往指定位置查看参数main.c#include <stdio.h> #include "xparameters.h" #include "xgpiops.h" #incl…

人工智能训练师三级备考笔记

一、实操1&#xff09;通用语法&#xff08;常见于实操题第一块代码块&#xff09;1.读取文件数据或加载数据集等描述时一般为以下结构&#xff1a;Datapd.read_文件格式(文件名) 注意&#xff1a;文件名需要用‘ ’框起来&#xff0c;必须要有引号文件格式有以下内容csv、txt…

Cherry Studio递归工具调用机制深度解析

在现代AI应用开发中,工具调用(Tool Calling)已成为大语言模型与外部系统交互的核心机制。Cherry Studio作为一款先进的AI对话客户端,实现了一套完整的递归工具调用系统,能够让AI助手在执行复杂任务时自动调用多个工具,并根据执行结果智能决策下一步操作。本文将深入解析这…

[哈希表]966. 元音拼写检查器

966. 元音拼写检查器 class Solution:def spellchecker(self, wordlist: List[str], queries: List[str]) -> List[str]:origin set(wordlist) # 存储原始单词用于完全匹配lower_to_origin {} # 存储小写形式到原始单词的映射vowel_to_origin {} # 存储元音模糊形…

正则表达式与文本三剑客(grep、sed、awk)基础与实践

正则表达式基础与实践一、正则表达式概述1. 定义正则表达式&#xff08;Regular Expression&#xff0c;简称 RE&#xff09;是用于描述字符排列和匹配模式的语法规则&#xff0c;核心作用是对字符串进行分割、匹配、查找、替换操作。它本质是 “模式模板”&#xff0c;Linux 工…

eclipse中web项目编译后的lib里面jar为空问题处理

1. 检查项目构建配置验证项目性质右键单击项目 → Properties确认项目已正确配置&#xff1a;​Project Facets​&#xff1a;确保已勾选"Dynamic Web Module"​Targeted Runtimes​&#xff1a;确保已选择服务器运行时&#xff08;如Tomcat&#xff09;检查部署程序…

C语言中的递归问题——汉诺塔问题

汉诺塔&#xff08;Tower of Hanoi)&#xff0c;又称河内塔&#xff0c;是一个源于印度古老传说的益智玩具。传说大梵天创造世界的时候做了三根金刚石柱子&#xff0c;在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在…

ArkAnalyzer源码初步分析I——分析ts项目流程

1.前言&#xff1a; 鸿蒙程序分析框架ArkAnalyzer&#xff08;方舟分析器&#xff09; 源码地址 入门文档 2.阅读入门文档后&#xff1a; 本人具有一定的Java开发经验。虽然我对 TypeScript&#xff08;TS&#xff09;和 ArkTS 还不熟&#xff0c;但很多概念对我这个 Java 开…

c#基础二(类和对象,构造器调用顺序、访问级别、重写和多态、抽象类和接口)

一、类1.0对象初始化器class Student {public String name;public int age { get; set; } } internal class Program {static void Main(string[] args){ //写法一Student stunew Student();stu.name"Tom";stu.age20;//写法二Student stu2 new Student { name &qu…

Qt之快捷键、事件处理、自定义按键——完成记事本项目

快捷键我们电脑中的记事本中还支持快捷键&#xff0c;如“CTRLO”打开文件、“CTRLS”保存文件在Qt中使用QShortcut这个类创建快捷键在.cpp文件的构造函数中创建QShortcut对象&#xff0c;绑定打开文件和保存文件的槽函数放大缩小字体还是在.cpp的构造函数中编写代码Widget::Wi…

Open cascade中如何使用BRepAlgoAPI_Splitter分割一个Face

理论介绍 在OpenCASCADE几何建模内核中&#xff0c;BRepAlgoAPI_Splitter是一个强大的工具&#xff0c;用于将一个形状&#xff08;Shape&#xff09;用另一个形状&#xff08;Tool&#xff09;进行分割。这种操作在CAD建模中非常常见&#xff0c;比如用平面切割实体、用曲线分…

【医疗 AI】Baichuan-M2 医疗大模型:技术解读与使用方法

【医疗 AI】Baichuan-M2 医疗大模型&#xff1a;技术解读与使用方法1. Baichuan-M2 医疗大模型简介1.1 基本信息1.2 下载地址1.3 技术特点2. Baichuan-M2 模型技术报告2.1 摘要2.2 医学性能评估2.2.1 HealthBench基准2.2.2 中国医疗场景对比评估2.3 系统架构2.3.1 验证器系统2.…

unity pcd 二进制版 简单显示文件对象(单色)

unity Point Cloud Viewer and Tool 那个插件不支持pcd二进制&#xff0c;而且网上到处都是AI 我恨这种AI滥用&#xff0c;提供不了一点价值 好了&#xff0c;言归正传 可以在Point Cloud Viewer and Tool这个插件报错地方转用这个代码&#xff0c;具体咋结合请自行研究。 …

强大的开源文档问答工具-Kotaemon

Kotaemon 是一个基于 RAG&#xff08;Retrieval-Augmented Generation&#xff09;架构的开源文档问答工具&#xff0c;为用户提供与文档对话的智能交互体验。该项目同时服务于终端用户和开发者&#xff0c;具有高度的可扩展性和定制化能力。技术栈分析核心技术栈后端框架Pytho…

区块链:搭建简单Fabric网络并调用智能合约

使用docker服务搭建Hyperledger/fabric网络的详细教程&#xff0c;实现构建多节点的简单联盟链&#xff0c;并编写、调用智能合约实现投票业务。 目录 背景知识 Hyperledger Fabric 基本组件 交易(Transaction) 智能合约 实验目的 实验环境 基础依赖 安装Golang 安装do…

Web前端面试题(2)

Web前端面试题(附答案及解析)&#xff08;2025.9月最新版&#xff09;-CSDN博客 1.link 与 import 的区别和用法 主要区别 特性<link>import语法类型HTML标签CSS规则加载方式并行加载&#xff08;与其他资源同时加载&#xff09;串行加载&#xff08;必须等待主CSS文件…