尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Doris建表实战指南:从核心模型到分区索引的完整设计

Doris建表实战指南:从核心模型到分区索引的完整设计 这次我们来看 Doris 数据库的核心操作之一创建数据表。对于任何数据系统表结构设计都是数据存储、查询和分析的基石。Doris 作为一款高性能的实时分析型数据库其建表语法在支持标准 SQL 的同时也提供了大量针对海量数据分析场景的优化选项。本文将直接切入主题详细拆解 Doris 的建表流程、核心概念、不同表模型的选择并提供一个从环境准备到表创建、数据验证的完整实操指南。如果你关心如何在本地或生产环境中快速部署 Doris 并创建出高性能的数据表本文将提供清晰的路径。我们将重点关注 Doris 的几种核心表模型Duplicate、Aggregate、Unique解释它们各自的适用场景、存储特性和查询性能影响。同时也会涵盖分区、分桶、索引、物化视图等高级特性帮助你设计出既能满足业务需求又能充分发挥 Doris 性能优势的表结构。1. 核心能力速览在深入细节之前我们先通过一个表格快速了解 Doris 建表的核心能力和特点这有助于你判断它是否适合你的场景。能力项说明项目类型高性能、实时的MPP分析型数据库表模型支持 Duplicate明细、Aggregate聚合、Unique主键三种核心模型以及基于Unique的Merge-on-Write模型。数据分布支持两级数据划分分区Partition和分桶Bucket。分区常用于管理数据生命周期分桶用于数据打散和查询并行。索引内置智能前缀索引Short Key Index同时支持Bloom Filter索引、Bitmap索引等加速查询。数据更新Aggregate和Unique模型支持数据更新。Unique模型提供“读时合并”和“写时合并”两种更新方式。物化视图支持创建基于基表的预聚合物化视图查询自动路由加速聚合查询。硬件门槛支持X86/ARM架构。内存和磁盘I/O是性能关键。单机测试建议8G以上内存生产环境需根据数据量和并发规划。启动方式通过MySQL客户端、Doris Web UI如Doris Manager或JDBC等方式连接Doris FE节点执行SQL。是否支持API是。提供标准MySQL协议接口任何兼容MySQL的客户端、驱动或BI工具均可连接。是否支持批量任务是。支持LOAD LABEL方式批量导入数据如HDFS、S3、本地文件也支持通过INSERT INTO SELECT进行ETL。适合场景实时报表、即席查询、日志分析、用户行为分析、数据仓库等需要低延迟、高并发查询的OLAP场景。2. 适用场景与使用边界Doris 的建表设计紧密围绕其分析型数据库的定位。理解其适用场景和边界能帮助你做出正确的技术选型和设计决策。适合谁用数据分析师与BI工程师需要执行复杂、快速的即席查询对查询响应时间敏感。后端开发与数据平台团队需要构建实时数据看板、用户画像分析、日志监控等系统。数仓开发人员在构建实时数仓层如DWD、DWS时需要一个高性能的查询引擎。能解决什么问题高并发点查与聚合查询通过前缀索引、物化视图等特性即使在海量数据中也能快速返回结果。实时数据更新与删除支持 Upsert 和 Delete 操作满足实时数仓中对维度表或事务表更新的需求。简化数据架构将传统的“Hadoop Hive Presto/Impala”复杂栈简化为一个统一的系统降低运维成本。标准SQL支持兼容MySQL协议学习成本低现有生态工具如Tableau、Metabase可无缝接入。不适合什么场景高频率TP事务处理Doris不是OLTP数据库不适合每秒数千上万次的小事务写入如支付交易。虽然支持更新但设计初衷是分析。超大规模宽表存储单表列数过多如上千列可能影响查询优化和存储效率。应遵循数仓建模规范适度宽表。非结构化数据存储Doris擅长处理结构化、半结构化数据不适合存储图片、视频等二进制大对象。合规与使用边界数据安全建表时需考虑敏感字段如手机号、身份证的加密存储或脱敏处理。资源隔离在多租户环境下需要通过集群、数据库、用户权限进行资源隔离避免相互影响。成本控制分区和副本数直接影响存储成本需根据数据冷热和重要性合理规划。3. 环境准备与前置条件在开始创建 Doris 表之前你需要一个可用的 Doris 环境。这里我们以单机部署为例概述环境要求。操作系统LinuxCentOS 7, Ubuntu 16.04 等是推荐的生产环境。macOS 和 Windows 可用于开发测试通过Docker或虚拟机。基础软件依赖JavaDoris FE前端需要 JDK 8 或更高版本推荐 OpenJDK 8/11。GCC用于从源码编译如果使用预编译包可忽略。硬件资源建议测试环境CPU4核或以上。内存8 GB 或以上。FE 和 BE 会占用一定内存。磁盘50 GB 以上可用空间建议使用 SSD 以获得更好的 I/O 性能。网络确保部署机器之间网络互通单机部署无需考虑。Doris 集群组件Frontend (FE)负责元数据管理、客户端连接、查询规划。Backend (BE)负责数据存储和查询执行。Broker用于访问外部存储系统如HDFS、S3进行数据导入导出。对于首次接触的用户建议从官网下载最新的预编译版本进行单机部署这是最快捷的启动方式。4. 安装部署与启动方式我们以 Linux 单机部署为例演示如何快速启动一个 Doris 集群。步骤 1下载与解压从 Apache Doris 官网或 GitHub Release 页面下载对应版本的二进制包。# 示例下载 doris-2.0.0-bin-x64.tar.gz wget https://apache-doris-releases.oss-accelerate.aliyuncs.com/apache-doris-2.0.0-bin-x64.tar.gz tar -zxvf apache-doris-2.0.0-bin-x64.tar.gz cd apache-doris-2.0.0-bin-x64步骤 2配置 FE进入 FE 的配置文件目录进行修改。cd fe/conf cp fe.conf.template fe.conf vi fe.conf关键配置项单机可主要关注# 元数据目录确保有写入权限 meta_dir ${DORIS_HOME}/doris-meta # 查询端口和RPC端口默认即可 query_port 9030 rpc_port 9020步骤 3启动 FEcd ../bin ./start_fe.sh --daemon检查是否启动成功# 查看日志 tail -f ../log/fe.log # 或使用mysql客户端连接初始无密码 mysql -h 127.0.0.1 -P 9030 -uroot步骤 4配置并启动 BEcd ../../be/conf cp be.conf.template be.conf vi be.conf关键配置项# 数据存储目录可配置多个用分号隔开 storage_root_path ${DORIS_HOME}/storage # BE端口 be_port 9060 webserver_port 8040启动 BEcd ../bin ./start_be.sh --daemon tail -f ../log/be.log步骤 5添加 BE 节点到集群使用 MySQL 客户端连接 FE执行以下 SQL-- 在FE中执行 ALTER SYSTEM ADD BACKEND your_be_host_ip:9050;单机部署时your_be_host_ip一般为127.0.0.1。步骤 6访问 Web UI可选Doris 本身提供了 FE 的 Web 界面默认端口 8030你可以通过浏览器访问http://your_fe_host:8030查看系统状态。更强大的管理工具是 Doris Manager需要单独部署。至此一个单机 Doris 集群已启动完成可以通过 MySQL 客户端如mysql,DBeaver,Navicat连接FE的9030端口进行操作。5. 功能测试与效果验证创建第一张表现在我们进入核心环节创建 Doris 表。我们将创建三种不同模型的表并插入数据验证其行为。5.1 创建数据库与用户首先连接 Doris 并创建一个测试数据库。-- 使用root用户连接初始无密码 mysql -h 127.0.0.1 -P 9030 -uroot -- 创建测试数据库 CREATE DATABASE IF NOT EXISTS test_db; USE test_db;5.2 创建 Duplicate 明细模型表适用场景存储原始明细数据如日志、行为流水不需要预聚合需要保留所有维度细节。CREATE TABLE IF NOT EXISTS duplicate_table ( user_id BIGINT NOT NULL COMMENT 用户ID, date DATE NOT NULL COMMENT 数据灌入日期, timestamp DATETIME NOT NULL COMMENT 事件时间戳, city VARCHAR(20) COMMENT 城市, age SMALLINT COMMENT 年龄, sex TINYINT COMMENT 性别, last_visit_date DATETIME REPLACE DEFAULT 1970-01-01 00:00:00 COMMENT 最后访问时间, cost BIGINT SUM DEFAULT 0 COMMENT 总花费, max_dwell_time INT MAX DEFAULT 0 COMMENT 最大停留时间, min_dwell_time INT MIN DEFAULT 99999 COMMENT 最小停留时间 ) ENGINEolap DUPLICATE KEY(user_id, date, timestamp, city, age, sex) COMMENT 明细模型测试表 PARTITION BY RANGE(date) ( PARTITION p202301 VALUES LESS THAN (2023-02-01), PARTITION p202302 VALUES LESS THAN (2023-03-01), PARTITION p202303 VALUES LESS THAN (2023-04-01) ) DISTRIBUTED BY HASH(user_id) BUCKETS 8 PROPERTIES ( replication_num 1, -- 副本数单机设为1 storage_medium SSD );关键点解析DUPLICATE KEY指定了明细模型的排序列。数据将按照这些列的顺序存储用于前缀索引加速查询。它并不是唯一约束允许重复。PARTITION BY RANGE按日期范围分区便于管理数据生命周期如定期删除旧分区。DISTRIBUTED BY HASH指定分桶列和桶数。数据按user_id的哈希值分布到 8 个桶中是实现并行和负载均衡的关键。PROPERTIES设置副本数、存储介质等属性。5.3 创建 Aggregate 聚合模型表适用场景需要实时聚合统计的业务如PV/UV、销售额、在线人数等。写入时即进行聚合节省查询时的计算开销。CREATE TABLE IF NOT EXISTS aggregate_table ( user_id BIGINT NOT NULL COMMENT 用户ID, date DATE NOT NULL COMMENT 数据灌入日期, city VARCHAR(20) COMMENT 城市, last_visit_date DATETIME REPLACE DEFAULT 1970-01-01 00:00:00 COMMENT 最后访问时间, total_cost BIGINT SUM DEFAULT 0 COMMENT 总花费, max_dwell_time INT MAX DEFAULT 0 COMMENT 最大停留时间 ) ENGINEolap AGGREGATE KEY(user_id, date, city) COMMENT 聚合模型测试表 PARTITION BY RANGE(date) ( PARTITION p202301 VALUES LESS THAN (2023-02-01), PARTITION p202302 VALUES LESS THAN (2023-03-01) ) DISTRIBUTED BY HASH(user_id) BUCKETS 4 PROPERTIES ( replication_num 1 );关键点解析AGGREGATE KEY指定聚合维度列。除了这些 Key 列其他列必须指定聚合函数如SUM,MAX,MIN,REPLACE。REPLACE表示相同 Key 下新值替换旧值。SUM表示相同 Key 下值累加。插入相同user_id,date,city的数据时total_cost会累加last_visit_date会被更新为最新的值。5.4 创建 Unique 主键模型表Merge-on-Read适用场景需要按主键进行 Upsert更新插入的场景如用户维度表、商品信息表等。CREATE TABLE IF NOT EXISTS unique_table_mow ( user_id BIGINT NOT NULL COMMENT 用户ID, username VARCHAR(50) NOT NULL COMMENT 用户名, city VARCHAR(20) COMMENT 城市, age SMALLINT COMMENT 年龄, sex TINYINT COMMENT 性别, phone VARCHAR(15) COMMENT 电话, address VARCHAR(500) COMMENT 地址, register_time DATETIME COMMENT 注册时间 ) ENGINEolap UNIQUE KEY(user_id) COMMENT 主键模型表读时合并 DISTRIBUTED BY HASH(user_id) BUCKETS 4 PROPERTIES ( replication_num 1, enable_unique_key_merge_on_write true -- 开启写时合并提升点查性能 );关键点解析UNIQUE KEY指定唯一键主键Doris 会保证该键的唯一性。enable_unique_key_merge_on_write设置为true即启用 Merge-on-Write 模式。在该模式下更新操作在写入时即完成合并查询时无需额外合并显著提升了点查性能但写入吞吐会有轻微下降。默认为false即 Merge-on-Read 模式。5.5 插入数据验证表行为我们向刚创建的三张表插入数据观察其不同行为。1. 向 Duplicate 表插入数据INSERT INTO duplicate_table VALUES (10001, 2023-01-15, 2023-01-15 08:00:00, 北京, 25, 1, 2023-01-15 08:00:00, 100, 10, 5), (10001, 2023-01-15, 2023-01-15 20:00:00, 北京, 25, 1, 2023-01-15 20:00:00, 200, 20, 15), (10002, 2023-01-16, 2023-01-16 09:00:00, 上海, 30, 2, 2023-01-16 09:00:00, 150, 8, 8); SELECT * FROM duplicate_table ORDER BY timestamp;预期结果你会看到3 条独立的记录。即使user_id,date相同也因为timestamp不同而作为两条记录存储。聚合函数列如costSUM在明细模型中不会自动聚合。2. 向 Aggregate 表插入数据INSERT INTO aggregate_table VALUES (10001, 2023-01-15, 北京, 2023-01-15 08:00:00, 100, 10), (10001, 2023-01-15, 北京, 2023-01-15 20:00:00, 200, 25), (10002, 2023-01-16, 上海, 2023-01-16 09:00:00, 150, 8); SELECT * FROM aggregate_table ORDER BY user_id, date;预期结果你会看到2 条记录。用户 10001 在北京 2023-01-15 的数据被合并为一条last_visit_date被替换为2023-01-15 20:00:00total_cost累加为 300max_dwell_time取最大值 25。3. 向 Unique 表插入并更新数据-- 第一次插入 INSERT INTO unique_table_mow VALUES (10001, 张三, 北京, 25, 1, 13800138000, 朝阳区, 2022-01-01), (10002, 李四, 上海, 30, 2, 13900139000, 浦东新区, 2022-02-01); SELECT * FROM unique_table_mow; -- 更新用户10001的城市和电话 (使用INSERT实现Upsert) INSERT INTO unique_table_mow (user_id, username, city, phone) VALUES (10001, 张三, 深圳, 13600136000) ON DUPLICATE KEY UPDATE city VALUES(city), phone VALUES(phone); SELECT * FROM unique_table_mow WHERE user_id 10001;预期结果第一次查询有两条记录。执行 Upsert 后用户 10001 的city和phone字段被更新其他字段保持不变。这验证了主键模型的 Upsert 能力。6. 接口 API 与批量任务Doris 通过 MySQL 协议提供访问接口这使得批量数据导入变得非常灵活。6.1 通过 MySQL 协议进行批量插入任何支持 MySQL 协议的客户端或编程语言驱动都可以执行批量INSERT。# Python 示例 (使用 pymysql) import pymysql connection pymysql.connect( host127.0.0.1, port9030, userroot, password, # 初始无密码 databasetest_db, charsetutf8mb4 ) try: with connection.cursor() as cursor: # 批量插入数据到 duplicate_table sql INSERT INTO duplicate_table (user_id, date, timestamp, city, age, sex, cost) VALUES (%s, %s, %s, %s, %s, %s, %s) data [ (10003, 2023-01-17, 2023-01-17 10:00:00, 广州, 28, 1, 300), (10004, 2023-01-17, 2023-01-17 11:00:00, 深圳, 35, 2, 450), ] cursor.executemany(sql, data) connection.commit() finally: connection.close()6.2 使用 LOAD LABEL 进行大批量数据导入对于海量数据如日志文件、HDFS/S3 上的数据INSERT语句效率不高。Doris 提供了LOAD LABEL命令进行批量的、事务性的数据导入。假设你有一个本地 CSV 文件data.csv10005,2023-01-18,2023-01-18 12:00:00,杭州,26,1,500 10006,2023-01-18,2023-01-18 13:00:00,南京,40,2,600-- 1. 创建导入任务 LOAD LABEL test_db.label_20240118_01 ( DATA INFILE(file:///path/to/your/data.csv) -- 本地文件路径 INTO TABLE duplicate_table COLUMNS TERMINATED BY , (user_id, date, timestamp, city, age, sex, cost) ) WITH BROKER broker_name -- 本地文件导入可使用内置的broker或设置为空 PROPERTIES ( timeout 3600 ); -- 2. 查看导入状态 SHOW LOAD WHERE LABEL label_20240118_01;关键点LOAD LABEL是一个异步操作可以通过SHOW LOAD查看状态State为FINISHED表示成功。对于本地文件broker_name可以留空或使用broker。也支持从 HDFS、S3、OSS 等外部存储导入需正确配置 Broker 和路径。6.3 通过 INSERT INTO SELECT 进行 ETL你还可以从 Doris 内的其他表或通过外部表如 MySQL、Elasticsearch进行数据转换和导入。-- 从另一张表聚合后导入 INSERT INTO aggregate_table (user_id, date, city, total_cost) SELECT user_id, date, city, SUM(cost) as total_cost FROM duplicate_table WHERE date 2023-01-15 GROUP BY user_id, date, city;7. 资源占用与性能观察建表时的设计决策直接影响集群的资源占用和查询性能。以下是一些关键的观察点和优化思路。1. 分区与分桶的影响分区Partition主要用于数据管理。过多的分区会增加元数据负担影响 FE 性能。通常按时间天/月分区是合理的选择。分桶Bucket直接影响数据分布的均匀性和查询并行度。桶数过多每个桶数据量少可能增加元数据开销和碎片。桶数过少每个桶数据量大不利于并发查询且可能加剧数据倾斜。建议单个 Tablet桶内数据单元的数据量在 100MB 到 1GB 之间比较理想。可以根据数据总量预估桶数。2. 索引与查询性能前缀索引Doris 会根据DUPLICATE/AGGREGATE/UNIQUE KEY中列的顺序自动构建前缀索引最多36字节。将高频查询条件列放在 Key 的前面能极大加速点查和范围查询。Bloom Filter 索引对于高基数列如user_id的等值查询过滤非常有效。可以在表属性中指定bloom_filter_columns。PROPERTIES ( bloom_filter_columns user_id,city );3. 物化视图Materialized View加速查询对于固定的聚合查询模式可以创建物化视图进行预计算。-- 为 aggregate_table 创建一个按城市统计总花费的物化视图 CREATE MATERIALIZED VIEW city_cost_mv AS SELECT city, SUM(total_cost) as sum_cost, COUNT(*) as cnt FROM aggregate_table GROUP BY city;创建后查询SELECT city, SUM(total_cost) FROM aggregate_table GROUP BY city;会自动路由到物化视图city_cost_mv上查询速度极快。4. 监控资源使用通过 Doris FE 的 Web UI (http://fe_host:8030) 可以查看集群负载、查询统计、磁盘使用情况。使用SHOW PROC /statistic;等命令查看系统状态。观察 BE 节点的内存、CPU、磁盘 I/O 使用率确保资源充足。8. 常见问题与排查方法在创建和使用 Doris 表的过程中你可能会遇到以下问题。问题现象可能原因排查方式解决方案建表失败报错Failed to create partition分区语法错误或分区值范围有重叠。检查PARTITION BY RANGE语句确保分区边界是递增且不重叠的。修正分区定义例如VALUES LESS THAN (2023-02-01)后接VALUES LESS THAN (2023-03-01)。数据导入失败状态为CANCELLED数据格式与表定义不匹配文件路径不可访问BE 节点磁盘满。使用SHOW LOAD WHERE LABELxxx\G查看详细的错误信息 (ErrorMsg)。根据错误信息修正 CSV 分隔符、列数或检查文件权限、磁盘空间。查询速度慢没有命中分区或分桶裁剪没有利用到前缀索引数据分布倾斜。使用EXPLAIN命令查看查询计划观察Partition和Bucket的过滤情况。优化查询条件使其包含分区键和前缀索引列检查数据分布考虑调整分桶列。UNIQUE KEY表更新后查询结果不一致可能处于Merge-on-Read模式查询时需要进行合并有一定延迟。检查表属性enable_unique_key_merge_on_write的值。对于点查性能要求高的场景建议在建表时设置enable_unique_key_merge_on_write true。ALTER TABLE添加列后查询新列报错unknown columnSchema Change 操作是异步的可能尚未完成。使用SHOW ALTER TABLE COLUMN查看 Schema Change 任务状态。等待任务状态变为FINISHED。BE 节点启动失败端口被占用存储路径权限不足配置文件错误。查看 BE 日志be.INFO或be.WARNING。根据日志提示释放端口9060/8040检查storage_root_path目录权限核对配置文件。内存不足OOM复杂查询、大聚合、高并发导致单个 BE 内存超限。监控 BE 节点内存使用查看查询日志中的内存峰值。优化查询减少单次处理数据量通过SET exec_mem_limit设置会话级内存限制升级硬件。9. 最佳实践与使用建议基于以上内容总结出 Doris 建表与使用的最佳实践表模型选择第一原则需要保留所有原始细节- 选Duplicate。需要实时预聚合- 选Aggregate。需要按主键更新- 选Unique并优先评估Merge-on-Write。分区与分桶设计分区按时间分区是最通用的做法便于管理数据生命周期DROP PARTITION。分桶选择高基数的、经常作为查询条件的列作为分桶列。桶数量建议是 BE 节点数量的整数倍利于数据均匀分布。单表数据量在百万级以下可以考虑 3-10个桶千万到亿级考虑10-30个桶十亿级以上需要更精细的计算。索引与性能将最常用的查询条件列放在KEY列定义的最前面以利用前缀索引。对高基数的等值过滤列如user_id,order_id创建 Bloom Filter 索引。针对固定且耗时的聚合查询创建物化视图。数据导入小批量数据用INSERT INTO ... VALUES。大批量数据GB级以上务必使用LOAD LABEL或Broker Load。定期合并小文件导入任务避免产生过多小数据版本。开发与运维为生产环境表设置合理的副本数通常为3保证高可用。监控磁盘空间设置数据过期策略TTL。使用EXPLAIN分析慢查询持续优化表结构和查询语句。在进行重大表结构变更如加减索引、修改分桶数前务必在测试环境充分验证。创建 Doris 数据表是一个结合业务需求和技术特性的综合设计过程。从最简单的明细表开始逐步应用分区、分桶、索引和物化视图等高级特性是掌握 Doris 的最佳路径。本文提供的建表示例、验证方法和问题排查清单应该能帮助你快速上手并规避常见陷阱。建议在实际项目中先从一个小型数据集开始完成从建表、导入到查询的全流程测试再逐步扩展到生产环境。
返回列表