这次我们来看 Doris 数据库的核心操作之一:创建数据表。对于任何数据系统,表结构设计都是数据存储、查询和分析的基石。Doris 作为一款高性能的实时分析数据库,其建表语法和策略直接决定了后续查询的性能、数据导入的效率和资源使用的合理性。本文将直接切入主题,详细拆解 Doris 的建表流程、核心概念、不同表引擎的选择,并通过实测演示如何从零开始创建一张高效可用的 Doris 表。
如果你关心如何在本地或生产环境快速部署 Doris 并创建第一张表,或者希望优化现有表结构以提升查询性能,这篇文章将提供可直接落地的操作指南。我们将重点关注建表语法的每个关键参数、不同表模型(Duplicate/Aggregate/Unique)的适用场景、分区与分桶策略的设计,以及如何通过 Doris Manager 等工具简化操作。全文将以“先理解概念,再动手操作”的顺序展开,确保读者能清晰掌握 Doris 建表的精髓。
1. 核心能力速览:Doris 建表
在深入细节之前,我们先通过一个表格快速了解 Doris 建表的核心特性和要求,这有助于你判断是否适合继续深入。
| 能力项 | 说明 |
|---|---|
| 数据库类型 | 实时分析数据库 (Real-Time Analytical Database) |
| 表引擎支持 | 支持 Duplicate(明细)、Aggregate(聚合)、Unique(主键)三种数据模型 |
| 分区与分桶 | 支持 Range Partition(范围分区)和 Hash Bucket(哈希分桶),是性能关键 |
| 索引能力 | 内置智能索引(前缀索引)、支持 Bloom Filter、Bitmap 等二级索引 |
| 硬件门槛 | 支持 X86/ARM 架构。内存和磁盘 I/O 是性能关键,无特定显卡要求。 |
| 部署方式 | 支持单机部署(测试)与分布式集群部署(生产)。本文演示基于单机。 |
| 启动与访问 | 通过 MySQL 协议访问,可使用任意 MySQL 客户端(如mysql命令行, DBeaver)或 Doris Manager Web UI。 |
| 是否支持 API | 原生支持标准 SQL 的 DDL(数据定义语言)进行建表,同时提供 RESTful API 用于集群管理。 |
| 是否支持批量任务 | 核心能力之一,支持多种批量数据导入方式(Broker Load, Routine Load, Spark Load等)。 |
| 适合场景 | 实时看板、即席查询(Ad-hoc)、日志分析、用户行为分析等需要亚秒级响应的 OLAP 场景。 |
2. 适用场景与使用边界
Doris 的建表设计并非通用型,它有明确的擅长领域和使用边界。
它最适合谁?
- 数据分析师与工程师:需要快速进行多维度、大体量的交互式分析,对查询延迟敏感。
- 后端开发与架构师:需要为应用构建实时数据仓库或宽表,提供统一的数据服务层。
- 运维与SRE团队:用于集中分析和监控日志、指标数据。
它能解决什么问题?
- 高并发快速查询:通过预聚合(Aggregate 模型)、前缀索引、分区裁剪和分桶优化,实现海量数据下的亚秒级查询。
- 实时数据更新:Unique 模型支持基于主键的 Upsert(更新/插入)操作,适用于需要实时更新的维度表或结果表。
- 简化数据架构:一个系统同时支持高吞吐批量导入和实时数据流接入,减少数据在多个系统间流转的复杂度。
它不适合什么场景?
- 高频单行事务:Doris 不是 OLTP(联机事务处理)数据库,不适合每秒数千次的单行增删改操作。
- 超宽列且频繁更新:如果表有数百列且每一列都可能被随机更新,维护成本会很高。
- 非结构化数据存储:不适合存储图片、视频、长文本等非结构化数据。
使用边界与合规提醒:
- 数据合规:在 Doris 中存储和处理数据前,需确保遵守相关数据安全法规(如个人信息保护法),对敏感信息进行脱敏或加密。
- 资源规划:分区和分桶策略设计不当可能导致数据倾斜,影响集群稳定性,需在生产环境前充分测试。
- 模型选择:数据模型(Duplicate/Aggregate/Unique)一旦选定,更改成本较高,需在业务初期谨慎设计。
3. 环境准备与前置条件
在创建第一张 Doris 表之前,你需要一个可用的 Doris 环境。以下是基于单机部署的快速准备清单。
1. 操作系统与依赖
- 操作系统:推荐 CentOS 7+ 或 Ubuntu 16.04+。本文演示环境为 Ubuntu 20.04。
- Java:运行 Doris(FE/BE)需要 JDK 8 或 JDK 11。确保已安装并配置
JAVA_HOME。# 检查Java版本 java -version - 磁盘空间:建议预留至少 50GB 的可用空间用于安装、数据存储及日志。
2. 获取 Doris 安装包从 Apache Doris 官网或 GitHub Release 页面下载最新稳定版本的二进制包。例如,下载 doris-2.0.4-x86_64.tar.gz。
wget https://apache-doris-releases.oss-accelerate.aliyuncs.com/apache-doris-2.0.4-bin-x86_64.tar.gz tar -zxvf apache-doris-2.0.4-bin-x86_64.tar.gz cd apache-doris-2.0.4/3. 部署与启动 Doris(单机模式)Doris 由 Frontend(FE)和 Backend(BE)组成。单机模式下,一台机器同时运行 FE 和 BE。
- 启动 FE:
# 进入FE目录 cd fe # 启动FE(首次启动需执行初始化) ./bin/start_fe.sh --daemon # 查看日志确认启动成功 tail -f log/fe.log | grep -i “thrift” - 启动 BE:
# 进入BE目录 cd ../be # 启动BE ./bin/start_be.sh --daemon # 查看日志确认启动成功 tail -f log/be.log | grep -i “heartbeat” - 将 BE 添加到 FE:通过 MySQL 客户端连接 FE,执行以下 SQL。
mysql -h 127.0.0.1 -P 9030 -uroot-- 在MySQL客户端中执行 ALTER SYSTEM ADD BACKEND “127.0.0.1:9050”;
4. 验证安装使用 MySQL 客户端连接 Doris FE(默认端口 9030),能成功连接并执行SHOW FRONTENDS;和SHOW BACKENDS;查看节点状态即表示环境就绪。
mysql -h 127.0.0.1 -P 9030 -uroot -e “SHOW FRONTENDS;”4. 建表核心概念与语法拆解
Doris 的CREATE TABLE语句比传统 MySQL 更复杂,因为它承载了数据模型、分布方式和索引策略。下面我们拆解一个完整的建表示例。
4.1 基础建表语句结构
CREATE TABLE [IF NOT EXISTS] [database.]table_name ( column_definition1, column_definition2, ... ) [ENGINE = olap] -- Doris 默认引擎 [KEY(column_name, ...)] -- 指定键列(前缀索引列) [DISTRIBUTED BY HASH(column_name, ...) BUCKETS bucket_num] -- 指定分桶列和桶数 [PARTITION BY RANGE(column_name)(...)] -- 指定分区列和范围 [PROPERTIES ("key"="value", ...)]; -- 设置表属性4.2 三大数据模型选择
这是 Doris 建表最关键的决策点,决定了数据如何存储和聚合。
1. Duplicate 明细模型
- 特点:存储最原始的明细数据,不做任何聚合。即使两行数据完全相同,也会保留。
- 适用场景:需要保留所有原始数据的日志分析、行为流水、事务事实表。
- 建表示例:
CREATE TABLE IF NOT EXISTS demo.user_behavior_dup ( `user_id` BIGINT, `item_id` BIGINT, `category_id` INT, `behavior` VARCHAR(10), `ts` DATETIME ) DUPLICATE KEY(user_id, item_id) -- 指定排序列,用于前缀索引 DISTRIBUTED BY HASH(user_id) BUCKETS 10 PROPERTIES ( “replication_num” = “1” -- 副本数,单机设为1 );DUPLICATE KEY仅指定排序列(前缀索引),并非主键,不保证唯一。
2. Aggregate 聚合模型
- 特点:数据在导入时,会根据
AGGREGATE KEY指定的列进行聚合。对于指标列,需要指定聚合函数(如 SUM, MAX, MIN, REPLACE)。 - 适用场景:需要预聚合的统计报表、汇总指标表。
- 建表示例:
CREATE TABLE IF NOT EXISTS demo.sales_agg ( `date` DATE, `product_id` INT, `city` VARCHAR(20), `sales_amount` BIGINT SUM, -- 指标列,聚合方式为SUM `max_price` DOUBLE MAX -- 指标列,聚合方式为MAX ) AGGREGATE KEY(date, product_id, city) -- 聚合键 DISTRIBUTED BY HASH(product_id) BUCKETS 8 PROPERTIES ( “replication_num” = “1” );- 查询时,Doris 会自动返回聚合后的结果,极大提升查询性能。
3. Unique 主键模型
- 特点:数据按主键唯一,支持 Upsert。新导入的数据行会替换相同主键的旧数据行。
- 适用场景:需要实时更新的用户画像表、商品维度表、实时结果表。
- 建表示例:
CREATE TABLE IF NOT EXISTS demo.user_profile_unique ( `user_id` BIGINT, `username` VARCHAR(50), `city` VARCHAR(20), `last_login` DATETIME, `score` INT ) UNIQUE KEY(user_id) -- 指定主键列 DISTRIBUTED BY HASH(user_id) BUCKETS 10 PROPERTIES ( “replication_num” = “1”, “enable_persistent_index” = “true” -- 可选,启用持久化索引以提升性能 );
4.3 分区与分桶:数据分布的艺术
这是影响查询性能和集群稳定性的核心设计。
1. 分区(PARTITION BY RANGE)
- 目的:将表按范围(通常是时间)划分为独立管理的部分。查询时可以通过“分区裁剪”只扫描相关分区,大幅减少数据读取量。
- 常用列:
DATE或DATETIME类型的时间列。 - 示例:
PARTITION BY RANGE(`dt`) ( PARTITION `p202401` VALUES LESS THAN (“2024-02-01”), PARTITION `p202402` VALUES LESS THAN (“2024-03-01”), PARTITION `p202403` VALUES LESS THAN (“2024-04-01”) )
2. 分桶(DISTRIBUTED BY HASH)
- 目的:将分区内的数据进一步打散到多个 Bucket(桶)中,实现数据的并行处理和负载均衡。
- 分桶列选择:应选择高基数、经常作为查询条件的列(如
user_id,order_id)。 - 分桶数(BUCKETS):建议设置为集群 BE 节点数量的整数倍,通常推荐在 10-100 之间。单机测试可先设置为 5-10。
- 示例:
DISTRIBUTED BY HASH(user_id) BUCKETS 10
5. 实战:创建一张完整的 Doris 表
假设我们要为电商场景创建一张用户订单明细表,要求按天分区、按用户分桶,并保留所有原始数据。
步骤 1:创建数据库
CREATE DATABASE IF NOT EXISTS ecommerce_db; USE ecommerce_db;步骤 2:执行建表语句
CREATE TABLE IF NOT EXISTS order_detail ( `order_id` BIGINT, `user_id` BIGINT, `product_id` INT, `category` VARCHAR(50), `price` DECIMAL(10, 2), `quantity` INT, `order_time` DATETIME, `city` VARCHAR(20), `payment_method` VARCHAR(20) ) ENGINE = olap DUPLICATE KEY(order_id, user_id, order_time) -- 明细模型,指定排序列 COMMENT “电商订单明细表” PARTITION BY RANGE(`order_time`) -- 按订单时间范围分区 ( PARTITION `p202405` VALUES LESS THAN (“2024-06-01”), PARTITION `p202406` VALUES LESS THAN (“2024-07-01”), PARTITION `p202407` VALUES LESS THAN (“2024-08-01”) ) DISTRIBUTED BY HASH(`user_id`) BUCKETS 8 -- 按用户ID哈希分桶 PROPERTIES ( “replication_num” = “1”, -- 单副本 “storage_medium” = “SSD”, -- 存储介质 “storage_cooldown_time” = “9999-12-31 23:59:59” -- 冷却时间(用于冷热数据分层,此处设为永不移至HDD) );步骤 3:验证表创建成功
-- 查看表结构 DESC order_detail; -- 查看建表语句 SHOW CREATE TABLE order_detail; -- 查看分区信息 SHOW PARTITIONS FROM order_detail;6. 通过 Doris Manager 可视化建表
对于不习惯命令行的用户,可以使用 Doris Manager(Doris 的可视化管理工具)来建表,操作更直观。
1. 启动并访问 Doris Manager
- 从 Doris 社区获取 Doris Manager 的安装包并启动。
- 通过浏览器访问
http://<manager_host>:<port>,登录后添加你的 Doris 集群(FE 地址和端口)。
2. 可视化建表流程
- 在 Doris Manager 中,导航到目标数据库。
- 点击“新建表”,会打开一个表单式界面。
- 填写基本信息:表名、注释、引擎(OLAP)。
- 设计列:通过表单添加列名、类型、是否可为空、默认值等。
- 选择数据模型:通过下拉框选择 Duplicate/Aggregate/Unique。
- 设置分区与分桶:在相应标签页下,配置分区列、分区范围、分桶列和分桶数。
- 设置属性:在“属性”页中,填写
replication_num等参数。 - 预览与执行:工具会生成对应的 SQL,确认无误后点击“执行”即可创建。
这种方式降低了语法记忆成本,特别适合初学者或进行表结构原型设计。
7. 数据导入验证与性能观察
表创建好后,需要导入数据验证其可用性,并观察资源占用。
1. 使用 INSERT INTO 插入测试数据
INSERT INTO order_detail VALUES (10001, 2001, 3001, ‘Electronics’, 2999.00, 1, ‘2024-06-15 10:30:00’, ‘Beijing’, ‘CreditCard’), (10002, 2002, 3002, ‘Clothing’, 199.00, 2, ‘2024-06-16 14:20:00’, ‘Shanghai’, ‘Alipay’), (10003, 2001, 3003, ‘Books’, 59.80, 1, ‘2024-06-17 09:15:00’, ‘Beijing’, ‘WeChatPay’);2. 使用 Broker Load 批量导入本地文件准备一个 CSV 文件order_data.csv:
10004,2003,3004,Home,450.50,1,2024-06-18 16:45:00,Guangzhou,CreditCard 10005,2004,3005,Electronics,1500.00,1,2024-06-19 11:10:00,Shenzhen,Alipay执行导入命令:
LOAD LABEL ecommerce_db.label_20240620 -- 导入任务标签 ( DATA INFILE(“file:///path/to/your/order_data.csv”) -- 文件路径 INTO TABLE order_detail COLUMNS TERMINATED BY “,” (order_id, user_id, product_id, category, price, quantity, order_time, city, payment_method) ) WITH BROKER “broker_name” -- 需预先配置Broker PROPERTIES ( “timeout” = “3600” );通过SHOW LOAD WHERE LABEL = ‘label_20240620’;查看导入状态。
3. 查询验证与性能观察
-- 简单查询验证 SELECT * FROM order_detail WHERE user_id = 2001; -- 聚合查询测试(即使明细模型也可聚合) SELECT city, COUNT(*) as order_count, SUM(price*quantity) as total_amount FROM order_detail WHERE order_time >= ‘2024-06-15’ GROUP BY city;- 资源占用观察:在另一个终端,可以通过
top或htop命令观察 BE 进程的内存和 CPU 占用。Doris 的查询性能主要消耗在 BE 节点的内存和磁盘 I/O 上。首次查询可能因为缓存未命中而较慢,后续查询会显著加快。
8. 常见问题与排查方法
在创建和使用 Doris 表时,你可能会遇到以下问题。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 建表失败,报语法错误 | SQL 语法错误,或使用了不支持的函数/类型。 | 仔细检查错误信息,定位出错行。 | 对照官方文档修正语法,确保关键字、括号、逗号使用正确。 |
| 建表成功,但数据导入失败 | 1. 文件路径或格式错误。 2. 列数或类型不匹配。 3. 分区/分桶列值不符合规则。 | 1. 检查SHOW LOAD状态和错误详情。2. 核对源文件与表结构。 | 1. 确保文件可访问,分隔符正确。 2. 调整表结构或数据文件。 3. 确保导入数据的分区列值在已定义分区范围内。 |
| 查询速度非常慢 | 1. 未命中分区裁剪。 2. 分桶列选择不当导致数据倾斜。 3. 没有合适的索引。 | 1. 使用EXPLAIN查看查询计划。2. 检查数据分布 SHOW DATA。 | 1. 在 WHERE 条件中使用分区列。 2. 选择高基数列作为分桶列,调整分桶数。 3. 考虑在常用查询条件列上创建 Rollup 表(物化视图)。 |
ALTER TABLE添加列后,查询报错 | 新列默认值问题,或历史数据分区与新结构不兼容。 | 检查表结构变更记录SHOW ALTER TABLE COLUMN。 | 对于 Aggregate/Unique 模型,添加非 Key 列需指定聚合函数或默认值。建议在业务低峰期执行 Schema Change。 |
| 单机部署,磁盘空间不足 | 数据文件、日志文件快速增长。 | 使用df -h查看磁盘使用率。 | 1. 清理过期数据(DROP PARTITION)。2. 调整数据保留策略。 3. 扩容磁盘或迁移至更大容量机器。 |
| 通过 MySQL 客户端连接被拒绝 | FE 未启动,或端口错误,或网络不通。 | 1. 检查 FE 进程 `ps -ef | grep fe。<br>2. 检查 FE 日志log/fe.log`。3. 检查防火墙。 |
9. 最佳实践与使用建议
为了在生产环境中更稳定、高效地使用 Doris,请遵循以下建议。
- 设计先行,测试验证:在正式建表前,使用小规模数据(如 1-10GB)测试不同的分区、分桶和模型设计,通过典型查询语句验证性能。
- 分区策略:
- 按时间分区是最常见的做法,便于管理数据生命周期(TTL)。
- 单个分区数据量建议在 1GB - 10GB 之间,避免分区过多或过大。
- 使用动态分区(
dynamic_partition)自动管理按天/月创建的分区。
- 分桶策略:
- 选择高基数、常用于
GROUP BY或WHERE条件的列作为分桶列。 - 分桶数建议是 BE 节点数的整数倍,通常 10-100 个桶是合理的起点。
- 避免使用低基数列(如性别、状态标志)作为分桶列,会导致数据严重倾斜。
- 选择高基数、常用于
- 数据模型选择:
- 明细数据,需保留所有记录->
Duplicate。 - 需要预聚合的统计报表->
Aggregate。 - 需要按主键实时更新的维度表->
Unique。
- 明细数据,需保留所有记录->
- 索引与 Rollup:
- 充分利用前缀索引,将高频查询条件列放在
KEY列的前面。 - 对于复杂且固定的聚合查询,创建 Rollup(物化视图)可以极大提升查询速度。
- 充分利用前缀索引,将高频查询条件列放在
- 数据导入:
- 大批量导入优先使用
Broker Load或Spark Load。 - 实时流导入使用
Routine Load。 - 避免高频、小批量的
INSERT INTO,性能不佳。
- 大批量导入优先使用
- 监控与维护:
- 定期查看集群容量和负载(Doris Manager 或
SHOW PROC命令)。 - 设置合理的数据过期策略,及时删除历史分区。
- 定期查看集群容量和负载(Doris Manager 或
创建 Doris 数据表是一个融合了数据建模、系统架构和性能调优的综合性任务。核心在于根据业务查询模式,选择正确的数据模型,并设计合理的分区与分桶策略。从本文的明细模型订单表开始,你可以逐步尝试 Aggregate 模型做聚合分析,或用 Unique 模型维护实时维度表。记住,在投入生产前,务必用真实的数据量和查询模式进行充分的性能测试。