📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入
Easysearch 布尔查询子句重排序(四)|Block-Max、实战与验证

Block-Max WAND 块级剪枝、混合查询端到端追踪、Profile API 亲手验证

INFINI Easysearch 是一款专注于企业级场景的分布式近实时搜索与分析引擎。它以 Apache Lucene 为内核进行了增强,在保持与行业主流搜索协议及开发生态完全兼容的同时,重点强化了安全性、稳定性、压缩率及信创兼容性。


引言:从标准 WAND 到块级剪枝 #

前三篇我们走完了 Easysearch 布尔查询优化的前半程: 第一篇讲 rewrite 11 条规则, 第二篇讲合取的 cost 排序, 第三篇讲析取的 WAND 算法——用 maxScore 上界 + 三堆调度,把"上界够不到及格线的文档"在打分前就剪掉。

但标准 WAND 留了个明显短板:每个子句的上界是全局的——“这个词在全索引最多能打多少分”。游标走到低分文档区,上界仍按全局最高估,剪枝不够激进。本文就围绕这块补全,并把前面所有内容串起来做实战和验证:

  • 一 Block-Max WAND——把全局上界换成"按块分段"的上界,整块低分文档一次跳过
  • 二 实战——MUST + SHOULD 混合查询的端到端追踪,看前几篇内容怎么协作
  • 三 Profile API——用对比实验亲手验证 WAND 生效,避开常见误读
  • 四 开发者启示
  • 五 全系列总结

一、Block-Max WAND 的增强 #

1.1 一个类比:为什么全局上界会"过乐观" #

想象一场考试,每个学生最多能考 100 分。现在老师想知道"有没有人超过 90 分"。

  • 标准 WAND 的做法:每个学生头顶都贴着"100"(全局上限)。老师得把所有人都叫过来核对,因为光看标签谁都"可能"过 90。
  • 聪明的做法:把学生按班级分组,每个班只记一个"本班最高分"。如果某班最高才 60,整班直接跳过,不用一个个核对。

Block-Max WAND 就是这个"按班级分组"的做法。倒排链在物理存储上本来就是分块的——Lucene 把每 128 篇文档压缩成一个 block( ForUtil.BLOCK_SIZE = 128),写入时顺手记下"这个 block 内最高能打多少分"。这个分段级上界比全局 maxScore 紧得多——因为它只看本 block 的数据,不会被远处的高分文档带偏。

一句话区分:标准 WAND 的上界是"这个词在全索引最多能打多少分";Block-Max 的上界是"这个词在当前这个 block最多能打多少分"。后者永远 ≤ 前者,所以更容易触发剪枝。

1.2 分段上界 vs 全局上界:一张图看懂 #

                  标准 WAND                 Block-Max WAND

            ┌──────────────┐        ┌────────────────────────────────┐
   docID    │全局上界=9     │        │块0 doc 0-127   max=9  高分段    │
     ↑      │不管游标到哪    │        ├────────────────────────────────┤
            │上界都是=9     │        │块1 doc 128-255 max=5  中分段    │
            │              │        ├────────────────────────────────┤
            │              │        │块2 doc 256-383 max=2  低分段★   │
            └──────────────┘        └────────────────────────────────┘

   及格线 = 8,游标已进入 Block 2(低分段):

   标准 WAND:上界估 9(全局),9 ≥ 8 → 不剪,逐文档查
   Block-Max:上界估 2(本块),  2 < 8 → 跳过整个 block

两种策略的对比一目了然——同一个及格线 8、同一个 Block 2:标准 WAND 还用全局 max=9 估计,以为"可能过线"就逐文档查(保守);Block-Max 用本块 max=2 估计,一眼看出整块无望直接跳过(激进),一次比较换掉 128 次 advance

1.3 源码层面:三个动作怎么串起来 #

Block-Max 在标准 WAND 之外多调了两个底层方法,理解它们的名字就抓住了主线。这两个方法由每个子句的 Scorer 实现(如 TermWeight 内部的 ImpactsScorer),WANDScorer 通过自己的私有协调方法 WANDScorer.updateMaxScores() 把它们串进三堆调度:

  • advanceShallow(target) —— “浅推进”。只跳到 target 所在的 block 边界,不逐文档解码。开销远低于真正的 advance(target),相当于"瞄一眼那个班的最高分标签"。
  • getMaxScore(upTo) —— 返回"当前 block 内"的最高分上界。这是上面图里 max=2 那个数的来源,比全局 maxScore 紧得多。
  • updateMaxScores() —— 协调者:游标进入新 block 时,用上述两个方法重算每个子句的分段 maxScore,替换掉之前用的全局值,重新累加上界。发现 tail 上界已经够线,就把高分 essential 子句推进到 head 去实际查。

三者配合后, 第三篇 §3.7 那张状态图右侧的 tailMax 数值会逐 block 变小——因为用的是分段上界而不是全局上界,更容易跌破及格线。

1.4 最底层:ImpactsDISI 的块级跳过 #

分段信息从哪来?写入索引时就备好了。Lucene 的 Impacts 数据结构在 flush 阶段为每个 block 预计算"本块内各 (freq, norm) 组合对应的最高分",查询时由 MaxScoreCacheMaxScoreCache.java:72-78)读出来。

真正执行跳过的是 ImpactsDISI。它内嵌一个 minCompetitiveScore,每次游标要 advance(target) 时先做一道判断( ImpactsDISI.java:68-100):

upTo      = maxScoreCache.advanceShallow(target);   // 找到 target 所在 block 的末尾 docID
maxScore  = maxScoreCache.getMaxScoreForLevelZero(); // 本块分段上界
while (maxScore < minCompetitiveScore) {             // 本块最高分都够不到及格线
    target = maxScoreCache.getSkipUpTo(...) + 1;     // 直接跳到下一个可能有戏的 block
    upTo     = maxScoreCache.advanceShallow(target);
    maxScore = maxScoreCache.getMaxScoreForLevelZero();
}
in.advance(target);                                   // 只在"有戏"的 block 内才真正推进

效果:跳过的单位从"单个文档"升级到"整个 block(128 篇)"。一次 advanceShallow 比较,省掉最多 128 次 advance

名词对照advanceShallow / getMaxScore / Impacts / ImpactsDISI / MaxScoreCache 是源码里的正式名字;“分段上界"“块级跳过"“block"是本文用的通俗说法,指的是同一回事。

1.5 剪枝的反馈闭环:从"猜"到"越来越准” #

把第一章的几层串起来看,剪枝是一个自适应加速的闭环:

   Collector 收满 K 个结果
        │
        │  setMinCompetitiveScore(kthBestScore)
        ▼
   WANDScorer 收到及格线(抬高)
        │
        │  ① matches():用 lead+tail 的 maxScore 上界跳过低分候选
        │  ② updateMaxScores():用分段上界替换全局上界,上界变紧
        ▼
   ImpactsDISI 收到分段级 minCompetitiveScore
        │
        │  整个 block 最高分都 < 及格线 → 跳过 128 篇
        ▼
   迭代更快 → 更快碰到高分文档 → Collector 收到更高分
        │
        │  setMinCompetitiveScore(...) 再次抬高
        ▼
      (循环)及格线越抬越高,剪枝越来越激进

这个闭环的关键在于双向反馈:Collector 把及格线往下传给 WANDScorer(决定哪些文档跳过),WANDScorer 再往下传给 ImpactsDISI(决定哪些 block 跳过)。一开始及格线低、剪枝保守(还没见过高分文档,不敢贸然跳);随着高分结果不断收集,线越抬越高,剪枝越来越激进——这就是 §三里 set_min_competitive_score_count 持续增长的来源。


二、实战:MUST + SHOULD 混合查询的端到端追踪 #

结合前面几篇内容,用一个混合查询走完整路径:

GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        { "term": { "status": "published" } },
        { "term": { "category": "ai" } }
      ],
      "should": [
        { "term": { "author": "sam" } },
        { "term": { "tag": "featured" } }
      ],
      "minimum_should_match": 1
    }
  }
}

2.1 一张图看清 Scorer 嵌套结构 #

这个查询最终会被组装成一棵 Scorer 树。先看树的样子,再逐层解释:

                      BooleanScorer(顶层,协调 MUST 与 SHOULD 的关系)
                              │
              ┌───────────────┴────────────────┐
              │                                │
     MUST 侧(合取)                      SHOULD 侧(析取,size=10 → TOP_SCORES)
              │                                │
    ConjunctionScorer                     WANDScorer
   (按 cost 排序,最稀疏领头)          (按 maxScore 调度,剪枝省打分)
              │                                │
      ┌───────┴────────┐               ┌───────┴────────┐
      │                │               │                │
  category:ai    status:published   author:sam     tag:featured
  (cost≈1万)     (cost≈100万)        (maxScore 高)   (maxScore 低)
   ↑ lead1       ↑ lead2             └── tail 堆按 maxScore 排
   (最稀疏,领头跳)                  (高分优先推进查实)

这张树图把前面几篇内容串到了一起——每个 Scorer 的选型都有明确理由:

  • MUST 侧(合取):两个条件都要满足,用 ConjunctionScorer第二篇)。按 cost 升序排列,让 category:ai(只命中 1 万篇,最稀疏)当 lead1 领头跳,status:published(命中 100 万篇)当 lead2 跟进。lead1 跳得快,整个 MUST 侧就快
  • SHOULD 侧(析取):两个条件满足一个就行,且查询是 Top-10(size=10),走 WANDScorer第三篇)。两个 SHOULD 子句按 maxScore 进 tail 堆,高分优先推进。
  • 顶层 BooleanScorer:把 MUST 的命中文档交给 SHOULD 侧打分。MUST 过滤掉绝大部分文档后,WAND 只需对剩下的少数文档做上界判断,二者职责互补。

2.2 执行追踪:一篇文档怎么走过这棵树 #

假设 MUST 侧的 lead1(category:ai)跳到 doc=X,整个追踪如下:

① MUST 侧 ConjunctionScorer:
   lead1 (category:ai) advance 到 doc=X
   → lead2 (status:published) 确认 doc=X 也在 → MUST 命中 ✓

② 顶层 BooleanScorer 把 doc=X 交给 SHOULD 侧打分

③ SHOULD 侧 WANDScorer:
   把 author:sam、tag:featured 的游标推进到 doc=X
   → 上界判断(leadMax + tailMax vs 及格线)
   → 通过 → score() 算实际分

④ Collector 收集 doc=X 的分数,必要时抬高 minCompetitiveScore
   → 反馈回 WANDScorer 和 ImpactsDISI(第一章所说的反馈闭环)

2.3 几篇内容怎么协作 #

回看整个过程,几篇内容各管一段,缺一不可:

  • [第一篇] rewrite 保证了查询结构简洁(去重、提升、展平)——这一步决定 Scorer 树的形态
  • [第二篇] cost 排序 让 MUST 侧高效迭代(最稀疏的 category:ai 领头)——决定合取侧的跳过效率。
  • [第三篇] WAND 调度 让 SHOULD 侧高效剪枝(高分优先 + 动态上界)——决定析取侧的打分开销。
  • 本文 Block-Max 让 SHOULD 侧的上界更紧、剪枝更激进——决定析取侧的块级跳过力度。
  • 顶层合取 把两者组合:MUST 先把文档数砍到很小,WAND 再在这个小集合里挑 Top-K,各自发挥所长。

三、动手验证:Profile API 观察 WAND 生效 #

用对比实验验证 WAND 的反馈闭环:track_total_hits: false 切入 TOP_SCORES 模式(WAND 生效),track_total_hits: true 强制 COMPLETE 模式(WAND 剪枝关闭),对比 profile 的 breakdown

breakdown 字段含义 #

profile 中每个查询节点的 breakdown 是一个 Map。每个操作有两条记录:不带 _count 后缀的是纳秒耗时,带 _count 后缀的是调用次数。与 WAND/Block-Max 最相关的几个:

字段含义与 WAND/Block-Max 的关系
match / match_countTwoPhaseIterator matches() 验证WAND 的上界判断在此发生
score / score_countscore() 实际打分仅对通过 matches() 的命中调用
shallow_advance / shallow_advance_countadvanceShallow() 块级定位Block-Max 独有:块级跳过
compute_max_score / compute_max_score_countgetMaxScore() 计算分段上界Block-Max 独有
set_min_competitive_score / set_min_competitive_score_countCollector 回传最低分阈值WAND 反馈闭环的直接证据

构造一个能体现剪枝的数据集 #

WAND 的文档级剪枝要体现为 score_count 下降,需要”少量高分文档 + 海量低分文档“的分布:高分文档先把 Top-K 的及格线抬到高位,低分文档的上界够不到线,于是被整批跳过。为此建一个专门的索引 wand_msm

  • 100 篇 body = "rare common" —— 同时命中 rare(高 idf)和 common,分数 ≈ 5.30
  • 20000 篇 body = "common extra" —— 命中 common + extra,两个都是高频低 idf 词,分数 ≈ 0.01

为什么加 minimum_should_match: 2?这是触发 WANDScorer 的关键。Lucene 的 Boolean2ScorerSupplier.opt()minShouldMatch > 1 时返回 WANDScorer;而纯析取(无 minimum_should_match 或 ≤1)走的是另一条 MaxScoreBulkScorer 路径( BooleanWeight.java:224)。两者同属 Block-Max 动态剪枝家族,但要直接观察 WANDScorer + Block-Max 的剪枝,用 minimum_should_match: 2 最干净。

GET /wand_msm/_search
{
  "profile": true,
  "track_total_hits": false,
  "size": 10,
  "query": {
    "bool": {
      "should": [
        { "term": { "body": "rare" }},
        { "term": { "body": "common" }},
        { "term": { "body": "extra" }}
      ],
      "minimum_should_match": 2
    }
  }
}

真实 profile 输出(Easysearch 2.2.0 / Lucene 9.12.2 实测) #

############ track_total_hits = false(WAND 生效)############
BooleanQuery (body:rare body:common body:extra)~2  breakdown:
  next_doc_count                       101
  match_count                          100
  score_count                          100        ← 只给 100 篇高分候选打了分
  set_min_competitive_score_count        1        ← 反馈闭环生效!

  body:common (TermQuery)
  advance_count                        100        ← common 链只推进到高分文档区
  shallow_advance_count                  3        ← Block-Max 块级定位
  compute_max_score_count                3        ← Block-Max 分段上界计算
  body:extra (TermQuery)
  advance_count                          1        ← extra 子句几乎整链跳过!

############ track_total_hits = true(WAND 剪枝关闭)############
BooleanQuery breakdown:
  next_doc_count                     20101
  match_count                        20100
  score_count                        20100       ← 给全部 20100 篇命中文档都打了分
  set_min_competitive_score_count        0       ← COMPLETE 模式,从不回传阈值

  body:common  advance_count         20100
  body:extra   advance_count         20001
  (shallow_advance_count / compute_max_score_count 均为 0)

两组的 score_count 相差悬殊——false 模式 100、true 模式 20100,差了 200 倍。WAND 把 20000 篇低分的 common extra 文档在打分前就跳过了,只对真正可能进 Top-10 的 100 篇高分候选调用了 score()。两组返回的 Top-10 完全相同(全是 h0h9score=5.2984)——剪枝只省功,不改结果

怎么读这份输出 #

把两组数据并排看:

字段track_total_hits: false(WAND 生效)track_total_hits: true(WAND 关闭)解读
score_count10020100文档级剪枝的直接证据:WAND 跳过 99.5% 的低分文档,只对高分候选打分
set_min_competitive_score_count10反馈闭环:只有 false 模式下 Collector 才回传阈值
shallow_advance_count(common 子句)30Block-Max 铁证:只在 false 模式做块级 advanceShallow
compute_max_score_count(common 子句)30Block-Max 铁证:只在 false 模式算分段上界
advance_count(extra 子句)120001低分上界子句被 WAND 几乎整链跳过
next_doc_count10120101false 模式连外层迭代都提前结束了
hits.total省略{"value":20100,"relation":"eq"}false 模式不精确计数、允许早退

三条证据互相印证:

  • set_min_competitive_score_count 从 0 变 1:Collector 在收集到第 K 个高分结果后,把当前最低分回传给 WANDScorer(Scorer.setMinCompetitiveScore),这是 §一"剪枝反馈闭环"在 profile 里的落地。track_total_hits: trueTopScoreDocCollectorhitsThresholdChecker 是 no-op(isThresholdReached() 恒为 false),永不回传,所以为 0。
  • score_count 从 20100 暴跌到 100:20000 篇 common extra 文档的上界(≈0.01)够不到及格线(≈5.30),在 score() 之前就被跳过——这正是 WAND"用廉价的上界比较换掉昂贵的打分"的直接体现。
  • shallow_advance_count / compute_max_score_count 只在 false 模式非零:这正是 §一所讲 Block-Max 的 advanceShallow() / getMaxScore() 在底层被调用的痕迹。注意它们挂在 TermQuery 叶子节点上、而不是 BooleanQuery 顶层节点——后者这两个字段恒为 0。

⚠️ 另需注意:score_count 反映的是进入 collect() 的打分次数,只有在"高分文档先出现、低分文档上界够不到及格线"的分布下才会明显下降——若所有命中文档分数接近(例如每篇内容雷同),及格线抬不上去,score_count 就不会降。

对比实验:观察耗时差异 #

track_total_hits 改为 true,同样查询再次执行,对比 score 耗时(纳秒,单次运行波动较大,下为多次中位数):

track_total_hits=false:   score ≈   37,000 ns   score_count =   100
track_total_hits=true:    score ≈ 2,640,000 ns   score_count = 20100     (约 70 倍)

本例剪枝比例高达 99.5%,false 模式的 score 耗时约只有 true 模式的 1/70——因为它只对 1% 的文档真正打分。数据集越大、剪枝比例越高,WAND 的收益越显著。(profile 本身有额外开销、绝对数字仅供参考,关键看两种模式的相对差距。)

小结 #

判断 Block-Max WAND 是否生效,看 set_min_competitive_score_count 是否从 0 变非零(机制是否触发);评估收益大小,看 score_count 的下降幅度与 score 耗时的相对差距。


四、开发者启示:写查询时该注意什么? #

既然子句顺序在 Easysearch 2.x 上无需操心,那开发者应该关注什么?

✅ 用 filter 代替 must 当不需要评分时 #

filter 不参与评分,走 ConstantScoreQuery 路径更高效。同时,filter 子句不会增加 WANDScorer 的调度开销——它们被提升到 MUST 后走合取路径,与评分子句的 WAND 调度互不干扰。

✅ 让 Lucene 做 minShouldMatch 优化 #

当 should 数量恰好等于 minimumShouldMatch 时,所有 SHOULD 子句自动提升为 MUST( 第一篇规则 10),走 ConjunctionScorer 而非 WANDScorer。这意味着:你不需要手动把 should 改成 must 来"帮助"优化器——只要语义上等价,Lucene 会自动做正确的选择。

✅ 避免嵌套过深的布尔查询 #

展平 SHOULD 嵌套能让 WAND 看到更多子句( 第一篇规则 9)。嵌套结构下,内层 BooleanQuery 的子句对外层 WANDScorer 不可见,maxScore 上界估计不够紧,剪枝效果打折。手动展平或让 rewrite 自动展平,都能提升 WAND 效率。

✅ 理解 cost 的含义 #

cost ≈ 匹配文档数的估算,不是执行时间。一个高 cost 的 TermQuery 可能有极佳的缓存局部性(因为倒排列表是连续存储的),而一个低 cost 的 PointRangeQuery 可能需要更昂贵的验证逻辑。Profile API 的 advance 次数分布才是实际性能的真实反映。

❌ 不必刻意调整子句顺序(Easysearch 2.x) #

底层会自动按 cost(合取)或 maxScore(析取)排序。无论是先写高频词还是低频词,执行时的迭代顺序完全相同。唯一例外见 第二篇 §八的边界说明:Easysearch 1.x(Lucene 8.11)上 must/filter 混有多词查询时,仍应把稀疏 term 写在前面;Easysearch 2.x(Lucene 9.12)已随 Lucene 9.5 的修复免疫此问题。

🔧 Easysearch 的额外能力 #

在 Lucene 标准优化栈之外,EasySearch 还提供一个面向特定场景的增强能力:

fast_terms 插件:在高基数字段(如 user_id、tag_id 数万量级)上,用 RoaringBitmap 位图集合替代 N 个独立 TermQuery,将 N 次倒排索引查找压缩为 1 次 bitmap 交集。查询 DSL 名为 fast_terms,但其在 Profile 中对应的 type 是底层 Query 类的简单名 FilterQuerytype 取自 query.getClass().getSimpleName(),而插件实现类是 org.infinilabs.query.FilterQuery)。底层 FilterQueryConstantScoreWeight + 位图迭代器,advance 调用次数从 O(N·命中数) 降到 O(命中数)。

它走自己的 Scorer 体系、不参与 BooleanQuery 的 rewrite / cost 排序 / WAND 剪枝路径,可按需叠加。


五、全系列总结 #

四篇文章,从构建层到执行层,从合取到析取,我们完整走过了 EasySearch 布尔查询的优化全景:

  1. 构建层( 第一篇):11 条 rewrite 规则

Easysearch + Lucene 的构建层不做代价排序,但通过 11 条代数规则自动简化查询结构。其中对执行性能影响最大的两条——规则 7(SHOULD+FILTER→MUST 提升)规则 9(SHOULD 嵌套展平)——改变了子句的执行路径,为后续优化铺路。Profile API 可以直接观察 rewrite 后的查询形态(+ 前缀 = MUST 提升成功)。

  1. 执行层·合取( 第二篇):cost 排序 + leadCost 传播

ConjunctionDISI 按 cost 排序,让最稀疏的迭代器领头——它是跳过无效文档速度最快的那个。两阶段验证按 matchCost 排序,leadCost 实现从外向内的策略传播(如 IndexOrDocValuesQuery 的自适应切换)。Profile 的 advance 次数分布是最直接的佐证:lead1 的 advance 次数远大于 followers。

  1. 执行层·析取 I( 第三篇):WAND 动态调度

WANDScorer 按 maxScore 动态调度子句,高分优先推进——这是 Top-K 查询能早退的根本保障。三堆(head/lead/tail)分工合作,用大量廉价的上界比较换掉少量昂贵的精确打分。

  1. 执行层·析取 II(本文):Block-Max 块级剪枝

Block-Max WAND 在块级别进一步剪枝:用分段级 maxScore 替换全局 maxScore,整块低分文档一次跳过。shallow_advance 字段可验证其效果。剪枝的反馈闭环——Collector → WANDScorer → ImpactsDISI——实现自适应加速:越到后面,剪枝越激进。

给开发者的核心建议 #

  1. 无需关心子句书写顺序——底层自动优化。Easysearch 2.x(Lucene 9.12)确实如此;1.x 基于 Lucene 8.11,must/filter 混有 prefix/wildcard 等多词查询时,仍建议把稀疏的 term 子句写在前面(见 第二篇 §八的边界说明)
  2. 关注查询结构设计——用 filter 替代不需要评分的 must,展平嵌套 SHOULD
  3. 善用 Profile API——set_min_competitive_score_count(反馈闭环是否生效)、advance/shallow_advance 次数(跳过力度)、score 耗时(打分成本)是核心观测指标;注意不带 _count 后缀的是纳秒耗时,带 _count 的才是次数
  4. 理解 WAND 的触发条件——track_total_hits: false 切入 TOP_SCORES 开启剪枝(纯析取走 MaxScoreBulkScorerminimum_should_match > 1 才走 WANDScorer),track_total_hits: trueCOMPLETE 关闭剪枝;对比 set_min_competitive_score_count 是否从 0 变非零是判断剪枝是否生效最直接的方式,score_count 的下降幅度则量化了实际收益
标签
Easysearch x
布尔查询 x
BoolQuery x
排序 x
自主可控 x
超聚变 x
FusionOS x
信创 x
CocoAI x
Elasticsearch x
中国银行 x
搜索引擎 x
DTCC x
中国数据库技术大会 x
爱加密 x
安全 x
极限网关 x
PICC x
Gateway x
Coco AI x
信创产品评估证书 x
达梦数据库 x
CDC x
AI搜索 x
DBX x
客户端 x
可视化 x
数据库 x
达梦 x
兼容认证 x
产品更新 x
巡检 x
CCR x
语义搜索 x
向量检索 x
RAG x
knn x
2026 x
信通院 x
TDBC x
可信数据库大会 x
中国数据库产业图谱 x
ZSTD x
Bboss x
开源 x
国产化 x
Java 客户端 x
Console x
搜索平台 x
鲲鹏 x
统信UOS x
DBackup x
鼎甲数据 x
备份与恢复 x
Coco x
迁移 x
快照 x
snapshot x
向量 x
IK x
分词 x
performance x
插件 x
开发 x
自定义 x
扩展 x
AI x
幻觉 x
大模型 x
Agent x
Mem0 x
MCP x
AI Agent x
kNN x
规则引擎 x
银行 x
保险 x
风控 x
Rules x
Percolator x
国产 x
搜索 x
Lucene x
GraalVM x
JDK x
赞助 x
开源生态 x
社区 x
二等奖 x
兴智杯 x
人工智能 x
赛事 x
低空经济 x
商业化 x
数据分析 x
金猿奖 x
技术卓越奖 x
创新产品奖 x
IT168 x
APM x
Skywalking x
Easy-Es x
GitLab x
代码审核 x
石油石化 x
Gitee x
投票 x
Meilisearch x
Rust x
轻量级 x
搜索百科 x
Docker x
Docker Compose x
Easyserach x
DevOps x
国产替代 x
backup x
esdump x
source_reuse x
ignore_above x
OpenSearch x
AWS x
Solr x
Easyearch x
发明专利 x
数据分区 x
国际专利 x
一等奖 x
人工智能应用创新大赛 x
bulk x
embedding x
OpenAI x
2025 x
搜索型数据库 x
上海开源创新菁英荟 x
开源创新新星企业 x
Workshop x
AI 搜索 x
智能助手 x
Automation x
Logstash x
MongoDB x
开源中国 x
直播 x
merge x
Elasticsearch 9 x
GitCode x
Cloud x
rollup x
Kubernetes x
Operator x
Arm64 x
Snapshot x
S3 x
Grafana x
Opensearch x
Nginx x
直播活动 x
搜索客社区 x
Meetup x
ES x
企业搜索 x
DeepSeek x
certificate x
windows x
Rollup x
TopN x
Filebeat x
Ubuntu x
请求限速 x
INFINI Console x
指标 x
Kibana x
多集群 x
client x
Spring Boot x
ECE x
ES Bulk x
vector database x
Postgres x
可搜索快照 x
SDK x
官网 x
Web 开发 x
Next.js x
React x
Three.js x
Metrics x
Helm x
filter x
querycache x
practice x
localStorage x
响应式 x
时间组件 x
时区组件 x
极限科技 x
三周年 x
周年庆 x
国家高新技术企业 x
校园招聘 x
湖北工业大学 x
Tauri x
Web 开发人员 x
桌面应用开发 x
桌面端 x
Electron x
Pizza x
认证培训 x
报名 x
Scrapy x
爬虫 x
Rust开发者大会 x
docsearch x
文档搜索 x
Easyseach x
有奖征文 x
黑神话悟空 x
EKS x
征文系列 x
跨集群搜索 x
科技中小企业 x
白皮书 x
Python SDK x
数据库产业图谱 x
超大规模 x
分布式集群 x
写入限流 x
2024可信数据库发展大会 x
创新型中小企业 x
搜索数据库 x
正排索引 x
免费许可证 x
K8S x
DTC2024 x
实时搜索 x
ES国产化 x
Redis x
OOM x
测试 x
内存 x
趋势 x
AI绘画 x
Stable Diffusion x
Diffusion x
Model x
GAN x
知识图 x
向量数据库 x
中国信通院 x
星河(Galaxy) x
标杆案例 x
鲲鹏技术认证 x
日志平台 x
LDAP x
Loadgen x
中国一汽 x
国内数据库 x
墨天轮 x
监控系统 x
集成测试 x
Helm Charts x
国产适配 x
兆芯 x
Linux x
LoongArch x
信创适配 x
二维拆分算法 x
中国移动云 x
Vault x
加密 x
安全工具 x
图片搜索 x
Alerting x
SQL x
Embedding x
可信数据库 x
统信 x
海光 x
龙芯 x
restore x
Arm x
大数据企业证书 x
移动云大会 x
信通院产品评测 x
国内首家 x
数据可视化 x
北京软协 x
第十届理事会会员单位 x
Apache Arrow x
宣传片 x
大会分享 x
多集群管理 x
无缝数据迁移 x
Loadrun x
INFINI Gateway x
log4j x