【Doris】实时分析型数据库
【Doris】实时分析型数据库
- 【一】简介
- 【1】介绍
- 【2】核心特性
- 【3】Doris技术概述
- 【4】使用场景
- (1)实时数据分析:
- (2)湖仓融合分析:
- (3)半结构化数据分析:
- 【5】整体架构
- (1)存算一体架构
- (2)存算分离架构
- 【二】数据库基本操作
- 【1】创建数据库
- 【2】查看数据库
- 【3】修改数据库属性
- 【4】删除数据库
- 【三】数据表基本操作
- 【1】创建表(基础语法)
- (1)创建明细表(Duplicate Key,保留所有数据)
- (2)创建聚合表(Aggregate Key,自动聚合重复数据)
- (3)创建主键表(Primary Key,支持行级更新)
- 【2】查看表信息
- 【3】修改表结构
- 【4】数据导入
- (1)INSERT INTO 导入(小批量数据)
- (2)Broker Load(从 HDFS/S3 导入大批量数据)
- (3)Stream Load(通过 HTTP 接口导入,适合实时数据)
- 【5】数据查询(基础 + 优化)
- 【6】删除表 / 分区 / 数据
- 【四】常见的优化操作
- 【1】表结构设计优化
- (1)字段类型精细化
- (2)表类型匹配业务场景
- (3)合理的冗余字段
- 【2】分区与分桶优化
- (1)分区优化
- (2)分桶优化
- 【3】索引优化
- 【4】物化视图优化
- (1)适用场景
- (2)实操案例
- (3)物化视图维护
【一】简介
【1】介绍
Apache Doris 是一款基于 MPP 架构的高性能、实时分析型数据库。它以高效、简单和统一的特性著称,能够在亚秒级的时间内返回海量数据的查询结果。Doris 既能支持高并发的点查询场景,也能支持高吞吐的复杂分析场景。
基于这些优势,Apache Doris 非常适合用于报表分析、即席查询、统一数仓构建、数据湖联邦查询加速等场景。用户可以基于 Doris 构建大屏看板、用户行为分析、AB 实验平台、日志检索分析、用户画像分析、订单分析等应用。
【2】核心特性
(1)性能优异:自带高效的列式存储引擎,减少数据扫描量的同时还实现了超高的数据压缩比。同时Doris还提供了丰富的索引结构来加速数据读取与过滤,利用分区分桶裁剪功能,Doris可以支持在线服务业务的超高并发,单节点最高可支持上千QPS。更进一步,Apache Doris 结合了向量化执行引擎来充分发挥现代化CPU并行计算能力,辅以智能物化视图技术实现预聚合加速,并可以通过查询优化器同时进行基于规划和基于代价的查询优化。通过上述多种方式,实现了极致的查询性能。
(2)简单易用:支持标准ANSI SQL语法,包括单表聚合、排序、过滤和多表Join、子查询等,还支持窗口函数、Grouping Set等复杂SQL语法,同时用户可以通过UDF和UDAF等自定义函数来拓展系统功能。除此以外,Apache Doris 还实现了MySQL协议兼容,用户可以通过各类客户端工具来访问Doris,并支持与BI工具的无缝对接。
(3)架构精简:系统只有Frontend(FE)和Backend(BE)两个模块,其中FE节点负责用户请求的接入、查询计划的解析、元数据存储及集群管理等工作,BE节点负责数据存储和查询计划的执行,自身就是一个完备的分布式数据库管理系统,用户无需安装任何第三方管控组件即可运行起Apache Doris 集群,并且部署和升级过程都非常简易。同时,任一模块都可以支持横向拓展,集群最高可以拓展到数百个节点,支持存储超过10PB的超大规模数据。
(4)稳定可靠:支持数据多副本存储,集群具备自愈功能,自身的分布式管理框架可以自动管理数据副本的分布、修复和均衡,副本损坏时系统可以自动感知并进行修复。节点扩容时,仅需一条SQL命令即可完成,数据分片会自动在节点间均衡,无需人工干预或操作。无论是扩容、缩容、单节点故障还是在升级过程中,系统都无需停止运行,可正常提供稳定可靠的在线服务。
(5)生态丰富:提供丰富的数据同步方式,支持快速加载来自本地、Hadoop、Flink、Spark、Kafka、SeaTunnel等系统中的数据,也可以直接访问MySQL、PostgreSQL、Oracle、S3、Hive、Iceberg、Elasticsearch等系统中的数据而无需数据复制。同时存储在Doris中的数据也可以被 Spark、Flink 读取,并且可以输出给上游数据应用进行展示分析。
【3】Doris技术概述
ApacheDoris 主要基于C++ 和Java 开发,集成了Google Mesa 和Apache Impala 的技术。将Mesa 与Impala进行组合的基础上,Doris 被设计为一个不依赖于其他系统的简单且单一紧密耦合的系统,并实现了MySQL协议,使得用户可以像使用MySQL 无缝过渡到Doris,包括各种报表应用都可以通过MySQL协议连接Doris,同时获得高并发低延迟点查询性能,而且还能进行高吞吐量的即席分析查询。Doris 不仅提供大批量数据加载,而且还提供近乎实时的小批量,甚至流数据加载。此外Doris还具备可用性,可靠性,容错性和可扩展性。
Doris整体架构如下图所示,Doris 架构非常简单,只有两类进程
(1)Frontend(FE),主要负责用户请求的接入、查询解析规划、元数据的管理、节点管理相关工作。
(2)Backend(BE),主要负责数据存储、查询计划的执行。
这两类进程都是可以横向扩展的,单集群可以支持到数百台机器,数十 PB 的存储容量。并且这两类进程通过一致性协议来保证服务的高可用和数据的高可靠。这种高度集成的架构设计极大的降低了一款分布式系统的运维成本。
(1)在使用接口方面,Doris 采用 MySQL 协议,高度兼容 MySQL 语法,支持标准 SQL,用户可以通过各类客户端工具来访问 Doris,并支持与 BI 工具的无缝对接。
(2)在存储引擎方面,Doris 采用列式存储,按列进行数据的编码压缩和读取,能够实现极高的压缩比,同时减少大量非相关数据的扫描,从而更加有效利用 IO 和 CPU 资源。
(3)Doris 也支持比较丰富的索引结构,来减少数据的扫描:
支持 Sorted Compound Key Index,可以最多指定三个列组成复合排序键,通过该索引,能够有效进行数据裁剪,从而能够更好支持高并发的报表场景
Z-order Index :使用 Z-order 索引,可以高效对数据模型中的任意字段组合进行范围查询
Min/Max 索引 :有效过滤数值类型的等值和范围查询
Bloom Filter :对高基数列的等值过滤裁剪非常有效
Invert Index :能够对任意字段实现快速检索
(4)在存储模型方面,Doris 支持多种存储模型,针对不同的场景做了针对性的优化:
Aggregate Key 模型:相同 Key 的 Value 列合并,通过提前聚合大幅提升性能
Unique Key 模型:Key 唯一,相同 Key 的数据覆盖,实现行级别数据更新
Duplicate Key 模型:明细数据模型,满足事实表的明细存储
(5)在查询引擎方面,Doris 采用 MPP 的模型,节点间和节点内都并行执行,也支持多个大表的分布式 Shuffle Join,从而能够更好应对复杂查询。
【4】使用场景
数据源经过各种数据集成和加工处理后,通常会进入实时数据仓库 Doris 和离线湖仓(如 Hive、Iceberg 和 Hudi),广泛应用于 OLAP 分析场景,如下图所示:
Apache Doris 主要应用于以下场景:
(1)实时数据分析:
(1)实时报表与实时决策: 为企业内外部提供实时更新的报表和仪表盘,支持自动化流程中的实时决策需求。
(2)交互式探索分析: 提供多维数据分析能力,支持对数据进行快速的商业智能分析和即席查询(Ad Hoc),帮助用户在复杂数据中快速发现洞察。
(3)用户行为与画像分析: 分析用户参与、留存、转化等行为,支持人群洞察和人群圈选等画像分析场景。
(2)湖仓融合分析:
(1)湖仓查询加速: 通过高效的查询引擎加速湖仓数据的查询。
(2)多源联邦分析: 支持跨多个数据源的联邦查询,简化架构并消除数据孤岛。
(3)实时数据处理: 结合实时数据流和批量数据的处理能力,满足高并发和低延迟的复杂业务需求。
(3)半结构化数据分析:
日志与事件分析: 对分布式系统中的日志和事件数据进行实时或批量分析,帮助定位问题和优化性能。
【5】整体架构
Apache Doris 采用 MySQL 协议,高度兼容 MySQL 语法,支持标准 SQL。用户可以通过各类客户端工具访问 Apache Doris,并支持与 BI 工具无缝集成。在部署 Apache Doris 时,可以根据硬件环境与业务需求选择存算一体架构或存算分离架构。
(1)存算一体架构
Apache Doris 存算一体架构精简且易于维护。它包含以下两种类型的进程:
(1)Frontend (FE): 主要负责接收用户请求、查询解析和规划、元数据管理以及节点管理。
(2)Backend (BE): 主要负责数据存储和查询计划的执行。数据会被切分成数据分片(Shard),在 BE 中以多副本方式存储。
在生产环境中,可以部署多个 FE 节点以实现容灾备份。每个 FE 节点都会维护完整的元数据副本。FE 节点分为以下三种角色:
FE 和 BE 进程都可以横向扩展。单个集群可以支持数百台机器和数十 PB 的存储容量。FE 和 BE 进程通过一致性协议来保证服务的高可用性和数据的高可靠性。存算一体架构高度集成,大幅降低了分布式系统的运维成本。
(2)存算分离架构
从 3.0 版本开始,可以选择存算分离部署架构。Apache Doris 存算分离版使用统一的共享存储层作为数据存储空间。存储和计算分离后,用户可以独立扩展存储容量和计算资源,从而实现最佳性能和成本效益。存算分离架构分为以下三层:
(1)元数据层: 负责请求规划、查询解析以及元数据的存储和管理。
(2)计算层: 由多个计算组组成。每个计算组可以作为一个独立的租户承担业务计算。每个计算组包含多个无状态的 BE 节点,可以随时弹性伸缩 BE 节点。
(3)存储层: 可以使用 S3、HDFS、OSS、COS、OBS、Minio、Ceph 等共享存储来存放 Doris 的数据文件,包括 Segment 文件和反向索引文件等。
【二】数据库基本操作
【1】创建数据库
-- 创建基础数据库
CREATE DATABASE IF NOT EXISTS user_behavior;-- 创建指定属性的数据库(如设置时区、数据存储策略)
CREATE DATABASE IF NOT EXISTS sales_db
PROPERTIES ("zone" = "Asia/Shanghai", -- 时区设置"storage_medium" = "SSD", -- 存储介质(SSD/HDD)"replication_num" = "3" -- 默认副本数
);
【2】查看数据库
-- 查看所有数据库
SHOW DATABASES;-- 查看数据库详情
DESCRIBE DATABASE sales_db;-- 切换数据库
USE sales_db;
【3】修改数据库属性
-- 修改数据库默认副本数
ALTER DATABASE sales_db
SET PROPERTIES ("replication_num" = "2"
);
【4】删除数据库
-- 删除数据库(需先删除库中所有表)
DROP DATABASE IF EXISTS user_behavior;
【三】数据表基本操作
【1】创建表(基础语法)
Doris 支持明细表(Duplicate Key)、聚合表(Aggregate Key)、更新表(Unique Key)、主键表(Primary Key) 四种类型,以下是常用案例:
(1)创建明细表(Duplicate Key,保留所有数据)
-- 适用于日志、行为等需要全量保留的数据
CREATE TABLE IF NOT EXISTS user_log (user_id BIGINT COMMENT "用户ID",action STRING COMMENT "行为类型",action_time DATETIME COMMENT "行为时间",ip STRING COMMENT "IP地址"
) ENGINE=OLAP
DUPLICATE KEY(user_id, action_time) -- 排序键(非唯一)
PARTITION BY RANGE(action_time) ( -- 按时间分区PARTITION p202301 VALUES LESS THAN ('2023-02-01'),PARTITION p202302 VALUES LESS THAN ('2023-03-01')
)
DISTRIBUTED BY HASH(user_id) BUCKETS 32 -- 按user_id分桶,32个桶
PROPERTIES ("replication_num" = "3", -- 副本数"storage_medium" = "SSD" -- 存储介质
);
(2)创建聚合表(Aggregate Key,自动聚合重复数据)
-- 适用于统计分析场景(如PV/UV、销售额汇总)
CREATE TABLE IF NOT EXISTS sales_stats (date DATE COMMENT "日期",region STRING COMMENT "地区",product STRING COMMENT "产品",sales_amount BIGINT SUM COMMENT "销售额(累加)",order_count BIGINT SUM COMMENT "订单数(累加)"
) ENGINE=OLAP
AGGREGATE KEY(date, region, product) -- 聚合键(重复时按聚合函数合并)
PARTITION BY RANGE(date) (PARTITION p2023 VALUES LESS THAN ('2024-01-01')
)
DISTRIBUTED BY HASH(region, product) BUCKETS 16
PROPERTIES ("replication_num" = "3","in_memory" = "false" -- 是否全表内存存储
);
(3)创建主键表(Primary Key,支持行级更新)
-- 适用于需频繁更新的业务表(如用户信息、订单状态)
CREATE TABLE IF NOT EXISTS user_info (user_id BIGINT NOT NULL COMMENT "用户ID",username STRING COMMENT "用户名",phone STRING COMMENT "手机号",register_time DATETIME COMMENT "注册时间",status TINYINT COMMENT "状态(0-禁用,1-正常)"
) ENGINE=OLAP
PRIMARY KEY(user_id) -- 主键(唯一,支持更新)
PARTITION BY RANGE(register_time) (PARTITION p2022 VALUES LESS THAN ('2023-01-01'),PARTITION p2023 VALUES LESS THAN ('2024-01-01')
)
DISTRIBUTED BY HASH(user_id) BUCKETS 24
PROPERTIES ("replication_num" = "3","enable_unique_key_merge_on_write" = "true" -- 开启实时更新
);
【2】查看表信息
-- 查看当前库所有表
SHOW TABLES;-- 查看表结构
DESCRIBE user_info;
-- 或
SHOW CREATE TABLE user_info;-- 查看表分区信息
SHOW PARTITIONS FROM user_info;-- 查看表分桶信息
SHOW BUCKETS FROM user_info;
【3】修改表结构
-- (1)添加列
ALTER TABLE user_info ADD COLUMN email STRING COMMENT "邮箱" AFTER phone;-- (2)修改列类型/注释
ALTER TABLE user_info MODIFY COLUMN phone STRING COMMENT "手机号(新增国际区号)";-- (3)删除列
ALTER TABLE user_info DROP COLUMN email;-- (4)添加分区(针对RANGE分区表)
ALTER TABLE user_log ADD PARTITION p202303 VALUES LESS THAN ('2023-04-01');-- (5)修改表属性(如副本数)
ALTER TABLE sales_stats SET PROPERTIES ("replication_num" = "2");
【4】数据导入
大批量数据优先用Broker Load或Routine Load,小批量用INSERT。
导入时设置合理的max_filter_ratio(允许少量脏数据),避免导入失败。
(1)INSERT INTO 导入(小批量数据)
INSERT INTO user_info (user_id, username, phone, register_time, status)
VALUES
(1001, '张三', '13800138000', '2023-01-15 08:30:00', 1),
(1002, '李四', '13900139000', '2023-02-20 14:20:00', 1);
(2)Broker Load(从 HDFS/S3 导入大批量数据)
LOAD LABEL sales_db.label_sales_202301 -- 唯一标签(用于追踪状态)
(DATA INFILE("hdfs://namenode:8020/user/hive/sales/202301/*")INTO TABLE sales_statsCOLUMNS TERMINATED BY "," -- 分隔符(date_str, region, product, sales_amount, order_count)SET (date = STR_TO_DATE(date_str, '%Y-%m-%d'), -- 转换日期格式region = region,product = product,sales_amount = sales_amount,order_count = order_count)
)
WITH BROKER hdfs_broker -- 已配置的Broker名称
("hadoop.security.authentication" = "kerberos","kerberos_principal" = "doris@EXAMPLE.COM","kerberos_keytab" = "/path/to/doris.keytab"
)
PROPERTIES ("timeout" = "3600", -- 超时时间(秒)"max_filter_ratio" = "0.01" -- 允许的最大错误率
);
(3)Stream Load(通过 HTTP 接口导入,适合实时数据)
# 终端执行:从本地文件导入
curl --location-trusted -u username:password \-T data.csv \-H "label:stream_load_20230101" \-H "column_separator:," \http://doris-fe:8030/api/sales_db/sales_stats/_stream_load
【5】数据查询(基础 + 优化)
尽量利用分区裁剪(WHERE子句包含分区键)。
-- 基础查询(利用分区裁剪)
SELECT region, SUM(sales_amount)
FROM sales_stats
WHERE date BETWEEN '2023-01-01' AND '2023-01-31' -- 仅扫描p2023分区
GROUP BY region;-- 强制使用指定索引(如果有)
SELECT /*+ USE_INDEX(user_log, idx_action_time) */ action, COUNT(*)
FROM user_log
WHERE action_time > '2023-01-01'
GROUP BY action;-- 查看查询执行计划(优化性能用)
EXPLAIN
SELECT SUM(sales_amount) FROM sales_stats WHERE region = '华东';
【6】删除表 / 分区 / 数据
-- 删除分区(保留表结构)
ALTER TABLE user_log DROP PARTITION p202301;-- 清空表数据(保留表结构)
TRUNCATE TABLE user_info;-- 删除表
DROP TABLE IF EXISTS sales_stats;
【四】常见的优化操作
在 Doris 中,表的优化核心目标是提升查询性能、减少存储占用和加速数据导入,需结合表结构设计、分区分桶策略、索引优化、物化视图等多维度操作。
Doris 表优化的核心思路是:“减少扫描数据量(分区 / 索引)→ 数据分布均匀(分桶)→ 预计算结果(物化视图)→ 匹配业务场景(表类型)”。实际操作中需结合数据量、查询模式和硬件资源,优先优化高频查询路径,逐步迭代调整。
以下是具体的优化方法及实操案例:
【1】表结构设计优化
合理的表结构是性能的基础,需从字段类型、表类型、冗余度三个角度优化。
(1)字段类型精细化
原则:使用最小可行的字段类型,避免存储空间浪费和计算开销。
案例:
用TINYINT(1 字节,范围 - 128~127)存储状态值(如 0/1/2),而非INT(4 字节)。
用DATE(3 字节)存储生日 / 日期,而非DATETIME(8 字节)。
字符串长度固定时用CHAR,可变且短用VARCHAR,超长按TEXT存储(但需谨慎,大字段会降低查询效率)。
-- 优化前:字段类型冗余
CREATE TABLE user (id INT, -- 实际用户ID最大100万,可用INT(足够),但可进一步评估status INT, -- 仅0/1/2,应改为TINYINTregister_time DATETIME -- 若仅需日期,可改为DATE
);-- 优化后:类型精细化
CREATE TABLE user (id INT, -- 若ID超20亿,需用BIGINT,否则保持INTstatus TINYINT,register_date DATE
);
(2)表类型匹配业务场景
Doris 提供 4 种表类型,选择错误会导致性能大幅下降:
明细表(Duplicate Key):适合日志、行为等需全量保留的数据(无聚合需求)。
聚合表(Aggregate Key):适合统计分析(如 PV/UV、销售额),自动聚合重复数据。
主键表(Primary Key):适合需频繁更新的业务表(如用户信息、订单状态),支持行级更新。
更新表(Unique Key):适合批量更新场景(已逐步被主键表替代,建议优先用 Primary Key)。
案例:
日志类数据(如用户点击日志)→ 明细表
销售汇总数据(按日 / 地区聚合)→ 聚合表
用户基本信息(需频繁修改手机号、状态)→ 主键表
(3)合理的冗余字段
不存储可通过计算得到的字段(如 “年龄” 可由 “生日” 计算,避免冗余存储)。
关联查询频繁的小维度字段(如 “部门名称”)可适度冗余(以空间换时间,减少 Join)。
【2】分区与分桶优化
分区和分桶是 Doris 分布式存储的核心,直接影响数据扫描范围和并行度。
(1)分区优化
核心目标:通过分区裁剪(Partition Pruning)减少查询扫描的数据量。
优化策略:
(1)分区键选择:优先选择高频过滤字段(如时间、地区),且值具有连续性(便于范围查询)。
例:日志表按action_time分区,销售表按sale_date分区。
(2)分区粒度:根据数据量和查询频率调整,避免过粗(扫描范围大)或过细(分区数过多,元数据管理开销大)。
例:日均数据 1000 万→按天分区;月均 1000 万→按月分区。
(3)生命周期管理:定期删除过期分区(如保留最近 3 个月数据)。
-- 优化前:分区粒度太粗(按年分区,单分区数据量过大)
CREATE TABLE sales (sale_date DATE,region STRING,amount BIGINT
)
PARTITION BY RANGE(sale_date) (PARTITION p2023 VALUES LESS THAN ('2024-01-01')
);-- 优化后:按季度分区,配合生命周期管理
CREATE TABLE sales (sale_date DATE,region STRING,amount BIGINT
)
PARTITION BY RANGE(sale_date) (PARTITION p2023Q1 VALUES LESS THAN ('2023-04-01'),PARTITION p2023Q2 VALUES LESS THAN ('2023-07-01'),PARTITION p2023Q3 VALUES LESS THAN ('2023-10-01'),PARTITION p2023Q4 VALUES LESS THAN ('2024-01-01')
);-- 定期删除过期分区(如删除2022年数据)
ALTER TABLE sales DROP PARTITION p2022Q4;
(2)分桶优化
核心目标:使数据在集群节点间均匀分布,避免数据倾斜,提升并行计算效率。
优化策略:
(1)分桶键选择:优先选择高基数字段(如user_id、order_id),避免低基数字段(如gender,会导致数据倾斜)。
例:用户表按user_id分桶,订单表按order_id分桶。
(2)分桶数量:通常设置为 (BE 节点数 × 每个节点核心数) 的倍数(如 3 个 BE 节点,每个 8 核→分桶数 24/32/48),单个分桶大小建议 1-10GB(太小会增加元数据开销,太大则并行度不足)。
-- 优化前:分桶键基数低(region字段仅3个值,导致数据倾斜)
CREATE TABLE sales (sale_date DATE,region STRING,amount BIGINT
)
DISTRIBUTED BY HASH(region) BUCKETS 3; -- 分桶数与region值数量一致,导致每个桶数据量差异大-- 优化后:分桶键改为高基数的order_id,分桶数匹配节点数
CREATE TABLE sales (sale_date DATE,region STRING,order_id BIGINT,amount BIGINT
)
DISTRIBUTED BY HASH(order_id) BUCKETS 24; -- 3个BE节点×8核→24个桶,数据分布均匀
(3)数据倾斜处理:若已存在倾斜,可通过REBALANCE重分布数据:
-- 检查分桶数据分布
SHOW BUCKETS FROM sales;-- 重分布数据(仅对分区表有效)
ALTER TABLE sales REBALANCE PARTITION p2023Q1;
【3】索引优化
Doris 提供多种索引类型,合理使用可减少扫描行数,提升过滤效率。
(1)前缀索引(默认开启,最核心)
原理:Doris 将表的排序键(Order Key)的前 36 字节作为前缀索引,加速等值和范围查询。
优化策略:
排序键需包含高频过滤字段,且按查询频率排序(前 36 字节尽可能覆盖常用过滤条件)。
避免将长字符串放在排序键前面(会占用前缀索引空间,导致其他字段无法纳入)。
-- 优化前:排序键为(user_id, action_time),但查询更频繁用action_time过滤
CREATE TABLE user_log (user_id BIGINT,action_time DATETIME,action STRING
)
DUPLICATE KEY(user_id, action_time); -- 排序键,前缀索引为user_id(8字节)+ action_time(8字节)-- 优化后:排序键调整为(action_time, user_id),优先匹配高频过滤的action_time
CREATE TABLE user_log (user_id BIGINT,action_time DATETIME,action STRING
)
DUPLICATE KEY(action_time, user_id); -- 前缀索引优先包含action_time,提升时间范围查询效率
(2)布隆过滤器(Bloom Filter)
适用场景:对低基数字段(如region、product_id)进行高频IN或=过滤,且字段值不适合作为排序键。
不适用场景:高基数字段(如user_id,布隆过滤器误判率高)、范围查询(>/<)。
-- 为region字段添加布隆过滤器,加速地区过滤
CREATE TABLE sales (sale_date DATE,region STRING COMMENT "布隆过滤器优化地区查询",amount BIGINT
)
DUPLICATE KEY(sale_date)
DISTRIBUTED BY HASH(order_id) BUCKETS 24
PROPERTIES ("bloom_filter_columns" = "region" -- 指定需创建布隆过滤器的字段
);
(3)Bitmap 索引
适用场景:低基数且需要精确去重计数的字段(如status、category),配合bitmap_union_count等函数使用。
案例:统计不同状态的用户数:
-- 创建带bitmap索引的表
CREATE TABLE user (user_id BIGINT,status TINYINT COMMENT "0-禁用,1-正常",register_date DATE
)
PRIMARY KEY(user_id)
DISTRIBUTED BY HASH(user_id) BUCKETS 16
PROPERTIES ("bitmap_index_columns" = "status" -- 为status创建bitmap索引
);-- 利用bitmap索引快速统计各状态用户数
SELECT status, BITMAP_UNION_COUNT(user_id)
FROM user
GROUP BY status;
【4】物化视图优化
物化视图是预计算查询结果的 “快照”,可将复杂查询(如多表 Join、大聚合)的耗时从分钟级降至毫秒级。
(1)适用场景
高频执行的聚合查询(如 “按日 / 地区汇总销售额”)。
复杂 Join 查询(如用户表与订单表的关联统计)。
(2)实操案例
-- 原表:销售明细表(数据量大,直接聚合慢)
CREATE TABLE sales_detail (sale_date DATE,region STRING,product STRING,amount BIGINT
)
DUPLICATE KEY(sale_date, region, product)
PARTITION BY RANGE(sale_date)
DISTRIBUTED BY HASH(product) BUCKETS 32;-- 创建物化视图:预计算每日各地区的销售额总和
CREATE MATERIALIZED VIEW mv_sales_region_daily
AS
SELECT sale_date, region, SUM(amount) AS total_amount
FROM sales_detail
GROUP BY sale_date, region;-- 查询时自动命中物化视图(无需显式指定)
SELECT sale_date, region, SUM(amount)
FROM sales_detail
WHERE sale_date BETWEEN '2023-01-01' AND '2023-01-31'
GROUP BY sale_date, region; -- 直接从mv_sales_region_daily读取结果,速度提升10-100倍
(3)物化视图维护
自动刷新:基表数据更新时,物化视图异步刷新(可配置刷新频率)。
手动刷新:
REFRESH MATERIALIZED VIEW mv_sales_region_daily;
删除无用物化视图(避免存储和刷新开销):
DROP MATERIALIZED VIEW mv_sales_region_daily;