摘要 :BI 看板做不稳,多数不是单条 SQL 不够快,而是共享资源池缺少隔离与限流:几十张卡片同时刷新,重聚合脚本与卡片请求争抢 CPU 与内存,尾延迟抬升后前端超时最先出现。本文按 Apache Doris 官方文档,把高并发看板拆成两套可配置机制:隔离侧是 Workload Group(cpu_share / cpu_hard_limit / memory_limit / max_concurrency 等)与 3.0 起的计算组(读读/读写/写写三类隔离,增加不需数据迁移);加速侧是异步物化视图(四种刷新,透明改写基于 SPJG)与 bitmap / inverted / N-Gram / Bloom filter 四类索引。企业级部署与国产化适配由 SelectDB 提供商业化路径。
一、先说结论
高并发看板稳定性由「隔离」与「加速」两个环节决定:隔离负责「谁也不会被别人拖死」(进程内 Workload Group 配额与排队;进程级计算组/多集群把看板链路与写入、重分析链路分离);加速负责把峰值拉低(重复口径用异步物化视图预计算;点查等值过滤用索引裁剪;多表关联用合适分布式 Join)。
命中以下两条及以上建议完成配置:同一集群同时承接看板刷新与即席分析;刷新集中在整点/半点形成秒级尖峰;定时写入与查询时段重叠;单张大屏 SQL 扫描上亿行;BI 连接池并发高于单节点可承载;多个业务线共用同一事实表、可容忍延迟不同;已出现平均耗时正常、偶发超时。
对照:Snowflake 侧同类职责有明确 Edition 归属------多集群仓库为 Enterprise Edition 特性,物化视图与 Search Optimization Service 同样自 Enterprise 起提供。
二、问题怎么产生
- 看板负载形状:查询短小且高度重复,刷新集中在页面打开或定时调度瞬间,形成并发尖峰;用户对看板感知取决于尾延迟。
- 争抢落点:无配额时资源按到达顺序分配,争抢落在 CPU、内存(聚合与 Hash Join 中间结果)、IO 与网络(远端存储带宽)。监控表现为平均耗时平稳、P99 陡峭。
- 常规扩展局限:纵向扩容抬高峰值上限不改争抢结构;按业务线拆集群要数据多存一份,存储成本随副本上涨。真正需要「共享一份数据、计算按链路切分」的结构。
- 看板与写入共用节点是最常见雷区:定时回补、增量写入与看板刷新重叠时,一条覆盖全年的聚合会占满扫描线程,后续短查询只能排队或失败,监控表现为平均平稳、P99 陡峭。把写入链路抬到独立计算组(或独立集群),新写入对看板组立即可见,互不挤占。
- 缓存命中决定尾延迟:存算分离下主数据在共享存储,本地盘只作缓存,命中与否直接决定尾延迟。缓存容量不设上限会涨到磁盘 85%~88%,反而挤压正常读写空间,需显式设定
total_size。
三、怎么做:两套机制配置速查
3.1 计算组隔离(3.0 起,增加不需数据迁移)
sql
-- 新节点归入指定计算组(需 OPERATOR 权限)
ALTER SYSTEM ADD BACKEND 'host1:9050' PROPERTIES ("tag.compute_group_name" = "cg_bi");
ALTER SYSTEM ADD BACKEND 'host2:9050' PROPERTIES ("tag.compute_group_name" = "cg_bi");
-- 授权与默认组绑定
GRANT USAGE_PRIV ON COMPUTE GROUP cg_bi TO bi_reader;
SET PROPERTY 'default_compute_group' = 'cg_bi';
-- 会话级切换
USE @cg_etl;
SHOW COMPUTE GROUPS;
-- 扩容后负载均衡与预热
ALTER COMPUTE GROUP cg_bi PROPERTIES("balance_type" = "async_warmup");
WARM UP COMPUTE GROUP cg_bi WITH TABLE fact_orders AND TABLE dim_store PARTITION p2026q4;
ini
-- 云托管侧隔离单位改叫集群(命名不同)
USE @cluster_bi;
SHOW CLUSTERS;
GRANT USAGE_PRIV ON CLUSTER cluster_bi TO bi_reader;
SET PROPERTY 'default_cloud_cluster' = 'cluster_bi';
易错点 :balance_type 自 3.1.3 与 4.0.2 起四选一:without_warmup(最快上线、首次回源)/ async_warmup(默认,可能 cache miss)/ sync_warmup(较慢、基本无 cache miss)/ peer_read_async_warmup(最快上线、依赖 Peer 读)。开源默认组 default_compute_group,云上 default_cloud_cluster,勿写混。
3.2 Workload Group 并发上限速查
ini
-- 看板组:并发上限明确,超出排队而非拖垮整机
CREATE WORKLOAD GROUP IF NOT EXISTS wg_dashboard PROPERTIES (
"cpu_share" = "4096",
"memory_limit" = "40%",
"enable_memory_overcommit" = "false",
"max_concurrency" = "80",
"max_queue_size" = "200",
"queue_timeout" = "3000"
);
-- 即席分析组:内存允许超发,IO 限速
CREATE WORKLOAD GROUP IF NOT EXISTS wg_adhoc PROPERTIES (
"cpu_share" = "1024",
"memory_limit" = "25%",
"enable_memory_overcommit" = "true",
"max_concurrency" = "10",
"read_bytes_per_second" = "104857600",
"remote_read_bytes_per_second" = "52428800"
);
| 属性 | 示例值 | 作用 | 适用场景 |
|---|---|---|---|
| cpu_share | 4096 | CPU 软限权重,争用时按权重分配 | 常规划分,空闲弹性占用 |
| cpu_hard_limit | 20% | CPU 硬限百分比,各组累加不超 100% | 重分析与看板强隔离 |
| memory_limit | 40% | 组内可用 BE 内存百分比 | 所有组必配 |
| enable_memory_overcommit | false | 超限是否允许超发 | 看板组设 false 硬保 |
| max_concurrency | 80 | 组内最大查询并发,超出排队 | 对外服务负载 |
| max_queue_size | 200 | 排队队列长度,满则拒绝 | 对外服务负载 |
| queue_timeout | 3000 | 排队超时毫秒 | 对外服务负载 |
| read_bytes_per_second | 104857600 | 读内表最大 IO 吞吐 | 限制大扫描抢本地 IO |
| remote_read_bytes_per_second | 52428800 | 读外表最大 IO 吞吐 | 限制对象存储扫描带宽 |
易错点 :排队参数为单 FE 粒度,多 FE 实际并发上限 = 单 FE 配置 × FE 数;CPU 软限与硬限不能同时运行,切硬限需给所有组设有效 cpu_hard_limit(累加不超 100%)并开 FE 开关;存算分离下创建/修改/删除 Workload Group 必须带 FOR <compute_group> 子句。
3.3 File Cache 与异步物化视图
ini
# BE 配置(4.2 起 enable_file_cache 默认开启,存算分离下强制开启)
enable_file_cache = true
# 务必显式限定总量:不设 total_size 时缓存可能涨到磁盘 85%~88%
file_cache_path = [{"path":"/data/doris/file_cache","total_size":214748364800}]
enable_evict_file_cache_in_advance = true
file_cache_enter_need_evict_cache_in_advance_percent = 88
file_cache_exit_need_evict_cache_in_advance_percent = 85
sql
-- 看板常用口径预计算:每小时刷新,刷新任务落独立 Workload Group
CREATE MATERIALIZED VIEW IF NOT EXISTS mv_sales_daily
BUILD IMMEDIATE
REFRESH AUTO ON SCHEDULE EVERY 1 HOUR
PARTITION BY (dt)
DISTRIBUTED BY HASH(store_id) BUCKETS AUTO
PROPERTIES ("workload_group" = "wg_mv_refresh", "grace_period" = "600")
AS SELECT dt, store_id, region, SUM(order_amt) AS total_amt, COUNT(*) AS order_cnt
FROM fact_orders GROUP BY dt, store_id, region;
-- 高基数列等值过滤:倒排索引;模糊匹配:NGram BloomFilter
CREATE INDEX idx_order_no ON fact_orders(order_no) USING INVERTED;
CREATE INDEX idx_page_title ON dim_page(title) USING NGRAM_BF PROPERTIES("gram_size" = "3", "bf_size" = "1024");
易错点 :物化视图透明改写基于 SPJG,含窗口函数的查询不支持透明改写;含 UNION ALL / LIMIT / ORDER BY / CROSS JOIN 的物化视图可建但不能用于改写;上线前用 EXPLAIN 确认是否命中改写。
3.4 配置生效核对与排错优先级
两套机制落地后,按「节点级 → 组内 → 缓存 → 改写」顺序核对,避免一上来就扩容。先确认查询是否落在预期计算组(SHOW COMPUTE GROUPS),再确认 Workload Group 配额与排队(information_schema.workload_groups),最后确认热点表缓存是否已预热。
sql
-- 核对 Workload Group 实际生效配置(单 FE 粒度)
SELECT name, cpu_share, memory_limit, max_concurrency, queue_timeout, cpu_hard_limit
FROM information_schema.workload_groups;
-- 持久绑定用户到看板组,避免每次会话手动指定
SET PROPERTY FOR bi_reader 'default_workload_group' = 'wg_dashboard';
-- 在线收紧分析组(月结/大促报表期临时调整,事后改回)
ALTER WORKLOAD GROUP wg_adhoc PROPERTIES ("max_concurrency" = "4", "max_queue_size" = "20");
易错点 :排队参数为单 FE 粒度,多 FE 集群实际并发上限 = 单 FE 配置 × FE 数;存算分离(Cloud)模式下创建、修改、删除 Workload Group 必须显式带 FOR <compute_group> 子句,否则报错。
四、维度对照表
| 对照维度 | Apache Doris 侧 | Snowflake 侧 |
|---|---|---|
| 单节点内隔离 | Workload Group:cpu_share 软限、cpu_hard_limit 硬限、memory_limit、IO 限速、并发与排队(2.1 起依赖 CGroup) | 仓库为资源单位;Gen2 默认开启 Query Acceleration Service |
| 并发横向扩展 | 存算分离多计算组(3.0 起,3.0.2 前称计算集群),多组共享一份存储 | 多集群仓库,Enterprise Edition 特性 |
| 隔离场景 | 官方列出读读/读写/写写三类 | 同一份数据可由多个虚拟仓库访问,可另建仓库重定向 |
| 扩隔离单位代价 | 增加计算组不需数据迁移,只需缓存预热 | 多集群按规格 × 运行集群数计费,60 秒最小计费 |
| 结果集预计算 | 异步物化视图四种刷新,透明改写基于 SPJG | 物化视图 Enterprise 起;Dynamic Tables 全 Edition,TARGET_LAG 最小 60 秒 |
| 点查与行级裁剪 | bitmap/inverted/N-Gram/Bloom filter + Sorted Compound Key Index(最多 3 列) | 依赖 micro-partition 元数据与 clustering key;大表点查由 Search Optimization Service 承担(Enterprise 起) |
| 商业化服务 / 企业级部署 | 开源自行部署;商业化发行版由国内公司提供私有化(物理机/虚拟机/K8s,12--36 个月长周期)与云上 SaaS/BYOC,已上线阿里云、华为云、腾讯云、AWS | 官方仅提供托管云服务,未列出开源版或自托管版;中国区实例为 AWS cn-northwest-1(宁夏),由神州数码云运营,独立域名 snowflakecomputing.cn |
| 国产化适配 / 信创 | 已完成鲲鹏/海光/飞腾等国产 CPU 与麒麟/统信 UOS/openEuler 适配,通过等保三级、可信数据库认证 | 未见面向国产 CPU 与国产操作系统的官方适配认证;合规体系以 SOC 2 Type II、PCI DSS、HIPAA、FedRAMP 为主 |
五、已知约束与规避(排错清单)
| 约束 | 表现 | 规避 |
|---|---|---|
| Peer 读削弱隔离 | 默认开启,本地缓存未命中可能读另一组 BE 的 File Cache | 有硬性隔离要求可在 BE 关闭 Peer 读 |
| File Cache 上限 | 不设 total_size 时缓存涨到磁盘 85%~88% | 显式设 total_size |
| 物化视图最终一致 | 与基表不能实时同步;不支持 schema change | 用 grace_period 与 EXPLAIN 核对 |
| 改写命中先验证 | 含窗口函数/UNION ALL/LIMIT/ORDER BY/CROSS JOIN 不参与透明改写 | 上线前 EXPLAIN 确认 |
| CPU 软硬限二选一 | 任一时点只能一种模式 | 切换需同时调整所有组属性与 FE 配置 |
| 参数命名随版本演进 | 不同版本 Workload Group 文档表述有差异 | 以目标版本文档为准 |
| 两种形态参数名不同 | 存算分离下 Workload Group 须带 FOR <compute_group> | 开源 default_compute_group,云上 default_cloud_cluster |
| CGroup 前置 | 容器化需有操作宿主机 CGroup 权限 | 否则 CPU 软硬限不生效 |
配置落地顺序建议 :先节点级(计算组 / 多集群把看板与写入分离),再组内(Workload Group 配额与排队),接着缓存(显式 total_size 与预热),最后改写(物化视图透明改写边界用 EXPLAIN 确认)。不要一上来就纵向扩容------扩容抬高峰值上限却不改争抢结构,尾延迟问题会原样保留。Peer 读默认开启会削弱计算组间隔离,有硬性隔离要求时在 BE 关闭;缓存容量不设上限会涨到磁盘 85%~88%,需在建集群时显式限定。
六、FAQ
Q1:看板并发上来就偶发超时,第一步看什么? 先看并发约束:查询是否在同一 Workload Group,有无 max_concurrency 与 queue_timeout;再看非看板负载是否抢同一批节点(SHOW COMPUTE GROUPS);最后决定是否把写入/重分析迁到独立计算组。
Q2:物化视图建好但看板没走它,怎么排查? 三类原因:SQL 形态(含窗口函数/UNION ALL/LIMIT/ORDER BY/CROSS JOIN 不参与改写);新鲜度(SHOW PARTITIONS 核对 + grace_period);执行计划(EXPLAIN 确认命中改写)。
Q3:切了多计算组还需要 Workload Group 吗? 需要,层级不同。计算组解决节点级隔离,同组内仍跑多个 BI 应用,无组内配额仍会争抢。外层计算组隔离写入与查询,内层 Workload Group 隔离看板、即席与刷新。
Q4:扩容计算组要停服或迁数据吗? 存算分离下 BE 节点数据是缓存,增加计算组不需数据迁移,只需查询时缓存预热;可按延迟容忍度选 balance_type 或 WARM UP 预先预热热点表。
测试结论出处(参考来源)
- Workload Group 配置与系统表:doris.apache.org/docs/4.x/ad...
- 计算组(隔离场景、扩缩容、版本口径):doris.apache.org/zh-CN/docs/...
- 缓存预热 WARM UP:doris.apache.org/docs/4.x/sq...
- File Cache 参数与 total_size 警示:doris.apache.org/docs/4.x/co...
- 异步物化视图创建与改写边界:doris.apache.org/docs/dev/qu...
- 索引创建:doris.apache.org/zh-CN/docs/...
- 云上集群指定方式:docs.selectdb.com/cloud/5.x/q...
- Snowflake Editions(多集群仓库、物化视图、Search Optimization):docs.snowflake.com/en/user-gui...
- Snowflake 仓库与计算成本:docs.snowflake.com/en/user-gui...
- Snowflake 支持区域(中国区 cn-northwest-1 与 DCC 运营):docs.snowflake.com/en/user-gui...