Apache Doris学习笔记

简介

Apache Doris 是一款基于 MPP(Massively Parallel Processing,大规模并行处理架构) 架构的高性能、实时分析型数据库。它以高效、简单和统一的特性著称,能够在亚秒级的时间内返回海量数据的查询结果。Doris 既能支持高并发的点查询场景,也能支持高吞吐的复杂分析场景。

基于这些优势,Apache Doris 非常适合用于报表分析、即席查询、统一数仓构建、数据湖联邦查询加速等场景。用户可以基于 Doris 构建大屏看板、用户行为分析、AB 实验平台、日志检索分析、用户画像分析、订单分析等应用。

应用场景

  • 实时数据分析:
    • 实时报表与实时决策: 为企业内外部提供实时更新的报表和仪表盘,支持自动化流程中的实时决策需求。
    • 交互式探索分析: 提供多维数据分析能力,支持对数据进行快速的商业智能分析和即席查询(Ad Hoc 根据即时需求临时编写的、非预定义的数据库查询操作),帮助用户在复杂数据中快速发现洞察。
    • 用户行为与画像分析: 分析用户参与、留存、转化等行为,支持人群洞察和人群圈选等画像分析场景。
  • 湖仓融合分析:
    • 湖仓查询加速: 通过高效的查询引擎加速湖仓数据的查询。
    • 多源联邦分析: 支持跨多个数据源的联邦查询,简化架构并消除数据孤岛。
    • 实时数据处理: 结合实时数据流和批量数据的处理能力,满足高并发和低延迟的复杂业务需求。
  • 半结构化数据分析:
    • 日志与事件分析: 对分布式系统中的日志和事件数据进行实时或批量分析,帮助定位问题和优化性能。

整体架构

Doris 采用 MySQL 协议,高度兼容 MySQL 语法,支持标准 SQL。用户可以通过各类客户端工具访问 Apache Doris,并支持与 BI 工具无缝集成。

存算一体架构

Apache Doris 存算一体架构精简且易于维护。它包含以下两种类型的进程:

  • Frontend (FE): 主要负责接收用户请求、查询解析和规划、元数据管理以及节点管理。
  • Backend (BE): 主要负责数据存储和查询计划的执行。数据会被切分成数据分片(Shard),在 BE 中以多副本方式存储。

数据库整体架构和技术特点

存算分离架构

Apache Doris 存算分离版使用统一的共享存储层作为数据存储空间。存储和计算分离后,用户可以独立扩展存储容量和计算资源,从而实现最佳性能和成本效益。存算分离架构分为以下三层:

  • 元数据层: 负责请求规划、查询解析以及元数据的存储和管理。
  • 计算层: 由多个计算组组成。每个计算组可以作为一个独立的租户承担业务计算。每个计算组包含多个无状态的 BE 节点,可以随时弹性伸缩 BE 节点。
  • 存储层: 可以使用 S3、HDFS、OSS、COS、OBS、Minio、Ceph 等共享存储来存放 Doris 的数据文件,包括 Segment 文件和反向索引文件等。

存算分离整体架构和技术特点

Apache Doris 的核心特性

  • 高可用: Apache Doris 的元数据和数据均采用多副本存储,并通过 Quorum 协议同步数据日志。当大多数副本完成写入后,即认为数据写入成功,从而确保即使少数节点发生故障,集群仍能保持可用性。Apache Doris 支持同城和异地容灾,能够实现双集群主备模式。当部分节点发生异常时,集群可以自动隔离故障节点,避免影响整体集群的可用性。
  • 高兼容: Apache Doris 高度兼容 MySQL 协议,支持标准 SQL 语法,涵盖绝大部分 MySQL 和 Hive 函数。通过这种高兼容性,用户可以无缝迁移和集成现有的应用和工具。Apache Doris 支持 MySQL 生态,用户可以通过 MySQL 客户端工具连接 Doris,使得操作和维护更加便捷。同时,可以使用 MySQL 协议对 BI 报表工具与数据传输工具进行兼容适配,确保数据分析和数据传输过程中的高效性和稳定性。
  • 实时数仓: 基于 Apache Doris 可以构建实时数据仓库服务。Apache Doris 提供了秒级数据入库能力,上游在线联机事务库中的增量变更可以秒级捕获到 Doris 中。依靠向量化引擎、MPP 架构及 Pipeline 执行引擎等加速手段,可以提供亚秒级数据查询能力,从而构建高性能、低延迟的实时数仓平台。
  • 湖仓一体: Apache Doris 可以基于外部数据源(如数据湖或关系型数据库)构建湖仓一体架构,从而解决数据在数据湖和数据仓库之间无缝集成和自由流动的问题,帮助用户直接利用数据仓库的能力来解决数据湖中的数据分析问题,同时充分利用数据湖的数据管理能力来提升数据的价值。
  • 灵活建模: Apache Doris 提供多种建模方式,如宽表模型、预聚合模型、星型/雪花模型等。数据导入时,可以通过 Flink、Spark 等计算引擎将数据打平成宽表写入到 Doris 中,也可以将数据直接导入到 Doris 中,通过视图、物化视图或实时多表关联等方式进行数据的建模操作。

技术特点

使用接口

Doris 采用 MySQL 协议,高度兼容 MySQL 语法,支持标准 SQL。

存储引擎

在存储引擎方面,Apache Doris 采用列式存储,按列进行数据的编码、压缩和读取,能够实现极高的压缩比,同时减少大量非相关数据的扫描,从而更有效地利用 IO 和 CPU 资源。

Apache Doris 也支持多种索引结构,以减少数据的扫描:

  • Sorted Compound Key Index: 最多可以指定三个列组成复合排序键。通过该索引,能够有效进行数据裁剪,从而更好地支持高并发的报表场景。
  • Min/Max Index: 有效过滤数值类型的等值和范围查询。
  • BloomFilter Index: 对高基数列的等值过滤裁剪非常有效。
  • Inverted Index: 能够对任意字段实现快速检索。

在存储模型方面,Apache Doris 支持多种存储模型,针对不同的场景做了针对性的优化:

  • 明细模型(Duplicate Key Model): 适用于事实表的明细数据存储。
  • 主键模型(Unique Key Model): 保证 Key 的唯一性,相同 Key 的数据会被覆盖,从而实现行级别数据更新。
  • 聚合模型(Aggregate Key Model): 相同 Key 的 Value 列会被合并,通过提前聚合大幅提升性能。

Apache Doris 也支持强一致的单表物化视图和异步刷新的多表物化视图。单表物化视图在系统中自动刷新和维护,无需用户手动选择。多表物化视图可以借助集群内的调度或集群外的调度工具定时刷新,从而降低数据建模的复杂性。

安装部署

见官网https://doris.incubator.apache.org/zh-CN/docs/3.0/install/preparation/env-checking

数据表

Doris的数据表数据以列的方式存储,分为key列和value列。对于value列的增减或者修改类型是轻量的,秒级别完成。对于key列(重量级的)不建议修改。

数据表模型

Doris数据表模型分为三种:明细模型、主键模型、聚合模型。

明细模型(Duplicate Key Model)

明细模型运行指定的key列重复,doris会存储所有的写入数据,适合存储日志,数据变化记录等数据。

建表语句

CREATE TABLE IF NOT EXISTS example_tbl_duplicate
(
    log_time        DATETIME       NOT NULL,
    log_type        INT            NOT NULL,
    error_msg       VARCHAR(1024),
    op_id           BIGINT,
    op_time         DATETIME
)
DUPLICATE KEY(log_time, log_type)
DISTRIBUTED BY HASH(log_type) BUCKETS 10;
  • DUPLICATE KEY 指定明细模型和key列
  • DISTRIBUTED BY HASH(log_type) 表明根据log_type字段 并按照Hash分桶
  • BUCKETS 10 指定分桶数为10
主键模型(Unique Key Model)

对于数据需要保持唯一性,需要更新的数据,使用主键模型。它保证了key列的数据唯一,插入或更新时,会新数据会覆盖旧的相同key的数据。

建表语句

CREATE TABLE IF NOT EXISTS example_tbl_unique
(
    user_id         LARGEINT        NOT NULL,
    user_name       VARCHAR(50)     NOT NULL,
    city            VARCHAR(20),
    age             SMALLINT,
    sex             TINYINT
)
UNIQUE KEY(user_id, user_name)
DISTRIBUTED BY HASH(user_id) BUCKETS 10
PROPERTIES (
    "enable_unique_key_merge_on_write" = "true"
);
  • UNIQUE KEY 指定主键模型和key列
  • DISTRIBUTED BY HASH(user_id) 表明根据user_id字段 并按照Hash分桶
  • BUCKETS 10 指定分桶数为10
  • enable_unique_key_merge_on_write 表明合并方式为写时合并
聚合模型(Aggregate Key Model)

聚合模型专为高效处理大规模数据查询中的聚合操作设计。它通过预聚合数据,减少重复计算,提升查询性能。 适用于需要汇总计算的场景。

建表语句

CREATE TABLE IF NOT EXISTS example_tbl_agg
(
    user_id             LARGEINT    NOT NULL,
    load_dt             DATE        NOT NULL,
    city                VARCHAR(20),
    last_visit_dt       DATETIME    REPLACE DEFAULT "1970-01-01 00:00:00",
    cost                BIGINT      SUM DEFAULT "0",
    max_dwell           INT         MAX DEFAULT "0",
)
AGGREGATE KEY(user_id, load_dt, city)
DISTRIBUTED BY HASH(user_id) BUCKETS 10;
  • AGGREGATE KEY(user_id, load_dt, city) 指定主键模型和key列,数据导入时,会按照key列相同的数据进行聚合成一行
  • DISTRIBUTED BY HASH(user_id) 表明根据user_id字段 并按照Hash分桶
  • BUCKETS 10 指定分桶数为10

维度聚合类型

聚合方式 描述
SUM 求和,多行的 Value 进行累加。
REPLACE 替代,下一批数据中的 Value 会替换之前导入过的行中的 Value。
MAX 保留最大值。
MIN 保留最小值。
REPLACE_IF_NOT_NULL 非空值替换。与 REPLACE 的区别在于对 null 值,不做替换。
HLL_UNION HLL 类型的列的聚合方式,通过 HyperLogLog 算法聚合。
BITMAP_UNION BITMAP 类型的列的聚合方式,进行位图的并集聚

语法

表操作
CREATE TABLE [IF NOT EXISTS] table_name
(
  column_name column_type [COMMENT "comment"],
  ...
  -- 模型相关关键字(根据模型选择)
  [DUPLICATE KEY (col1, col2, ...)]  -- 明细模型
  [AGGREGATE KEY (col1, col2, ...)]  -- 聚合模型
  [UNIQUE KEY (col1, col2, ...)]     -- 主键模型 更新模型
)
[COMMENT "table comment"]
PARTITION BY (partition_column)  -- 分区方式(可选,如RANGE、LIST)
DISTRIBUTED BY HASH (distribute_column) [BUCKETS num]  -- 分桶方式(必选)
[PROPERTIES ("key" = "value", ...)];  -- 表属性(如存储介质、副本数等)
视图语法
CREATE VIEW [IF NOT EXISTS] view_name AS SELECT query;
查询语法

Doris查询语法与MySql很相似,并且支持ROW_NUMBER()RANK()SUM() OVER()等窗口函数,并新增两种聚合函数

  • PERCENTILE_CONT():计算连续百分位数
  • APPROX_COUNT_DISTINCT():近似去重计数(高性能)
SELECT [DISTINCT] col1, col2, ...
FROM table_name
[WHERE condition]
[GROUP BY col1, col2, ... [HAVING condition]]
[ORDER BY col1 [ASC|DESC], ...]
[LIMIT num];

索引

Doris有两种类型的索引:点差索引和跳数索引

  • 点差索引:原理是通过where条件进行查询对应的数据行,然后读取对应行。Doris 的点查索引包括前缀索引和倒排索引。
    • 前缀索引:Doris按照排序键有序存储数据,没1024行创建一个稀疏前缀索引,索引key是当前1024行第一列的值。查询时会从相关1024行第一行开始扫描数据。
    • 倒排索引:Doris 会建立每个值到对应行号的倒排表。对应等值查询,先从倒排表中查询对应行号集合,直接读取对应行的数据。
  • 跳数索引:原理是通过索引确定不满足对应查询条件的数据块,跳过这些数据库,只查询有可能满足条件的数据块,然后在进行过滤查询。Doris 的跳数索引包括 ZoneMap 索引、BloomFilter 索引、NGram BloomFilter 索引。
    • ZoneMap 索引:会自动维护每一列的统计信息,为每一个数据文件和数据块记录最大值、最小值、是否有 NULL。范围条件查询时可以直接判断是否包含满足的数据。
    • BloomFilter 索引:将索引对应列的可能取值存入 BloomFilter 数据结构中,可以快速判断是否存在BloomFilter中,BloomFilter 存储空间占用很低。当等值查询时,判断值是否在BloomFilter中,就可以判断是否查询对应数据文件和数据块。(适合类型,状态等字段)
    • NGram BloomFilter: 用于加速文本字段like的查询,它会将文本进行NGram分词,然后将分词数据存入BloomFilter中。当like查询时,它会将 LIKE 的 pattern 也进行 NGram 分词,判断每个词是否在 BloomFilter 中,判断是否查询对应数据文件和数据块。(需要模糊查询的文本字段)

Doris的前缀索引和ZoneMap 索引是系统自动维护的,无需创建。

  • 各种类型索引特点对比
类 型 索引 优点 局限
点查索引 前缀索引 内置索引,性能最好 一个表只有一组前缀索引
点查索引 倒排索引 支持分词和关键词匹配,任意列可建索引,
多条件组合,持续增加函数加速
索引存储空间较大,与原始数据相当
跳数索引 ZoneMap 索引 内置索引,索引存储空间小 支持的查询类型少,只支持等于、范围
跳数索引 BloomFilter 索引 比 ZoneMap 更精细,索引空间中等 支持的查询类型少,只支持等于
跳数索引 NGram BloomFilter 索引 支持 LIKE 加速,索引空间中等 支持的查询类型少,只支持 LIKE 加速
  • 索引加速的运算符和函数列表
运算符 / 函数 前缀索引 倒排索引 ZoneMap 索引 BloomFilter 索引 NGram BloomFilter 索引
= YES YES YES YES NO
!= YES YES NO NO NO
IN YES YES YES YES NO
NOT IN YES YES NO NO NO
>, >=, <, <=, BETWEEN YES YES YES NO NO
IS NULL YES YES YES NO NO
IS NOT NULL YES YES NO NO NO
LIKE NO NO NO NO YES
MATCH, MATCH_* NO YES NO NO NO
array_contains NO YES NO NO NO
array_overlaps NO YES NO NO NO
is_ip_address_in_range NO YES NO NO NO
倒排索引

创建倒排索引

-- 语法 1
CREATE INDEX idx_name ON table_name(column_name) USING INVERTED [PROPERTIES(...)] [COMMENT 'your comment'];
-- 语法 2
ALTER TABLE table_name ADD INDEX idx_name(column_name) USING INVERTED [PROPERTIES(...)] [COMMENT 'your comment'];

历史存量数据生成倒排索引

-- 语法 1,默认给全表的所有分区 BUILD INDEX
BUILD INDEX index_name ON table_name;
-- 语法 2,可指定 Partition,可指定一个或多个
BUILD INDEX index_name ON table_name PARTITIONS(partition_name1, partition_name2);

查看索引生成进度

SHOW BUILD INDEX [FROM db_name];
-- 示例 1,查看所有的 BUILD INDEX 任务进展
SHOW BUILD INDEX;
-- 示例 2,查看指定 table 的 BUILD INDEX 任务进展
SHOW BUILD INDEX where TableName = "table1";

索引语法

  1. idx_name(column_name) 是必须的,column_name 代表你建立的的那一列的索引, idx_name是索引的名字,表内唯一。
  2. **USING INVERTED **是必须的,用于指定索引类型是倒排索引
  3. COMMENT 是可选的,指定索引注释
  4. PROPERTIES 是可选的,指定倒排索引的额外属性
    • lower_case:是否将分词进行小写转换,在匹配时忽略大小写
    • 其他请看官网
BloomFilter 索引

BloomFilter 索引能够对等值查询(包括 = 和 IN)加速,对高基数字段效果较好,比如 userid 等唯一 ID 字段

建表时创建 BloomFilter 索引,可以指定多个列

PROPERTIES (
"bloom_filter_columns" = "column_name1,column_name2"
);

已有表增加 BloomFilter 索引

ALTER TABLE table_name SET ("bloom_filter_columns" = "column_name1,column_name2,column_name3"

已有表删除 BloomFilter 索引

ALTER TABLE table_name SET ("bloom_filter_columns" = "column_name2,column_name3");

Schema 变更(表结构修改)

Doris的表结构操作时,根据操作类型的不同,分为轻量级和重量级,主要区别在执行速度、资源消耗、执行过程复杂性上。

特性 轻量级 Schema Change 重量级 Schema Change
执行速度 秒级(几乎实时) 分钟级、小时级、天级(依赖表的数据量,数据量越大,执行越慢)
是否需要数据重写 不需要 需要,涉及数据文件的重写
系统性能影响 影响较小 可能影响系统性能,尤其是在数据转换过程中
资源消耗 较低 较高,会占用计算资源重新组织数据,过程中涉及到的表的数据占用的存储空间翻倍。
操作类型 增加、删除 Value 列,修改列名,修改 VARCHAR 长度 修改列的数据类型、更改主键、修改列的顺序等

数据查询

数据类型
类型 取值范围
Boolean 0 代表 false,1 代表 true
Tinyint -128 ~ 127
Smallint -32768 ~ 32767
int -2147483648~ 2147483647
Bigint -2^63 ~ 2^63-1
LARGEINT -2^127 ~ 2^127-1
Decimal 默认值:Decimal(9, 0)
Float/Double
Date ['0000-01-01', '9999-12-31']
DateTime 范围:['0000-01-01 00:00:00[.000000]', '9999-12-31 23:59:59[.999999]'] - 格式:YYYY-MM-DD hh:mm.fraction
Char 1-255
Varchar 1-65535
String 1048576 字节(1MB),可调大到 2147483643 字节(2G)
JSON
HyperLogLog 不能做key列
BITMAP 不能做key列
QUANTILE_STATE 不能做key列
Array 不能做key列
MAP<K, V> 不能做key列
STRUCT<field_name:field_type, ... > 不能做key列
Agg_State 不能做key列
'AGG_STATE', 'ALL', 'ARRAY', 'BIGINT', 'BITMAP', 'BOOLEAN', 'CHAR', 'DATE', 'DATETIME', 'DATETIMEV2', 'DATEV2', 'DATETIMEV1', 'DATEV1', 'DECIMAL', 'DECIMALV2', 'DECIMALV3', 'DOUBLE', 'FLOAT', 'HLL', 'INT', 'INTEGER', 'IPV4', 'IPV6', 'JSON', 'JSONB', 'LARGEINT', 'MAP', 'QUANTILE_STATE', 'SMALLINT', 'STRING', 'STRUCT', 'TEXT', 'TIME', 'TINYINT', 'VARCHAR', 'VARIANT'
分组查询

在数据库中,ROLLUP、CUBE 和 GROUPING SETS 是用于多维数据聚合的高级 SQL 语句。

  • ROLLUP:ROLLUP 是一种用于生成层次化汇总的操作。它按照指定的列顺序进行汇总,从最细粒度的数据逐步汇总到最高层次。
  • CUBE:CUBE 是一种更为强大的聚合操作,它生成所有可能的汇总组合。与 ROLLUP 不同,CUBE 会计算所有维度的子集。
  • GROUPING SETS:GROUPING SETS 提供了对特定分组集进行聚合的灵活性。它允许用户指定一组列的组合进行独立聚合,而不是像 ROLLUP 和 CUBE 那样生成所有可能的组合。
posted @ 2025-11-07 17:50  迷失海洋  阅读(6)  评论(0)    收藏  举报