【大数据 - Doris 实践】数据表的基本使用(二):数据划分

1.列定义

列的基本类型,可以通过在 mysql-client 中执行 HELP CREATE TABLE 查看。

AGGREGATE KEY 数据模型为例进行说明(更多数据模型参阅 Doris 数据模型)。AGGREGATE KEY 数据模型中,所有没有指定聚合方式(SUMREPLACEMAXMIN)的列视为 Key 列。而其余则为 Value 列。定义列时,可参照如下建议:

  • Key 列必须在所有 Value 列之前。
  • 尽量选择整型类型。因为整型类型的计算和查找比较效率远高于字符串。
  • 对于不同长度的整型类型的选择原则,遵循够用即可。
  • 对于 VARCHAR 和 STRING 类型的长度,遵循够用即可。
  • 所有列的总字节长度(包括 Key 和 Value)不能超过 100 KB。

2.分区与分桶

Doris 支持两层的数据划分。第一层是 Partition,支持 Range 和 List 的划分方式。第二层是 Bucket(Tablet),仅支持 Hash 的划分方式。也可以仅使用一层分区。使用一层分区时,只支持 Bucket 划分。

2.1 Partition

  • Partition 列可以指定一列或多列。分区类必须为 KEY 列。多列分区的使用方式在后面介绍。
  • 不论分区列是什么类型,在写分区值时,都需要加双引号。
  • 分区数量理论上没有上限。
  • 当不使用 Partition 建表时,系统会自动生成一个和表名同名的,全值范围的 Partition。该 Partition 对用户不可见,并且不可删改。

2.1.1 Range 分区

分区列通常为时间列,以方便的管理新旧数据。不可添加范围重叠的分区。

Partition 指定范围的方式:

  • VALUES LESS THAN (…) 仅指定上界,系统会将前一个分区的上界作为该分区的下界,生成一个左闭右开的区间。分区的删除不会改变已存在分区的范围。删除分区可能出现空洞。
  • VALUES […) 同时指定上下界,生成一个左闭右开的区间。

通过 VALUES […) 同时指定上下界比较容易理解。这里举例说明,当使用 VALUES LESS THAN (…) 语句进行分区的增删操作时,分区范围的变化情况:

上篇博客 中新建的 expamle_range_tbl 示例,当建表完成后,会自动生成如下 3 个分区:

p201701: [MIN_VALUE, 2017-02-01)
p201702: [2017-02-01, 2017-03-01)
p201703: [2017-03-01, 2017-04-01)

增加一个分区 p201705 VALUES LESS THAN (“2017-06-01”),分区结果如下:

p201701: [MIN_VALUE, 2017-02-01)
p201702: [2017-02-01, 2017-03-01)
p201703: [2017-03-01, 2017-04-01)
p201705: [2017-04-01, 2017-06-01)

此时删除分区 p201703,则分区结果如下:

p201701: [MIN_VALUE, 2017-02-01)
p201702: [2017-02-01, 2017-03-01)
p201705: [2017-04-01, 2017-06-01)

注意到 p201702p201705 的分区范围并没有发生变化,而这两个分区之间,出现了一个空洞:[2017-03-01, 2017-04-01)。即如果导入的数据范围在这个空洞范围内,是无法导入的。

继续删除分区 p201702,分区结果如下:

p201701: [MIN_VALUE, 2017-02-01)
p201705: [2017-04-01, 2017-06-01)

空洞范围变为:[2017-02-01, 2017-04-01)

现在增加一个分区 p201702new VALUES LESS THAN (“2017-03-01”),分区结果如下:

p201701: [MIN_VALUE, 2017-02-01)
p201702new: [2017-02-01, 2017-03-01)
p201705: [2017-04-01, 2017-06-01)

可以看到空洞范围缩小为:[2017-03-01, 2017-04-01)

现在删除分区 p201701,并添加分区 p201612 VALUES LESS THAN (“2017-01-01”),分区结果如下:

p201612: [MIN_VALUE, 2017-01-01)
p201702new: [2017-02-01, 2017-03-01)
p201705: [2017-04-01, 2017-06-01)

即出现了一个新的空洞:[2017-01-01, 2017-02-01)

2.1.2 List 分区

分区列支持 BOOLEANTINYINTSMALLINTINTBIGINTLARGEINTDATEDATETIMECHARVARCHAR 数据类型,分区值为枚举值。只有当数据为目标分区枚举值其中之一时,才可以命中分区。不可添加范围重叠的分区。

Partition 支持通过 VALUES IN (…) 来指定每个分区包含的枚举值。下面通过示例说明,进行分区的增删操作时,分区的变化。

(1)以 上篇博客 中新建的 example_list_tbl 示例,当建表完成后,会自动生成如下 3 个分区:

p_cn: ("Beijing", "Shanghai", "Hong Kong")
p_usa: ("New York", "San Francisco") 
p_jp: ("Tokyo")

(2)增加一个分区 p_uk VALUES IN (“London”),分区结果如下:

p_cn: ("Beijing", "Shanghai", "Hong Kong")
p_usa: ("New York", "SanFrancisco") 
p_jp: ("Tokyo")
p_uk: ("London")

(3)删除分区 p_jp,分区结果如下:

p_cn: ("Beijing", "Shanghai", "Hong Kong")
p_usa: ("New York", "SanFrancisco") 
p_uk: ("London")

2.2 Bucket

  • 如果使用了 Partition,则 DISTRIBUTED … 语句描述的是数据在各个分区内的划分规则。如果不使用 Partition,则描述的是对整个表的数据的划分规则。

  • 分桶列可以是多列,但必须为 Key 列。分桶列可以和 Partition 列相同或不同。

  • 分桶列的选择,是在 查询吞吐查询并发 之间的一种权衡:

    • 如果选择多个分桶列,则数据分布更均匀。如果一个查询条件不包含所有分桶列的等值条件,那么该查询会触发所有分桶同时扫描,这样查询的吞吐会增加,单个查询的延迟随之降低。这个方式适合大吞吐低并发的查询场景。
    • 如果仅选择一个或少数分桶列,则对应的点查询可以仅触发一个分桶扫描。此时,当多个点查询并发时,这些查询有较大的概率分别触发不同的分桶扫描,各个查询之间的 IO 影响较小(尤其当不同桶分布在不同磁盘上时),所以这种方式适合高并发的点查询场景。
  • 分桶的数量理论上没有上限。

2.3 使用复合分区的场景

以下场景推荐使用复合分区

  • 有时间维度或类似带有有序值的维度,可以以这类维度列作为分区列。分区粒度可以根据导入频次、分区数据量等进行评估。
  • 历史数据删除需求:如有删除历史数据的需求(比如仅保留最近 N 天的数据)。
    使用复合分区,可以通过删除历史分区来达到目的。也可以通过在指定分区内发送 DELETE 语句进行数据删除。
  • 解决数据倾斜问题:每个分区可以单独指定分桶数量。如按天分区,当每天的数据量差异很大时,可以通过指定分区的分桶数,合理划分不同分区的数据,分桶列建议选择区分度大的列。

3.PROPERTIES

在建表语句的最后 PROPERTIES 中,可以指定以下两个参数。

3.1 replication_num

每个 Tablet 的副本数量。默认为 3 3 3,建议保持默认即可。在建表语句中,所有 Partition 中的 Tablet 副本数量统一指定。而在增加新分区时,可以单独指定新分区中 Tablet 的副本数量。

副本数量可以在运行时修改。强烈建议保持奇数。

最大副本数量取决于集群中独立 IP 的数量(注意不是 BE 数量)。Doris 中副本分布的原则是,不允许同一个 Tablet 的副本分布在同一台物理机上,而识别物理机即通过 IP。所以,即使在同一台物理机上部署了 3 3 3 个或更多 BE 实例,如果这些 BE 的 IP 相同,则依然只能设置副本数为 1 1 1

对于一些小,并且更新不频繁的维度表,可以考虑设置更多的副本数。这样在 Join 查询时,可以有更大的概率进行本地数据 Join

3.2 storage_medium

BE 的数据存储目录可以显式的指定为 SSD(Solid State Disk,固态硬盘)或者 HDD(Hard Disk Drive,机械硬盘),通过 .SSD 或者 .HDD 后缀区分。建表时,可以统一指定所有 Partition 初始存储的介质。注意,后缀作用是显式指定磁盘介质,而不会检查是否与实际介质类型相符。

默认初始存储介质可通过 FE 的配置文件 fe.conf 中指定 default_storage_medium=xxx,如果没有指定,则默认为 HDD。如果指定为 SSD,则数据初始存放在 SSD 上。

注意,当指定 storage_medium 时:

  • 如果 FE 参数 enable_strict_storage_medium_checkFalse,该参数只是一个 “尽力而为” 的设置。即使集群内没有设置 SSD 存储介质,也不会报错,而是自动存储在可用的数据目录中。 同样,如果 SSD 介质不可访问、空间不足,都可能导致数据初始直接存储在其他可用介质上。而数据到期迁移到 HDD 时,如果 HDD 介质不可访问 、 空间不足 , 也可能迁移失败 (但是会不断尝试) 。
  • 如果 FE 参数 enable_strict_storage_medium_checkTrue,则当集群内没有设置 SSD 存储介质时,会报错 Failed to find enough host in all backends with storage medium is SSD

3.3 storage_cooldown_time

如果没有指定 storage_cooldown_time,则默认 30 30 30 天后,数据会从 SSD 自动迁移到 HDD 上。如果指定了 storage_cooldown_time,则在到达 storage_cooldown_time 时间后,数据才会迁移。

4.ENGINE

本示例中,ENGINE 的类型是 olap,即默认的 ENGINE 类型。在 Doris 中,只有这个 ENGINE 类型是由 Doris 负责数据管理和存储的。其他 ENGINE 类型,如 mysqlbrokeres 等等,本质上只是对外部其他数据库或系统中的表的映射,以保证 Doris 可以读取这些数据。而 Doris 本身并不创建、管理和存储任何非 olap ENGINE 类型的表和数据。

<think>嗯,用户想了解如何搭建离线与准实时数据仓库的架构方案,涉及Hadoop、Spark、Flink这些技术。首先,我需要明确离线数据仓库和准实时数据仓库的区别。离线通常是处理T+1的数据,比如Hadoop MapReduce和Hive,而准实时可能需要近实时的处理,比如用Flink或者Spark Streaming。 然后,用户提到的架构方案,可能需要分层设计。常见的数据仓库分层有ODS、DWD、DWS、ADS。ODS是原始数据层,DWD是清洗后的明细数据,DWS是汇总层,ADS是应用层。需要确认这些分层是否适用于离线与准实时的情况。 技术选型方面,离线处理通常用Hadoop生态,比如HDFS存储,Hive做查询,Spark做更快的批处理。准实时可能需要Kafka做消息队列,Flink处理流数据,写入HBase或者ClickHouse。同时,需要考虑数据同步工具,比如Sqoop或Flume,以及资源管理如YARN。 另外,用户可能关心如何将离线和准实时架构结合。比如Lambda架构或者Kappa架构。Lambda有批层和速度层,适合离线和实时并存,但维护复杂。Kappa则统一用流处理,可能更适合准实时场景,但可能需要更高资源。 还要注意数据一致性、容错、扩展性等问题。比如Flink的Checkpoint机制保证状态一致性,HDFS的冗余保证存储可靠。元数据管理、数据质量监控也是架构中需要考虑的部分,可能需要Atlas或Griffin这样的工具。 最后,用户可能需要具体的架构图示例,说明各组件如何协作。比如数据源通过Sqoop导入HDFS,Spark处理离线数据到Hive,同时Kafka接实时数据,Flink处理后写入HBase,再通过BI工具展示。同时,需要提到优化措施,比如压缩、资源调优、小文件合并等。 可能用户的实际场景是电商或金融,需要处理大量日志和交易数据,既要日常报表,又要实时监控。因此架构需要兼顾吞吐量和低延迟,并且易于扩展和维护。需要确保方案中涵盖这些方面,并给出可行的技术组合和最佳实践。</think>### 离线与准实时数据仓库架构方案 #### 1. **分层设计** 数据仓库通常采用分层架构,结合离线与准实时需求,可划分为以下层级: - **ODS层(原始数据层)**:存储原始数据,支持离线批量导入(如HDFS)和准实时流式接入(如Kafka)[^2]。 - **DWD层(明细数据层)**:通过ETL清洗、标准化数据。离线场景用Hive/Spark处理,准实时场景用Flink进行流处理。 - **DWS层(汇总数据层)**:按业务主题聚合数据,离线汇总用Hive/Spark,准实时汇总用Flink窗口计算。 - **ADS层(应用数据层)**:对接BI工具或报表系统,支持OLAP引擎(如Doris、ClickHouse)[^3]。 #### 2. **技术选型与组件** | 场景 | 技术栈 | 核心组件与作用 | |------------|------------------------|------------------------------------------------------------------------------| | **离线处理** | Hadoop生态 | - **HDFS**:分布式存储<br>- **Hive**:SQL化查询与批处理<br>- **Spark**:高性能批处理与内存计算 | | **准实时处理** | 流计算引擎 | - **Flink**:低延迟流处理(支持Exactly-Once语义)<br>- **Kafka**:消息队列保障数据实时传输 | | **混合架构** | Lambda/Kappa架构 | - **Lambda**:离线批处理层+实时流处理层<br>- **Kappa**:统一流处理(需回溯能力) | | **存储优化** | 列式存储/OLAP引擎 | - **HBase**:实时读写<br>- **ClickHouse**:高性能OLAP分析 | #### 3. **具体实现方案** **离线数据仓库流程**: 1. 数据采集:使用Sqoop/Flume批量导入业务数据至HDFS。 2. 数据处理:通过Hive SQL或Spark进行ETL,生成DWD层表。 3. 数据建模:基于维度建模构建星型/雪花模型,生成DWS层汇总表。 4. 数据服务:Hive结果导出至MySQL或OLAP引擎供查询[^1]。 **准实时数据仓库流程**: 1. 实时接入:通过Kafka采集日志或数据库变更(如Debezium)。 2. 流处理:Flink消费Kafka数据,进行实时清洗、关联、窗口聚合。 3. 结果存储:输出至HBase(点查场景)或ClickHouse(分析场景)。 4. 混合查询:结合离线与实时数据(如Hive+Flink联合查询)。 #### 4. **关键优化点** - **数据一致性**:Flink Checkpoint保障状态一致性,HDFS多副本保障存储可靠性。 - **资源调度**:YARN或Kubernetes管理集群资源,隔离离线与实时任务。 - **小文件合并**:Hive/Spark输出时合并小文件,减少NameNode压力。 - **压缩优化**:使用ORC/Parquet列式存储,并启用Snappy压缩。 #### 5. **架构示例图** ```plaintext 数据源 │ ├─离线链路:Sqoop → HDFS → Hive/Spark → HDFS(DWD/DWS) → OLAP引擎 │ └─准实时链路:Kafka → Flink(流处理) → HBase/ClickHouse │ └─与离线数据关联(如维表Join) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

G皮T

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值