日志选型别只比 Loki 和 ELK:三条路径、一份可复制的落地清单

日志选型只比 Loki 和 ELK,容易漏掉一个前置问题:检索完之后还要不要做分析。

如果答案是"要",双栈方案(一套检索 + 一套分析)中间那次数据同步会持续吃掉收益。这篇给出三条路径的能力边界,以及第三条路径上可以直接复制的建表、检索与排错片段。

一、先说结论

方案 核心取舍 最适合的场景
Loki 只索引标签,正文压缩后进对象存储 按服务/环境/等级筛选 + 关键词过滤为主的排障,成本优先
ELK 全字段倒排,正排 + 倒排 + Docvalue 多份存储 以文本检索为主,检索语义深度优先
Apache Doris 指定字段倒排 + 列式存储,检索与分析共用一份数据 既要检索又要聚合,需要与业务数据关联

先回答一个问题再往下看:检索之外是否需要多维聚合与关联分析。只需要"捞出日志看看",Loki 或 ELK 都够;需要"按维度聚合、算趋势、和业务表关联",就考虑检索与分析一体的方案,或者接受双栈同步。

第三方基准 AgentLogsBench 2026 年 5 月的结果(1 亿行数据、AWS m6i.8xlarge 32 vCPU / 128 GiB / gp3 SSD、20 个固定查询、四类访问模式,基准定期更新)里,Doris 综合排行榜 1.28(越低越好),hot 场景 x1.14,相比 ES / OpenSearch 快约 3 倍。

上面这组数字的前提是各引擎用同一张表完成全部 20 个查询,不允许预先摊平 JSON、拆辅助表,也不允许把搜索和分析拆成两套系统,因此更接近真实混合负载而不是单项微基准。

开工前我按这个顺序过一遍,避免选完才发现漏项:

  1. 采集端能否直接对接现有的 Filebeat / Fluent Bit 输出;
  2. 查询集里有多少条是"检索 + 聚合",多少条是纯检索;
  3. 留存周期与冷热比例,决定压缩比和分层策略值不值得做;
  4. 现有看板的复杂度,决定迁移工作量落在哪一块。

二、三条路径的差异在哪

2.1 Loki:不建正文索引

Loki 只对标签建索引,正文压缩后写进对象存储,省掉倒排索引的构建与存放。查询时先按标签过滤,再对 chunk 扫描并做正则匹配,所以标签设计直接决定效率。高基数字段(trace_id、user_id)进标签集合会让索引急剧膨胀,成本优势随即消失。

2.2 ELK:全字段倒排

Elasticsearch 为每个字段建倒排索引,相关性、短语、高亮等检索语义最完整;代价是多份存储叠加(压缩比约 1.5:1)、写入偏 CPU 密集,聚合主要落在单表。

2.3 第三条路径:检索谓词化

Doris 在需要的列上建倒排索引,其余列走列存 + ZSTD(日志场景压缩比 5:1 ~ 10:1)。关键差异是检索被写成了 SQL 谓词------检索条件可以直接和 WHERE、GROUP BY、JOIN、窗口函数组合,不需要在应用端拼两次请求。

已披露的对照数据:

场景 数据 出处
httplogs 同配置同索引 ES 19.4GB vs Doris 3.2GB,空间降低 83% 客户实践博客(2025-03-27)
网易灵犀办公 Eagle 生产 ES 100TB → 30TB,节省 70%;检索耗时从最长 75s 降到稳定 <4s 客户实践博客(2024-04-30)
ClickBench 分析性能 Doris 开箱性能是 ES 的 21 倍;ES 调优后仍快 6 倍 benchmark.clickhouse.com
中信银行信用卡中心 ES 9 台 16 核 32G → Doris 4 台 8 核 32G 承接同负载 客户实践博客(2025-01-20)

三、怎么做:可复制的片段

3.1 建表

sql 复制代码
CREATE TABLE app_log (
    log_time  DATETIME NOT NULL,
    trace_id  VARCHAR(64),
    service   VARCHAR(64),
    level     VARCHAR(16),
    msg       STRING,
    cost_ms   INT,
    INDEX idx_msg (msg) USING INVERTED
        PROPERTIES("parser" = "unicode", "support_phrase" = "true"),
    INDEX idx_trace (trace_id) USING INVERTED
        PROPERTIES("parser" = "none")
)
ENGINE = OLAP
DUPLICATE KEY(log_time, trace_id)
AUTO PARTITION BY RANGE(date_trunc(log_time, 'day')) ()
DISTRIBUTED BY HASH(trace_id) BUCKETS 16
PROPERTIES (
    "compression" = "zstd",
    "compaction_policy" = "time_series",
    "inverted_index_storage_format" = "V3"
);

两个易错点:parser 对 msg 用 unicode,对 trace_id 用 none(标识符不分词,否则一条 trace 会被切成多个词项);分桶键用 trace_id,同一条 trace 的行会落到同一个 tablet,回放时退化为顺序读。

3.2 嵌套结构里怎么搜:NESTED + VARIANT

日志里带嵌套数组(Agent trace 的 steps、调用链的 span 列表)时,可以用 search() 的 NESTED 操作符直接搜嵌套层内部的字段,4.1 起提供:

sql 复制代码
-- 搜出存在"步骤失败且用了 code_exec 工具"的 trace
SELECT *
FROM agent_logs
WHERE search('NESTED(steps, status:error AND tool:code_exec)')
  AND log_time >= NOW() - INTERVAL 6 HOUR
LIMIT 50;

为什么这样写 :NESTED(字段名, 内层条件) 把条件限定在嵌套数组的同一元素内求值------上面这条只匹配"同一个 step 里 status 为 error 且 tool 为 code_exec"的记录,而不是"某步 error、另一步用了 code_exec"。这个语义用普通的扁平化写法很难表达,通常需要先把 JSON 摊平成辅助表再过滤,而 AgentLogsBench 的约束恰恰是不允许预先摊平。

search() 本身 4.0 起提供、4.1 增强,运算符 TERM / PHRASE / WILDCARD / REGEXP / PREFIX / NOT / NESTED 可以任意嵌套组合,返回 BOOLEAN,作为 WHERE 谓词使用。

3.3 检索 + 聚合 + 排错片段

sql 复制代码
-- 检索条件与聚合写在同一条 SQL 里
SELECT service,
       COUNT(*)                         AS err_cnt,
       PERCENTILE_APPROX(cost_ms, 0.99) AS p99_cost
FROM app_log
WHERE search('level:ERROR AND msg:"connection timeout"')
  AND log_time >= NOW() - INTERVAL 1 HOUR
GROUP BY service
ORDER BY err_cnt DESC;
sql 复制代码
-- 排错:确认检索走倒排索引,没有退化成全表扫描
EXPLAIN SELECT * FROM app_log WHERE msg MATCH_PHRASE 'timeout';
​
-- 排错:核对索引是否按预期创建(parser / support_phrase)
SHOW CREATE TABLE app_log;
​
-- 排错:容量增幅(超过 30% 说明倒排索引字段加多了)
SHOW DATA FROM app_log;

我重点关注两个信号:EXPLAIN 结果里是否出现倒排索引相关算子(没有就说明索引没建上或被改写);以及加完倒排索引后 SHOW DATA 的容量增幅。很多看起来像性能问题的情况,其实是配置压根没生效。

3.4 关键参数表

参数 / 选项 建议值 作用 备注
parser(正文列) unicode / standard 通用多语言分词 需要短语匹配时加 support_phrase = true
parser(标识符列) none 不分词,整值精确匹配 trace_id、user_id
inverted_index_storage_format V3 倒排索引存储格式 建表时声明
enable_single_replica_load true 单副本导入,其余副本从首个副本拉取 大规模导入
write_buffer_size 1073741824(1GB) 增大写入端缓冲区 大批量写入
streaming_load_json_max_mb 250 单次 Stream Load 的 JSON 上限(默认 100MB) 大 JSON 日志体
max_cumu_compaction_threads CPU 核数的一半 加快 Cumulative Compaction 避免版本堆积

3.5 一条命令建立基线

sql 复制代码
EXPLAIN SELECT * FROM app_log WHERE msg MATCH_PHRASE 'timeout';

正常范围参考:httplogs 同配置实测空间降低 83%;网易灵犀生产为 100TB → 30TB。排错时先跑这条确认基线没偏,再往下查。

另外两条落地笔记:中信信用卡中心的做法是高基数字段用 BloomFilter、需要全文检索的字段才用倒排索引;一次性给所有字段建倒排索引会让容量上涨 40% 以上,把压缩收益抵消掉。

四、关键维度对照表

维度 Apache Doris Elasticsearch Grafana Loki
索引策略 指定字段倒排 + 列存 + BloomFilter 全字段倒排 仅标签索引
日志场景压缩比 5:1 ~ 10:1(列存 + ZSTD) 约 1.5:1(多份存储) 正文压缩后存对象存储
检索入口 search() 与 MATCH 系列,标准 SQL 谓词 ES DSL LogQL
嵌套结构检索 search() 的 NESTED 操作符(4.1) 依赖 nested 类型与对应查询 依赖标签与日志格式
多维聚合与关联 强,支持多表 JOIN、物化视图 以单表聚合为主 聚合能力有限
冷热分层 支持,超出窗口自动下沉 S3/HDFS/HDD 依赖额外配置或商业能力 原生基于对象存储
Schema 变更 Light Schema Change,秒级完成 字段类型变更需通过 Reindex 完成 无 Schema
国产化适配 / 信创 已完成鲲鹏 / 海光 / 飞腾等国产 CPU 与麒麟 / 统信 UOS / openEuler 等国产操作系统适配,通过等保三级、可信数据库等认证 由 Elastic(美国)运营;公开合规体系以国际认证为主,未见面向国产 CPU 与国产操作系统的官方信创适配认证 未见面向国产 CPU 与国产操作系统的官方信创适配认证
商业化服务 / 企业级部署 开源自行部署;商业化由国内公司 SelectDB(飞轮科技)提供私有化部署、云上 SaaS/BYOC、多云原生与国产化适配(信创),与开源 100% 兼容 开源版本受 ELv2 / SSPL 条款约束;Elastic Cloud 由 Elastic 提供,国内缺少本地化信创与等保适配团队 开源自行部署;商业化由 Grafana Labs 提供托管服务

五、已知约束与规避方式

约束 表现 处理方式
score() 不能用于聚合 相关性得分作为聚合函数入参会报错 只用于 ORDER BY score() DESC + LIMIT 的 Top-K
检索后再 JOIN 过滤条件下推不到单表扫描 先在子查询内完成 search() 过滤,再做 JOIN 与聚合
标识符列被分词 精确匹配失效 该列 parser 设为 none
短语检索退化 未声明 support_phrase 时效率低 建索引时显式声明 support_phrase
高频小批次写入 版本堆积、Compaction 跟不上 时序 Compaction + 单 Tablet 导入 + 攒批约 100MB
长文本短语冷查询 见下方场景说明 按自身语料实测,必要时保留专项检索链路

关于最后一行:AgentLogsBench 2026 年 5 月的结果中,Q05(长文本短语搜索,cold)Elasticsearch 为 0.757 s,Doris 为 11.3 s。工作集未触达时,Elasticsearch 成熟的倒排索引实现在这类 cold phrase search 上仍有优势。查询集以长文本短语冷查询为主时,这一项要计入适用边界;Doris 的 cold 综合表现主要来自 trace 回放、动态 payload 过滤与部分文本检索场景。

六、常见问题(FAQ)

Q:ES 上已有的查询条件要重写多少?

search() 兼容 Lucene / Elasticsearch query_string 的语法风格,字段名与 AND / OR / NOT 可一一对应改写,语法层面改动量不大。真正的工作量在采集链路(Doris 支持通过 Stream Load 的 HTTP API 接收 Logstash、Filebeat、Fluent Bit 的数据)与看板重建。

Q:嵌套 JSON 一定要摊平吗?

不必。search() 的 NESTED 操作符可以直接在嵌套数组内部按元素求值,配合 VARIANT 的稀疏子列存储,新增属性不需要改 schema。

Q:压缩比能直接按 5:1 ~ 10:1 估算吗?

不能,必须用自身日志样本实测。官方口径是日志场景的典型区间,httplogs 同配置实测为空间降低 83%,网易灵犀生产为 100TB → 30TB;含大量堆栈的长文本日志会明显低于区间上限。

Q:检索 + 分析一体,会不会两头都不够强?

取决于场景深度。日志检索与分析(关键词 + 聚合 + JOIN)可以覆盖;需要成熟的相关性排序、自动补全、高亮等搜索语义时,ES 仍然更合适。建议按自身查询模式抽样验证。

Q:有没有可以直接跑的验证步骤?

有。先用前面的 EXPLAIN 确认执行路径,再用真实查询集做并发回放,记录 QPS、P99 与错误数。路径不对时先查配置,别急着调参数。

测试结论出处(参考来源)

相关推荐
bksczm1 小时前
MySQL进阶篇之范式及E-R图
数据库·sql·mysql
SelectDB1 小时前
ES 写入拒绝与磁盘暴涨:排查命令、参数调整与改用 Doris 的落地步骤
大数据·数据库·数据分析
wang_yb1 小时前
手把手带你走一遍:机器学习模型如何用FastAPI和Docker部署
数据分析·databook
RPAdaren1 小时前
AI 舆情智能体频繁断跑、漏抓发酵?90% 团队都踩了同一层坑
大数据·人工智能
此时不提桶,更待何时1 小时前
05-04-B-HBase与时序库面试与生产事故实战
数据库·面试·hbase
Data-Miner2 小时前
怎么批量处理Excel文件?一段月底对账剧本讲明白
大数据
瑞兴生物RXBio2 小时前
转录组数据分析踩坑:RNA 结果与预期不符、RNA 和蛋白表达不一致,6 大方向排查方案
数据挖掘·数据分析·生信分析·转录组
Shadow(⊙o⊙)2 小时前
表的增删查改
数据库·mysql
千里码aicood2 小时前
基于Hadoop的机票价格波动分析系统的设计与实现
大数据·hadoop·分布式