Doris 与 ClickHouse 在业务中的隐藏陷阱:那些官方文档没告诉你的细节

Doris 和 ClickHouse 聚合操作在业务不同阶段的对比与实践

在大数据分析领域,Doris 和 ClickHouse 都是非常受欢迎的 MPP 数据库,它们在聚合操作上的设计理念和实现方式各有特点。本文将详细探讨在业务发展的初期和中期,这两种数据库在聚合操作方面的差异以及实际应用场景中的实践经验,帮助大家更好地理解和选择适合的数据库。

业务初期:Doris 聚合便捷性优势显著

在业务刚刚起步的阶段,我们通常需要快速搭建数据模型,实现数据的聚合统计,以便及时为业务提供决策支持。此时,Doris 的聚合模型展现出了极大的便捷性。

创建聚合表

以一个常见的用户行为分析场景为例,我们需要根据用户 ID(user_id)和城市 ID(city_id)对用户的分数(score)进行聚合求和。在 Doris 中,我们可以通过以下步骤快速实现:

  1. 定义聚合模型表结构 :明确聚合键(Aggregate Key)并指定指标列的聚合函数。例如,假设需按 user_id 和 username 维度聚合统计年龄总和(SUM)及最新注册时间(MAX):
CREATE TABLE IF NOT EXISTS example_tbl_agg1 (
    `user_id` LARGEINT NOT NULL COMMENT "用户id",
    `username` VARCHAR(50) NOT NULL COMMENT "用户昵称",
    `city` VARCHAR(20) COMMENT "用户所在城市" REPLACE_IF_NOT_NULL,
    `age` SMALLINT SUM COMMENT "用户年龄总和",
    `sex` TINYINT REPLACE COMMENT "最新性别",
    `phone` LARGEINT REPLACE_IF_NOT_NULL COMMENT "最新电话",
    `address` VARCHAR(500) REPLACE_IF_NOT_NULL COMMENT "最新地址",
    `register_time` DATETIME MAX COMMENT "最新注册时间"
)
AGGREGATE KEY(`user_id`, `username`)
DISTRIBUTED BY HASH(`user_id`) BUCKETS 1
PROPERTIES (
    "replication_allocation" = "tag.location.default: 1"
);
  • AGGREGATE KEY :定义聚合维度列(user_id 和 username),相同键值的数据会自动聚合。
  • 聚合函数 :SUM 用于累加数值型指标(如 age),MAX/MIN 取最大 / 最小值(如 register_time),REPLACE 覆盖更新非聚合列(如 sex),REPLACE_IF_NOT_NULL 仅当新值非空时覆盖(如 city、phone)。
  1. 迁移并聚合数据 :通过 INSERT INTO … SELECT 语句将原表数据导入新表,并显式指定聚合逻辑:
INSERT INTO example_tbl_agg1
SELECT 
    user_id, 
    username,
    city,
    SUM(age) AS age,
    ANY_VALUE(sex) AS sex,  -- 若无需聚合,取任意值(需与 REPLACE 语义匹配)
    phone,
    address,
    MAX(register_time) AS register_time
FROM example_tbl_unique
GROUP BY user_id, username, city, phone, address;
 * **GROUP BY 子句** :需包含所有非聚合字段(如 city、phone、address),否则可能导致数据丢失或错误。
 * **高基数维度处理** :若存在高基数维度(如 address),建议在聚合模型中将其定义为 REPLACE_IF_NOT_NULL 或 REPLACE,避免存储膨胀。
  1. 验证数据一致性 :对比原表与新表的数据量及关键指标:
-- 原表数据量
SELECT COUNT(*) FROM example_tbl_unique;

-- 新表数据量(应 ≤ 原表,因聚合后相同键值合并)
SELECT COUNT(*) FROM example_tbl_agg1;

-- 验证年龄总和一致性
SELECT SUM(age) FROM example_tbl_unique;
SELECT SUM(age) FROM example_tbl_agg1;
  1. 性能调优建议

    • 分桶优化 :根据数据规模调整 BUCKETS 数量,避免数据倾斜。
    • 物化视图 :若需加速特定查询,可基于聚合表创建物化视图进一步预聚合。
    • 冷热分离 :通过 PARTITION 划分时间范围,将历史数据与实时数据分开存储。
  2. 注意事项
    如果 example_tbl_unique 插入操作一直在进行,那么在进行迁移并聚合数据 时可能会存在数据断层不全

通过以上步骤,Doris 能够快速实现数据的聚合统计,并且查询新表时无需显式调用聚合函数,Doris 会自动返回预聚合结果,大大简化了开发流程。

此时在插入数据层,Doris 需要同时对两个表(原始表和聚合表)进行插入操作,才能让新数据参与聚合。

ClickHouse 物化视图方案

相比之下,ClickHouse 在业务初期的聚合操作相对复杂,但也有其独特的优势。以相同的用户行为分析场景为例,ClickHouse 的实现步骤如下:

  1. 创建物化视图
-- 物化视图(聚合逻辑)
CREATE MATERIALIZED VIEW user_city_count
ENGINE = AggregatingMergeTree()
ORDER BY (user_id, city_id)
POPULATE
AS 
SELECT 
  user_id,
  city_id,
  sumState(score) AS score -- 中间状态存储
FROM user_city_record
GROUP BY user_id, city_id;

-- 查询视图
CREATE VIEW user_city_view AS 
SELECT 
  user_id AS id,
  city_id,
  sumMerge(score) AS score -- 最终聚合结果
FROM user_city_count
GROUP BY id, city_id;
 * **POPULATE 关键字** :如果创建物化视图时指定了 POPULATE 关键字,则在创建时将 SELECT 子句所指定的源表数据插入到物化视图中。但一般不推荐使用 POPULATE 关键字,因为在物化视图创建期间写入源表的数据将不会写入物化视图中。

此时,在插入数据层,ClickHouse 不需要修改插入逻辑,只需向原始表(user_city_record)插入数据,物化视图会自动根据预定义的聚合逻辑进行聚合。

业务中期:聚合操作的拓展与优化

随着业务的发展,数据量不断增长,查询需求也日益复杂。在业务中期,我们需要进一步拓展和优化聚合操作,以满足业务的多样化需求。

Doris 聚合表的拓展与优化

在业务中期,Doris 聚合表的拓展主要体现在以下几个方面:

  • 添加新的聚合指标 :如果需要添加新的聚合指标,可以通过修改表结构来实现。例如,添加一个新的指标列 “visit_count” 来统计用户的访问次数:
ALTER TABLE example_tbl_agg1 ADD COLUMN visit_count INT SUM DEFAULT "0";
  • 优化查询性能 :随着数据量的增长,查询性能可能会受到影响。可以通过创建物化视图来进一步预聚合数据,提高查询性能。例如,创建一个按天统计用户访问次数的物化视图:
CREATE MATERIALIZED VIEW daily_user_visit
AS SELECT 
    user_id,
    DATE_TRUNC('day', register_time) AS day,
    SUM(visit_count) AS visit_count
FROM example_tbl_agg1
GROUP BY user_id, day;
  • 处理数据更新 :在业务中期,可能会出现数据更新的需求。Doris 的 REPLACE 和 REPLACE_IF_NOT_NULL 聚合函数可以方便地实现数据的更新。例如,更新用户的地址信息:
INSERT INTO example_tbl_agg1
SELECT 
    user_id, 
    username,
    city,
    age,
    sex,
    phone,
    address,
    register_time
FROM (
    SELECT 
        user_id, 
        username,
        city,
        age,
        sex,
        phone,
        address,
        register_time,
        ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY update_time DESC) AS rn
    FROM example_tbl_unique
) t
WHERE rn = 1;

ClickHouse 物化视图的拓展与优化

在业务中期,ClickHouse 物化视图的拓展主要体现在以下几个方面:

  • 添加新的聚合指标 :如果需要添加新的聚合指标,可以通过修改物化视图的定义来实现。例如,添加一个新的指标列 “visit_count” 来统计用户的访问次数:
ALTER TABLE user_city_count ADD COLUMN visit_count SimpleAggregateFunction(sum, Int32);
  • 优化查询性能 :ClickHouse 通过分布式表和平行计算来提高查询性能。可以利用集群的分布式特性,将数据分片存储在不同的节点上,并在查询时进行并行计算。例如,创建一个分布式表来查询用户的访问次数:
CREATE TABLE distributed_user_city_count
(
    user_id String,
    city_id String,
    score AggregateFunction(sum, Float64),
    visit_count AggregateFunction(sum, Int32)
)
ENGINE = Distributed(test_cluster, default, user_city_count);
  • 处理数据更新 :ClickHouse 的 MergeTree 引擎支持数据的更新和删除操作。可以通过创建一个临时表来存储更新后的数据,然后将临时表的数据合并到原始表中。例如,更新用户的分数信息:
CREATE TEMPORARY TABLE tmp_user_city_record
(
    id UUID,
    user_id String,
    city_id String,
    score Float64,
    created_time DateTime
);

INSERT INTO tmp_user_city_record
VALUES (...);

ALTER TABLE user_city_record UPDATE score = tmp.score
FROM tmp_user_city_record tmp
WHERE user_city_record.id = tmp.id;

DROP TABLE tmp_user_city_record;

总结与建议

在业务初期,Doris 的聚合模型由于其便捷的创建和维护方式,以及实时聚合的特点,使得开发效率更高,更适合快速搭建数据模型和实时查询场景。而 ClickHouse 虽然在初期设置上相对复杂,但其强大的分布式处理能力和灵活的物化视图机制,使其在处理大规模数据时具有显著优势。

在业务中期,随着数据量的增长和查询需求的复杂化,Doris 和 ClickHouse 都可以通过拓展和优化来满足业务需求。Doris 在处理数据更新和添加新聚合指标方面具有一定的优势,而 ClickHouse 在分布式查询和复杂聚合逻辑方面表现更为出色。

选型建议

  • 选择 Doris :如果你的业务场景对实时性要求极高,需要快速搭建数据模型,并且希望开发和维护过程简单高效,同时数据量相对适中,那么 Doris 是一个很好的选择。例如,在实时监控、实时数据看板、交易报表统计等场景中,Doris 能够快速提供准确的聚合结果。
  • 选择 ClickHouse :如果你的业务数据量巨大,对查询性能要求极高,并且能够接受一定的数据延迟,同时需要灵活的自定义聚合逻辑和强大的分布式处理能力,那么 ClickHouse 更适合你的需求。例如,在大规模日志分析、用户行为分析、数据仓库等场景中,ClickHouse 能够高效地处理海量数据并提供快速的查询响应。

在实际应用中,我们也可以根据业务需求和数据特点,结合 Doris 和 ClickHouse 的优势,构建混合架构的数据分析平台,以实现更高效、更灵活的数据分析解决方案。希望本文的对比和实践经验分享能够为大家在选择和使用 Doris 和 ClickHouse 时提供有价值的参考。

以上就是我今天跟大家分享的 Doris 和 ClickHouse 聚合操作在业务不同阶段的对比与实践经验,如果你在使用这两种数据库的过程中遇到了具体问题,欢迎在评论区留言交流

如果你觉得这篇文章对你有所帮助,别忘了点赞、评论和转发哦,你的支持是我持续创作的动力!

你可能感兴趣的:(clickhouse,数据库,Doris)