[Doris/OLAP/数仓] Apache Doris : 实现标准SQL + 强多表关联 + 强实时更新 + 强一致性 + 支持高并发查询的开源、高性能OLAP与通用数仓

0 序

2022.06.16 从Apache基金会成功毕业

  • 2022年6月16日,Apache软件基金会宣布Apache Doris正式毕业,成为Apache顶级项目。

作为由国人主导的开源数据仓库项目,此次升级标志着百度长期支持开源的重要里程碑。
目前,Apache Doris已在互联网、金融、电商、教育、文娱等多个行业广泛应用,成长为业界主流的开源实时数仓之一。
Doris由百度自主研发并捐赠至Apache软件基金会,其前身为百度PALO。

1 概述: Apache Doris

产品介绍

  • Apache Doris 是一个开源的、高性能的、实时的分析型数据库(OLAP)。其核心目标是提供一个“开箱即用”、运维简单且性能卓越的统一分析平台。
  • 个人理解的定位:实现标准SQL + 强多表关联 + 强实时更新 + 强一致性 + 支持高并发查询的开源、高性能OLAP与通用数仓
  • 产品定位:专为在线分析处理(OLAP)场景设计,能够同时支持高并发的点查询、复杂的即席查询(Ad-hoc Query)、实时数据看板、日志检索分析以及湖仓一体(Lakehouse)查询等多种工作负载。

  • 诞生背景与原因:项目最初由百度于 2010 年左右内部研发,原名为 Palo。当时,百度面临传统 OLAP 系统(如基于 Hive + MapReduce)在实时性、查询延迟和系统复杂性方面的巨大挑战。内部迫切需要一个能同时满足低延迟、高吞吐、易用性和高可靠性的新一代分析引擎。

  • 解决的核心问题:

    • 打破传统 T+1 批处理模式,实现秒级甚至亚秒级的数据可见性和查询响应。
    • 简化 OLAP 架构,避免 Lambda/Kappa 架构的冗余和运维负担,提供一体化解决方案。
    • 提供标准 SQL 和 MySQL 协议兼容性,降低用户学习和集成成本。
    • 通过列式存储、向量化执行、智能索引等技术,在保证高性能的同时优化资源利用率和总体拥有成本(TCO)。
  • URLs:

发展历程

Apache Doris 的发展历程清晰地反映了其从企业内部工具到全球顶级开源项目的演进。

  • 2010–2017 年(百度内部阶段):作为百度内部 OLAP 引擎 Palo 开发和演进,支撑搜索、广告等核心业务。
  • 2017年:百度宣布将 Palo 开源。
  • 2018年:项目捐赠给 Apache 软件基金会(ASF),进入孵化器,并更名为 Apache Doris。
  • 2022年6月:Apache Doris 成功从孵化器毕业,成为 Apache 顶级项目(Top-Level Project, TLP),标志着其社区治理、代码质量和生态成熟度得到了 ASF 的官方认可。
  • 2023-2025年(功能爆发期):进入快速发展期,社区贡献者和企业用户数量激增。关键版本如 2.0 引入了主键模型(Unique Key Model)以支持高效的实时更新;3.0 增强了半结构化数据(JSON)处理能力。
  • 2025–2026年(AI 时代演进):4.0 版本是里程碑式的发布,正式引入了向量检索(Vector Search)和混合搜索(Hybrid Search)能力,将应用场景拓展至 AI 时代,同时完善了存算分离架构。

核心功能

Doris 的功能集使其成为一个真正意义上的“统一”分析数据库。

  • 多样化的数据模型:

    • Duplicate Key (明细模型):保留所有原始数据,适用于日志、事件流等场景。
    • Aggregate Key (聚合模型):在导入时自动聚合相同维度的数据,极大提升聚合查询性能。
    • Unique Key (主键模型):保证主键唯一性,支持高效的行级更新(Upsert)和删除(Delete),是构建实时数仓的核心。
  • 极速查询引擎:

    • MPP 架构:实现节点间和节点内的并行计算。
    • 全向量化执行引擎:显著提升 CPU 利用率和计算效率。
    • Cascades-style CBO (Cost-Based Optimizer):结合 RBO(Rule-Based)和 HBO(History-Based)生成最优执行计划。
    • Pipeline 执行引擎:解决线程爆炸问题,提高资源利用率。
  • 灵活的数据摄入:

    • 批量导入:支持从 HDFS、S3、本地文件等加载数据。
    • 流式导入:原生支持 Kafka,通过 Routine Load 实现自动、容错的数据消费。
    • 实时写入:通过 Stream Load (HTTP)、Broker Load、MySQL INSERT 语句等方式实现秒级数据可见。
  • 联邦查询(Unified Lakehouse):可直接查询外部数据湖(Hive, Iceberg, Hudi)和数据库(MySQL, Elasticsearch, JDBC 兼容库)中的数据,无需 ETL 移动,实现真正的湖仓一体。

  • 强大的半结构化与非结构化数据处理:

    • 原生 JSON 类型(VARIANT)支持动态 Schema、路径索引、稀疏列等高级特性。
    • 内置 倒排索引(Inverted Index) 和 N-Gram BloomFilter,为日志分析和全文检索提供强大支持。
  • AI 时代新能力(4.0+):支持十亿级规模的 向量相似性搜索(ANN),可与标量过滤结合进行混合搜索,为 RAG、推荐系统等 AI 应用提供数据底座。

主要特点

维度 特点
极致性能 在 SSB、TPC-H 等基准测试中,性能远超 ClickHouse、Druid 等同类产品,尤其在多表关联和实时更新场景。
简单易用 仅需 FE 和 BE 两类进程,无 ZooKeeper、HDFS 等外部依赖。兼容 MySQL 协议,任何 MySQL 客户端或 BI 工具(如 Tableau, Power BI)均可无缝接入。
高可用与弹性 FE 和 BE 均支持横向扩展。元数据和数据均采用多副本机制,自动故障转移和数据恢复。
统一架构 单一系统即可覆盖从实时报表、即席分析到数据湖加速、日志检索的全场景,避免了多套系统的维护成本。
开放生态 提供 Flink-Doris-Connector、Spark-Doris-Connector 等官方组件,深度融入大数据生态。

局限性

尽管功能强大,Apache Doris 仍存在一些局限性,需在选型时权衡。

  • 非事务型数据库:不支持 ACID 事务,不适合需要强一致性和复杂事务逻辑的 OLTP 场景。
  • 高频率随机更新的代价:虽然 Unique Key 模型支持更新,但频繁的、大范围的随机更新会带来较高的 Compaction 开销,影响整体性能。
  • 内存敏感:向量化引擎和复杂的查询对内存有较高要求,不当的资源配置可能导致 OOM。
  • 社区版高级功能:部分前沿功能(如某些向量索引算法、企业级安全特性)可能由商业公司率先实现,社区版跟进存在时间差。

适用场景

Apache Doris 的适用场景非常广泛,几乎涵盖了现代数据分析的所有主流需求。

  • 实时数据仓库:构建统一的、支持实时更新的企业级数据仓库。
  • 交互式 BI 与仪表盘:为业务人员提供秒级响应的自助分析和可视化看板。
  • 用户行为分析:分析用户点击流、留存、转化漏斗等。
  • 日志与事件分析:利用倒排索引快速检索和分析海量日志数据。
  • 湖仓查询加速:作为高性能查询引擎,直接加速对数据湖(Iceberg/Hudi)的查询。
  • AI/ML 应用数据平台:利用其向量检索能力,为大模型 RAG、个性化推荐等场景提供底层支持。

同类竞品

竞品 对比分析
ClickHouse CH 在纯追加写入和单表聚合查询上性能极佳,但 JOIN 能力弱、不支持高效更新、运维复杂。Doris 在功能完整性、易用性和更新场景上优势明显。
StarRocks StarRocks 与 Doris 同源(早期分叉),两者在核心架构和性能上非常接近。主要区别在于社区治理:Doris 是 Apache 顶级项目,社区更加开放中立;StarRocks 由商业公司主导,开源策略相对收紧。
Trino/Presto Trino 是优秀的联邦查询引擎,但本身无存储,依赖外部系统,查询延迟通常高于 Doris。Doris 自带高性能存储,更适合低延迟分析。
Snowflake/Redshift 这些是成熟的云数仓服务,功能全面但成本高昂且闭源。Doris 可私有化部署,为企业提供成本可控、自主可控的替代方案。

发展趋势

Apache Doris 的开源社区呈现高度活跃和健康的增长态势。

  • 社区活跃度:GitHub Stars 已突破 15k+,总贡献者超过 710+,月均活跃贡献者稳定在 120+。
  • 企业采纳:在中国,超过 80% 的 Top 50 互联网公司(如字节跳动、京东、美团、小米、腾讯等)已在生产环境中大规模使用 Doris。其影响力正迅速向全球扩展。
  • 技术演进:项目发展重心已从传统的 OLAP 引擎,转向 “AI 时代的实时分析与搜索数据库”。4.0 版本的向量搜索、存算分离、增强的 JSON 处理能力都是这一战略的体现。
  • 一句话总结:Apache Doris 凭借其卓越的性能、极致的易用性和前瞻性的技术布局(如向量搜索),已成为构建现代统一实时数据平台的首选开源方案之一,社区和生态正处于高速上升通道。

2 工作原理与架构

Apache Doris 采用经典的 Shared-Nothing MPP 架构,主要由两个核心组件构成:

doris-architecture

  • Frontend (FE):

    • 角色:集群的“大脑”。
    • 职责:
      • 元数据管理:存储和管理所有数据库、表、分区、副本等元数据。元数据在多个 FE 节点间通过 BDB JE (Berkeley DB Java Edition) 进行强同步,保证一致性。
      • SQL 解析与规划:接收客户端的 SQL 请求,进行词法/语法分析、逻辑计划生成,并通过 CBO/RBO 优化器生成最优的分布式物理执行计划。
      • 查询调度:将物理计划分发给 Backend 节点执行。
    • 高可用:FE 节点分为 Master、Follower 和 Observer。Master 负责元数据写入,Follower 参与选举,Observer 仅提供读服务以扩展查询并发。任意一个 Follower 可在 Master 故障时被选举为新的 Master。
  • Backend (BE):

    • 角色:集群的“肌肉”。
    • 职责:
      • 数据存储:负责实际数据的存储、读写。数据按表被水平切分为多个 Tablet,每个 Tablet 有多个副本,分散在不同的 BE 节点上。
      • 查询执行:接收 FE 下发的执行计划片段(Fragment),利用 向量化引擎 和 Pipeline 执行模型 进行本地计算,并与其他 BE 节点交换中间数据(如 Shuffle Join)。
      • 数据导入:处理来自各种渠道(Stream Load, Broker Load, Routine Load)的数据导入请求,并完成数据的排序、聚合和持久化。

关键技术亮点:

  • 列式存储:按列组织数据,极大提升压缩比和 I/O 效率,特别适合分析查询。
  • 智能索引:组合使用前缀索引、MinMax 索引、BloomFilter 索引和倒排索引,有效减少数据扫描量。
  • 物化视图:支持单表强一致的同步物化视图和多表异步刷新的物化视图,预计算加速查询。
  • 存算分离(4.x+):通过对接 S3/MinIO 等对象存储,将冷数据下沉,实现计算和存储资源的独立伸缩,降低成本。

3 使用指南

重要提示:Apache Doris 官方不支持在 Windows 上进行生产部署。开发和测试可以使用 Docker,生产环境强烈推荐在 Linux(如 CentOS 7+/Ubuntu 20.04+)上部署。

安装部署

方式一:Docker Compose(快速体验)

# 克隆官方仓库
git clone https://github.com/apache/doris.git
cd doris/docker-compose

# 启动集群(包含1个FE和1个BE)
docker-compose up -d

# 通过 MySQL 客户端连接
mysql -h 127.0.0.1 -P 9030 -u root

方式二:手动部署(生产推荐)

  1. 准备环境:

    • 操作系统:Linux (CentOS/Ubuntu)
    • 软件依赖:Java 8/11 (仅 FE 需要), Python 2/3
    • 硬件:至少 3 台机器(1 FE + 2 BE 以保证高可用)
  2. 下载与解压:

    # 从官网下载最新二进制包
    wget https://.../apache-doris-x.x.x-bin-x86.tar.gz
    tar -xzf apache-doris-x.x.x-bin-x86.tar.gz
    
  3. 配置与启动:

    • 配置 FE:编辑 fe/conf/fe.conf,设置 priority_networks 为本机 IP。
    • 启动 FE:
      ./fe/bin/start_fe.sh --daemon
      
    • 添加 BE:使用 MySQL 客户端连接 FE (默认端口 9030),执行:
      ALTER SYSTEM ADD BACKEND "be_host_1:9050";
      ALTER SYSTEM ADD BACKEND "be_host_2:9050";
      
    • 配置与启动 BE:在每台 BE 机器上,编辑 be/conf/be.conf,同样设置 priority_networks,然后启动:
      ./be/bin/start_be.sh --daemon
      

综合示例: 创建表模型 => 数据导入 => 数据查询

  • 创建表(Unique Key 模型示例):

    CREATE DATABASE test_db;
    USE test_db;
    
    CREATE TABLE orders (
        order_id BIGINT,
        user_id INT,
        product_name VARCHAR(128),
        price DECIMAL(12, 2),
        order_time DATETIME
    ) ENGINE=OLAP
    UNIQUE KEY(order_id)
    DISTRIBUTED BY HASH(order_id) BUCKETS 10
    PROPERTIES(
        "replication_num" = "3",
        "enable_unique_key_merge_on_write" = "true" -- 推荐开启,性能更好
    );
    
  • 数据导入(Stream Load):

    # 准备 CSV 文件 data.csv
    echo "1001,101,'Laptop',5999.00,2026-02-08 10:00:00" > data.csv
    
    # 通过 curl 导入
    curl --location-trusted -u root: \
        -H "label:load_order_001" \
        -H "column_separator:," \
        -T data.csv \
        http://fe_host:8030/api/test_db/orders/_stream_load
    
  • 查询(含 JSON 和向量):

-- 查询订单
SELECT * FROM orders WHERE user_id = 101;

-- (4.0+)假设有一个 product_embeddings 表,包含向量列
SELECT product_id, cosine_similarity(embedding, [0.1, 0.2, ..., 0.5]) AS score
FROM product_embeddings
ORDER BY score DESC
LIMIT 10;

数据库管理

创建数据库

create database bdp_xxx_dev;

表管理

支持的数据类型

1. TINYINT

1字节有符号整数,范围:[-128, 127]

2. SMALLINT

2字节有符号整数,范围:[-32768, 32767]

3. INT

4字节有符号整数,范围:[-2147483648, 2147483647]

4. BIGINT

8字节有符号整数,范围:[-9223372036854775808, 9223372036854775807]

5. LARGEINT

16字节有符号整数,范围:[-2^127 + 1 ~ 2^127 - 1]

6. FLOAT

4字节浮点数

7. DOUBLE

8字节浮点数

8. DECIMAL

格式:DECIMAL(M[,D])。默认为DECIMAL(9, 0)

16字节高精度定点数,M 代表一共有多少个有效数字(precision,范围1 ~ 27),D 代表小数位有多少个数字(scale,范围0 ~ 9)。所以整数位数字个数的范围是1 ~ 18

9. BOOLEAN

与TINYINT一样,0代表false,1代表true

10. CHAR

语法:CHAR(M)。默认是CHAR(1)
定长字符串,M代表的是定长字符串的长度。M的范围是1-255

11. VARCHAR(M)

变长字符串,M代表的是变长字符串的字节长度。M的范围是1-65533

变长字符串是以UTF-8编码存储的,因此英文字符占1个字节,中文字符占3个字节

12. STRING

变长字符串,最大支持2147483643字节(2GB-4)。String类型的长度还受BE配置参数 string_type_soft_limit的影响, 实际能存储的最大长度取两者最小值

String类型只能用在value列,不能用在key列和分区分桶列

变长字符串是以UTF-8编码存储的,因此英文字符占1个字节,中文字符占3个字节

13. DATE

DATE类型:3字节,取值范围是:[‘0000-01-01’, ‘9999-12-31’], 默认的打印形式是’YYYY-MM-DD’

DATE函数:语法是:DATE(expr),表示将输入的类型转化为DATE类型。例如:SELECT DATE('2022-08-01 10:02:03');

14. DATETIME

3字节,日期时间类型,取值范围是:[‘0000-01-01 00:00:00’, ‘9999-12-31 23:59:59’],打印的形式是’YYYY-MM-DD HH:MM:SS’

15. BITMAP

  • 整型的集合,元素最大支持到2^64 - 1。

  • BITMAP不能作为key列使用,建表时配合聚合类型为BITMAP_UNION。

  • 用户不需要指定长度和默认值。长度根据数据的聚合程度系统内控制

  • 并且BITMAP列只能通过配套的bitmap_union_count、bitmap_union、bitmap_hash等函数进行查询或使用

  • 离线场景下,使用BITMAP会影响导入速度,在数据量大的情况下查询速度会慢于HLL,并优于Count Distinct

  • 实时场景下,BITMAP如果不使用全局字典,使用了bitmap_hash()可能会导致有千分之一左右的误差

  • 查询示例:

select 
	hour
	, BITMAP_UNION_COUNT(pv) over(order by hour) uv 
from (
   select 
       hour, BITMAP_UNION(device_id) as pv
   from metric_table -- 查询每小时的累计UV
   where 1 = 1 
       and dateKey=20220801
   group by hour 
   order by 1
) final;

16. HLL(HyperLogLog)

  • 1~16385 个字节。HLL不能作为key列使用,建表时配合聚合类型为HLL_UNION。用户不需要指定长度和默认值。长度根据数据的聚合程度系统内控制

  • 并且HLL列只能通过配套的hll_union_agg、hll_raw_agg、hll_cardinality、hll_hash进行查询或使用

  • HLL是模糊去重,在数据量大的情况性能优于Count Distinct。

HLL的误差通常在1%左右,有时会达到2%

  • 查询示例:
select 
    hour, HLL_UNION_AGG(pv) over(order by hour) uv 
from (
   select 
       hour, HLL_RAW_AGG(device_id) as pv
   from metric_table -- 查询每小时的累计UV
   where datekey=20220801
group by hour order by 1
) final;

创建表

在Doris中,创建表是数据存储和管理的基础操作

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [database_name.]table_name
(
   column_name column_type [KEY | AGGREGATE_TYPE] [NOT NULL] [DEFAULT default_value] [COMMENT "comment"],
)
[ENGINE = olap] -- 
[KEY_TYPE KEY (key_columns)]
[PARTITION BY RANGE | LIST (partition_columns) (partition_definitions)]
[DISTRIBUTED BY HASH (distribute_columns) BUCKETS bucket_count]
[PROPERTIES ("key"="value", ...)];
  • 样例
drop table `bdp_xxx_dev`.`dwd_robot_basic_status_ri`;
create table IF NOT EXISTS `bdp_xxx_dev`.`dwd_robot_basic_status_ri` (
    `sn` VARCHAR(32) NULL COMMENT '设备编码',
	
	`xxx01` VARCHAR(255) NULL,
	`xxx02` VARCHAR(255) NULL,
	`xxx03` VARCHAR(255) NULL,
	
    `delete_flag` TINYINT NULL DEFAULT "0" COMMENT '删除标识:0未删除,1删除',
    `sign` TINYINT NULL DEFAULT "1" COMMENT '有效标识:-1业务端物理删除数据无效,1数据有效未删除(本DB识别收到的数据value是否有值并更新该字段)',
    `version` DATETIME(3) NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '版本号(数据写入DB时间戳)'
) 
ENGINE=olap
DUPLICATE KEY(sn)
PARTITION BY RANGE(sign) ()
DISTRIBUTED BY HASH(sn) BUCKETS 10

创建简单的表

CREATE TABLE IF NOT EXISTS user_info (
	user_id BIGINT NOT NULL COMMENT "用户ID",
	name VARCHAR(50) COMMENT "用户名",
	age INT COMMENT "年龄",
	city VARCHAR(20) COMMENT "城市",
	total_spent BIGINT SUM DEFAULT "0" COMMENT "总消费金额"
)
ENGINE=olap
AGGREGATE KEY(user_id, name, age, city)
DISTRIBUTED BY HASH(user_id) BUCKETS 10
PROPERTIES (
    "replication_num" = "1",
    "storage_medium" = "SSD"
);

创建带分区的表

创建一个按日期分区的订单表

CREATE TABLE IF NOT EXISTS orders (
	order_id BIGINT NOT NULL COMMENT "订单ID",
	user_id BIGINT NOT NULL COMMENT "用户ID",
	order_date DATE NOT NULL COMMENT "订单日期",
	amount BIGINT SUM DEFAULT "0" COMMENT "订单金额"
)
ENGINE=olap
AGGREGATE KEY(order_id, user_id, order_date)
PARTITION BY RANGE(order_date) (
	PARTITION p202301 VALUES LESS THAN ("2023-02-01"),
	PARTITION p202302 VALUES LESS THAN ("2023-03-01")
)
DISTRIBUTED BY HASH(order_id) BUCKETS 5
PROPERTIES (
	"replication_num" = "2",
	"storage_medium" = "HDD"
);

创建动态分区的表

动态分区用于自动管理分区,例如每天新增或删除分区:

CREATE TABLE IF NOT EXISTS dynamic_partition_table (
	id INT,
	event_date DATE NOT NULL,
	event_name VARCHAR(50)
)
DUPLICATE KEY(id, event_date)
PARTITION BY RANGE(event_date) ()
DISTRIBUTED BY HASH(id) BUCKETS 10
PROPERTIES (
	"dynamic_partition.enable" = "true",
	"dynamic_partition.time_unit" = "DAY",
	"dynamic_partition.start" = "-7",
	"dynamic_partition.end" = "3",
	"dynamic_partition.prefix" = "p",
	"replication_num" = "1"
);

注意事项

  • 数据模型选择:根据业务需求选择 AGGREGATE、UNIQUE 或 DUPLICATE 模型。
  • 分区与分桶:合理设置分区和分桶以优化查询性能。
  • 副本数:建议设置为奇数以提高容错能力。
  • 动态分区:适用于需要频繁新增或删除分区的场景。

修改表

表的重命名

  • Demo
alter table test_db.old_table_name rename new_table_name
  • 推荐文献

表字段的重命名

ALTER TABLE [{dbName}.]{tableName} RENAME COLUMN `oldColumnName` `newColumnName`;

表字段的删除

ALTER TABLE 表名 DROP COLUMN 字段名;

查看表

查看建表语句/查看目标表的DDL

show create table bdp_dim.dim_common_device_ri_d;

/**
CREATE TABLE `dim_common_device_ri_d` (
  `device_id` VARCHAR(32) NULL COMMENT '设备号',
  `id` BIGINT NULL COMMENT 'id',
  `sys_code` VARCHAR(32) NULL DEFAULT "XXXX" COMMENT '租户',
  `uuid` VARCHAR(64) NULL COMMENT 'uuid',
  `device_bind_device_time` BIGINT NULL COMMENT '设备绑定时间',
  `device_create_time` BIGINT NULL COMMENT '设备创建时间',
  -- `device_id` BIGINT NULL COMMENT '设备id',
  `device_manufacturing_date` BIGINT NULL COMMENT '设备制造日期',
  `device_sn` VARCHAR(32) NULL COMMENT '设备sn',
  `device_type` VARCHAR(8) NULL COMMENT '设备类型:TBOX,...,GATEWAY',
  `device_update_time` BIGINT NULL COMMENT '设备更新时间',
  `imei` VARCHAR(32) NULL COMMENT 'imei',
  `pdid` VARCHAR(48) NULL COMMENT 'pdid',

  `device_bind_status` VARCHAR(16) NULL COMMENT '设备绑定状态',
  `device_brand_alias` VARCHAR(64) NULL COMMENT '品牌别名',
  `device_brand_code` VARCHAR(16) NULL COMMENT '品牌编码',
  `device_brand_id` BIGINT NULL COMMENT '品牌id',
  `device_brand_name` VARCHAR(128) NULL COMMENT '品牌名称',
  `device_brand_uuid` VARCHAR(64) NULL COMMENT '品牌uuid',

  `device_data_source` VARCHAR(16) NULL COMMENT '设备数据来源:SYSTEM,MANUAL',

  `device_id` BIGINT NULL COMMENT '设备id',
  `device_uuid` VARCHAR(64) NULL COMMENT '设备uuid',
  `device_interior_color_code` VARCHAR(16) NULL COMMENT '设备内饰颜色编码',
  `device_inventory_status` VARCHAR(16) NULL COMMENT '设备库存状态:TEST,INVENTORY',
  `device_manufacturing_date` BIGINT NULL COMMENT '设备制造日期',

  `device_model_alias` VARCHAR(128) NULL COMMENT '设备型别名',
  `device_model_code` VARCHAR(32) NULL COMMENT '设备型编码',
  `device_model_id` BIGINT NULL COMMENT '设备型id',
  `device_model_name` VARCHAR(128) NULL COMMENT '设备型名',
  `device_model_uuid` VARCHAR(64) NULL COMMENT '设备型uuid',

  `device_optional_pack_code` VARCHAR(32) NULL COMMENT '设备选装包编码',
  `device_order_number` VARCHAR(32) NULL COMMENT '设备订单号',
  `device_plate_number` VARCHAR(32) NULL COMMENT '设备牌号',

  `device_project_alias` VARCHAR(128) NULL COMMENT '设备系别名',
  `device_project_code` VARCHAR(32) NULL COMMENT '设备系编码',
  `device_project_id` BIGINT NULL COMMENT '设备系id',
  `device_project_name` VARCHAR(128) NULL COMMENT '设备系名',
  `device_project_uuid` VARCHAR(64) NULL COMMENT '设备系uuid',

  `device_sale_status` VARCHAR(16) NULL COMMENT '设备销售状态:STOCK_IN,STOCK_OUT,SALE',
  `device_type` VARCHAR(16) NULL COMMENT '设备类型:NORMAL,TEST,BETA,EXHIBITION',

  `module_id` VARCHAR(32) NULL COMMENT '子系统moduleId',

  `create_by` VARCHAR(64) NULL COMMENT '创建人',
  `create_time` BIGINT NULL COMMENT '创建时间',
  `update_by` VARCHAR(64) NULL COMMENT '更新人',
  `update_time` BIGINT NULL COMMENT '更新时间',
  `delete_flag` TINYINT NULL DEFAULT "0" COMMENT '删除标识:0未删除,1删除',
  `sign` TINYINT NULL DEFAULT "1" COMMENT '有效标识:-1业务端物理删除数据无效,1数据有效未删除(OLAP识别收到的数据value是否有值并更新该字段)',
  `version` DATETIME(3) NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '版本号(CH写入数据的时间戳)'
) ENGINE=OLAP
UNIQUE KEY(`din`)
COMMENT 'OLAP'
DISTRIBUTED BY HASH(`din`) BUCKETS 1
PROPERTIES (
	"replication_allocation" = "tag.location.default: 3",
	"min_load_replica_num" = "-1",
	"is_being_synced" = "false",
	"storage_medium" = "hdd",
	"storage_format" = "V2",
	"inverted_index_storage_format" = "V1",
	"enable_unique_key_merge_on_write" = "true",
	"light_schema_change" = "true",
	"disable_auto_compaction" = "false",
	"enable_single_replica_compaction" = "false",
	"group_commit_interval_ms" = "10000",
	"group_commit_data_bytes" = "134217728"
);
**/

表数据管理

删除表数据

-- select * from test.tb_xxxx where device = 'xxxxxx';
DELETE FROM test.tb_xxxx WHERE device = 'xxxxx';

修改表数据

UPDATE test.ods_xxx_device_data_analysis
SET biz_type = 'device-signals'
WHERE k1 = 1;

-- 注: 不支持修改 unique 模型表的主键列,否则报错: [HY000]: errCode = 2, detailMessage = Only unique table could be updated.

插入表数据

  • INSERT 语法
INSERT INTO table_name
[ PARTITION (p1, ...) ]
[ WITH LABEL label]
[ (column [, ...]) ]
{ VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query }
  • tablet_name: 导入数据的目的表。可以是 db_name.table_name 形式。
  • partitions: 指定待导入的分区,必须是 table_name 中存在的分区,多个分区名称用逗号分隔。
  • label: 为 Insert 任务指定一个 label。
  • column_name: 指定的目的列,必须是 table_name 中存在的列。
  • expression: 需要赋值给某个列的对应表达式。
  • DEFAULT: 让对应列使用默认值。
  • query: 一个普通查询,查询的结果会写入到目标中。
  • Insert Into 命令

需要通过 MySQL 协议提交,创建导入请求会同步返回导入结果,主要的Insert Into 命令包含以下两种:

  • INSERT INTO tbl SELECT ...
  • INSERT INTO tbl (col1, col2, ...) VALUES (1, 2, ...), (1,3, ...);
  • INSERT INTO SELECT 方式
INSERT INTO test.ods_xxx_device_data_analysis2(
    device_id, biz_type, `data`,data_version ,`time`
)
select 
	device_id, 'device-signals' as biz_type, NULL as `data`, data_version ,`time`
from test.ods_xxx_device_data_analysis;

Z FAQ for Doris

Q: 修改字段的值(update table set xxx=xxx)失败,报: [HY000]: errCode = 2, detailMessage = Only unique table could be updated.

  • 问题描述

修改字段的值(update table set xxx=xxx)失败,报

[HY000]: errCode = 2, detailMessage = Only unique table could be updated.
  • 原因分析

该错误通常出现在使用 Apache Doris 数据库时,尝试更新非唯一键表或不符合更新规则的列。Doris 的 UNIQUE KEY 模型仅允许更新值列,而主键列或非值列无法直接更新。

在 UNIQUE KEY 表中,仅允许更新非主键的值列。若需更新主键,需通过删除旧数据并插入新数据实现。

Q: Doris通过阿里云OSS导出导入?

https://blog.csdn.net/m0_73193173/article/details/130827159

Q: Doris 支持 UPDATE / DELETE 吗?

A: 支持,但仅限 Unique Key 模型(主键模型)。它通过指定主键进行行级覆盖(Upsert)或删除,不支持带有 WHERE 条件的通用批量更新或删除。

Q: 能否用 Doris 替代 MySQL?

A: 不能。Doris 是分析型数据库(OLAP),不适合高频点写、事务处理、复杂关联更新等在线事务处理(OLTP)场景。MySQL 是优秀的 OLTP 数据库,两者定位完全不同。

Q: 如何监控 Doris 集群健康状态?

A: 可通过多种方式监控:

  • FE Web UI:访问 http://<fe_host>:8030,可查看节点状态、Tablet 健康度、慢查询等。
  • Prometheus + Grafana:Doris 提供了 Prometheus Exporter,可集成 Grafana 监控 Query QPS、延迟、CPU/Mem/Disk 使用率等核心指标。
  • 日志:分析 FE/BE 的日志文件,排查错误和性能瓶颈。

Q: 是否支持向量搜索?

A: 是的,从 4.0 版本开始支持。Doris 内置了 IVF_PQ、HNSW 等向量索引算法,可处理十亿级向量,并支持与标量条件(如关键词、数值范围)结合进行混合搜索,非常适合 RAG、推荐系统等 AI 应用。

Q: 社区版和商业托管版(如 SelectDB Cloud)有何区别?

A: 核心引擎一致,社区版功能完整。商业托管版通常在社区版基础上,提供全托管服务(免运维)、SLA 保障、企业级安全(如 RBAC、审计日志)、更高级的监控告警、专业的技术支持以及一些尚未完全开源的前沿特性(如特定的向量索引优化)。

Y 推荐文献

X 参考文献

posted @ 2026-02-08 12:41  千千寰宇  阅读(4)  评论(0)    收藏  举报