SelectDB search() 实战教程:从 Elasticsearch 迁移到一条 SQL 搞定搜索与分析

还在维护 ES + ClickHouse 两套系统做日志搜索和分析?本教程带你从零开始,在 SelectDB(基于 Apache Doris)中用 search() 函数替代 ES 全文检索功能,实现搜索 + 分析同一条 SQL、同一份数据。含完整建表、索引配置、数据导入、15 种查询算子用法和 ES 迁移指南。

关键词:SelectDB · Apache Doris · search() · 全文检索 · Elasticsearch 迁移 · 倒排索引 · 日志分析 · 实战教程


前言:你的日志架构还能更简单吗?

当前主流日志架构:

复制代码
应用日志 → Kafka → Logstash → Elasticsearch(搜索)
                          └──→ ClickHouse(分析)

维护两套集群 + 一条同步链路,成本高、运维累。本教程的目标:用一套 SelectDB 集群替代这个双系统,搜索和分析用同一条 SQL 完成。


第 1 步:环境准备

组件 最低版本 作用
SelectDB 或 Apache Doris 2.1+(需支持 V3 倒排索引) 核心引擎
MySQL Client 或其他 SQL 客户端 任意 执行 SQL

确保 SelectDB 集群已启动并可通过 MySQL 协议连接(默认端口 9030)。


第 2 步:创建带倒排索引的日志表

sql 复制代码
-- 1. 创建数据库
CREATE DATABASE IF NOT EXISTS log_search;
​
-- 2. 创建日志表 + 倒排索引
CREATE TABLE IF NOT EXISTS log_search.inference_logs (
  log_time          DATETIME,           -- 日志时间
  request_id        VARCHAR(64),        -- 请求 ID
  model_name        VARCHAR(32),        -- 模型名称
   level             VARCHAR(16),        -- 日志级别
  error_msg         TEXT,               -- 错误信息(需全文检索)
  context           TEXT,               -- 上下文(需全文检索)
  prompt_tokens     INT,                -- prompt token 数
  completion_tokens INT,                -- 回复 token 数
  latency_ms        INT,                -- 延迟(毫秒)
   -- ===== 倒排索引定义 =====
   INDEX idx_level(level) USING INVERTED,
   INDEX idx_error(error_msg) USING INVERTED PROPERTIES(
       "parser" = "unicode",            -- 中英文混合分词
       "support_phrase" = "true"        -- 支持精确短语搜索
   ),
   INDEX idx_context(context) USING INVERTED PROPERTIES(
       "parser" = "unicode",
       "support_phrase" = "true"
   ),
   INDEX idx_model(model_name) USING INVERTED
) ENGINE = OLAP
DUPLICATE KEY(log_time)
DISTRIBUTED BY HASH(request_id) BUCKETS 16
PROPERTIES (
   "inverted_index_storage_format" = "V3",   -- V3 格式,压缩效率高
   "compression" = "ZSTD"
);

配置说明

  • USING INVERTED:为字段创建倒排索引,search() 函数依赖此索引加速检索
  • support_phrase = "true":如需搜索 "CUDA out of memory" 这样的精确短语,必须开启
  • parser = "unicode":中英文混合分词,不需要像 ES 那样额外安装 IK 分词器
  • V3 倒排格式:支持 ZSTD 字典压缩,索引体积比 ES 减少约 20%

重点 :SelectDB 的倒排索引加减不需要重写数据文件 ------可以先导入数据,再根据查询需求针对性添加索引,也可以随时删除冗余的索引释放空间。整个操作无需停服、无需重建表


第 3 步:导入测试数据

sql 复制代码
-- Stream Load 方式导入(示例)
-- 也可以通过 INSERT INTO SELECT 从其他表导入
​
INSERT INTO log_search.inference_logs VALUES
('2026-03-20 10:00:01', 'req_001', 'gpt-4', 'ERROR', 'CUDA out of memory at layer 12', 'model inference context...', 2048, 512,3200),
('2026-03-20 10:00:02', 'req_002', 'gpt-4', 'ERROR', 'connection refused to backend', 'routing context...', 512, 128, 500),
('2026-03-20 10:00:03', 'req_003', 'gpt-4o', 'ERROR', 'CUDA out of memory at layer 8', 'model inference context...', 4096, 1024,5800),
('2026-03-20 10:00:04', 'req_004', 'gpt-4o', 'WARN', 'high latency detected', 'monitoring context...', 1024, 256, 4500),
('2026-03-20 10:00:05', 'req_005', 'gpt-4', 'ERROR', 'timeout waiting for response', 'routing context...', 256, 64, 8000),
('2026-03-20 10:00:06', 'req_006', 'gpt-4o', 'ERROR', 'CUDA out of memory at layer 24', 'model inference context...', 8192, 2048,9200);

第 4 步:基础搜索 ------ 你的第一个 search() 查询

sql 复制代码
-- 搜索所有 GPU OOM 错误
SELECT request_id, model_name, error_msg, latency_ms
FROM log_search.inference_logs
WHERE search('level:ERROR AND error_msg:"CUDA out of memory"')
ORDER BY latency_ms DESC;

结果解读 :这条 SQL 在倒排索引中先定位包含 "CUDA out of memory" 短语 + level:ERROR 的行,再按延迟降序排列。语法和 ES query_string 几乎一致。


第 5 步:进阶查询 ------ 15 种算子实战

5.1 多条件组合定位故障

vbnet 复制代码
-- 5 种算子同时使用:TERM + PHRASE + RANGE + NOT + IN
SELECT *
FROM log_search.inference_logs
WHERE search('
level:ERROR 
AND error_msg:"out of" 
AND latency:[1000 TO *] 
AND NOT model_name:gpt-4o
AND request_id:IN(req_001 req_002)
');

5.2 正则匹配

sql 复制代码
-- 抓住所有 CUDA 相关错误,不管具体描述是什么
SELECT request_id, error_msg
FROM log_search.inference_logs
WHERE search('error_msg:/CUDA.*error/ AND level:ERROR');

5.3 BM25 相关性打分排序

sql 复制代码
-- 按搜索相关性排序,最匹配的排前面
SELECT request_id, error_msg, score() AS relevance_score
FROM log_search.inference_logs
WHERE search('error_msg:"memory allocation" OR error_msg:"CUDA error"')
ORDER BY relevance_score DESC
LIMIT 10;

score() 列暴露 BM25 评分(IDF 加权 + 文档长度归一化),配合存储层 TopN 优化,全量排序性能无忧。

5.4 搜索 + 聚合分析(融合模式)

sql 复制代码
-- 一条 SQL:搜索 + 统计分析,无需跨系统搬运数据
SELECT
  model_name,
   COUNT(*) AS error_count,
   AVG(prompt_tokens) AS avg_prompt_tokens,
   AVG(latency_ms) AS avg_latency
FROM log_search.inference_logs
WHERE search('level:ERROR AND error_msg:"out of"')
GROUP BY model_name
ORDER BY error_count DESC;

这一步是本教程的核心亮点:传统方案中,你需要在 ES 搜索 → 导出结果 → 在 OLAP 聚合。现在同一条 SQL 就能完成,延迟从分钟级降到秒级。

5.5 窗口函数:追踪错误趋势

sql 复制代码
-- 按小时统计错误数量,并计算环比变化
SELECT
  model_name,
  DATE_TRUNC('hour', log_time) AS hour,
   COUNT(*) AS error_count,
  LAG(COUNT(*)) OVER (PARTITION BY model_name ORDER BY DATE_TRUNC('hour', log_time)) AS prev_hour_errors
FROM log_search.inference_logs
WHERE search('level:ERROR')
GROUP BY model_name, DATE_TRUNC('hour', log_time)
ORDER BY hour;

第 6 步:从 Elasticsearch 迁移到 SelectDB

6.1 索引映射对照表

Elasticsearch SelectDB
"type": "text" TEXT + INDEX ... USING INVERTED
"type": "keyword" VARCHAR(32) + INDEX ... USING INVERTED
"type": "long" BIGINT
"type": "date" DATETIME

6.2 查询改写对照

sql 复制代码
-- === ES 查询 ===
GET /logs/_search
{
 "query": {
   "query_string": {
     "query": "level:ERROR AND error_msg:"timeout""
   }
 }
}
​
-- === SelectDB 查询 ===
SELECT * FROM log_search.inference_logs
WHERE search('level:ERROR AND error_msg:"timeout"');

90% 的查询只需要:REST API → SQL WHERE + 加个 search()

6.3 迁移收益

指标 双系统(ES + OLAP) SelectDB search()
集群数量 2 套 1 套
同步链路 Kafka → Logstash → ES 无(直写)
存储膨胀 ES 侧 2-3 倍 ZSTD 压缩
TB 级存储成本 基准 降 50%
查询延迟(搜+析) 分钟级(跨系统) 秒级(同引擎)

常见问题

Q:倒排索引对写入性能有影响吗? A:有一定开销,但在 DUPLICATE KEY 模型下日志场景以追加写为主,影响可控。V3 格式的压缩和索引构建性能已针对性优化。

Q:search() 和 ES query_string 语法有差异吗? A:query_string 模式下语法兼容,大部分查询可以直接移植。Lucene 模式支持 MUST/SHOULD/MUST_NOT 语义。

Q:能处理嵌套 JSON 日志吗? A:可以。配合 VARIANT 类型 + search() 的 NESTED 算子,可直接在数组内部检索,无需拆表。

Q:需要像 ES 一样提前规划索引 mapping 吗? A:不需要严格规划。先导入数据,后续可以随时添加或删除索引,无需停服、无需重建表


扩展阅读


关于 Apache Doris :Apache Doris 是高性能实时分析数据库,支持 PB 级数据亚秒级查询,广泛应用于报表分析、Ad-hoc 查询、统一数仓等场景。SelectDB 是 Apache Doris 的商业化公司,提供企业级支持和云服务。欢迎加入 Doris 社区 交流更多实践。

相关推荐
番茄炒鸡蛋加糖21 小时前
Spring 事务传播机制 & 事务失效场景
java·后端·spring
SelectDB21 小时前
Apache Doris / SelectDB 全栈实战教程:从 ClickBench 全球登顶到 AI Native 部署落地
后端
SelectDB21 小时前
Apache Doris HTAP 实战教程:PostgreSQL 实时分析从零搭建
后端
SelectDB21 小时前
SelectDB 实战教程:从部署到 AI 混合检索的完整实践
后端
qq_1715388521 小时前
Spring TransactionSynchronizationManager:事务同步的幕后指挥官
java·后端·spring
Oneslide21 小时前
ES 7.17 APM 致命坑:@timestamp 被识别为 text,彻底解释为什么必须升级 8.x
后端
SimonKing1 天前
Spring Boot 集成 OnlyOffice,5 分钟搞定 Word/Excel 在线编辑
java·后端·程序员
明月_清风1 天前
🌐 多链生态对比:EVM vs Solana vs Sui,开发者怎么选?
后端·web3
swipe1 天前
14|(前端转全栈)商品详情高频访问怎么扛?Redis Cache Aside 实战
前端·后端·面试