<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>Longda Feng</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <icon>https://ilongda.com/img/my.jpg</icon>
  <id>https://ilongda.com/</id>
  <link href="https://ilongda.com/" rel="alternate"/>
  <link href="https://ilongda.com/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, Longda Feng</rights>
  <subtitle>分布式数据库与 AI Agent 工程实践</subtitle>
  <title>Longda's Interesting World</title>
  <updated>2026-07-06T02:01:03.000Z</updated>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="技术详解" scheme="https://ilongda.com/categories/%E6%8A%80%E6%9C%AF%E8%AF%A6%E8%A7%A3/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="AI Agent" scheme="https://ilongda.com/tags/AI-Agent/"/>
    <category term="seekdb" scheme="https://ilongda.com/tags/seekdb/"/>
    <category term="PowerMem" scheme="https://ilongda.com/tags/PowerMem/"/>
    <category term="数据底座" scheme="https://ilongda.com/tags/%E6%95%B0%E6%8D%AE%E5%BA%95%E5%BA%A7/"/>
    <category term="AI 数据库" scheme="https://ilongda.com/tags/AI-%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    <category term="Lakebase" scheme="https://ilongda.com/tags/Lakebase/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"AI Agent 要用数据库了：Lakebase、seekdb 与 PowerMem 怎么理解","description":"从 Lakebase 与 AI 数据库谈起：Agent 需要怎样的数据底座？梳理 OceanBase Lakebase、seekdb、PowerMem 等 Agent 友好能力与演进方向。","image":"https://ilongda.com/img/2026-07-06-ai-agent-database-evolution/18.png","wordCount":5510,"datePublished":"2026-07-06T02:01:03.000Z","dateModified":"2026-07-06T02:01:03.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-07-06-ai-agent-database-evolution/"},"url":"https://ilongda.com/2026/2026-07-06-ai-agent-database-evolution/","inLanguage":"zh-CN","keywords":["OceanBase","AI Agent","seekdb","PowerMem","数据底座","AI 数据库","Lakebase"],"articleSection":["技术详解"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"技术详解","item":"https://ilongda.com/categories/技术详解/"},{"@type":"ListItem","position":3,"name":"AI Agent 要用数据库了：Lakebase、seekdb 与 PowerMem 怎么理解","item":"https://ilongda.com/2026/2026-07-06-ai-agent-database-evolution/"}]}</script><p>AI Agent 开始真正“用”数据库之后，库本身也要变：既要扛事务与一致性，又要管向量、全文和长期记忆，还得让开发者别被一堆组件拼到怀疑人生。</p><p>本文想讲两件事：</p><ol><li><strong>Lakebase &#x2F; AI 数据库到底在说什么？</strong> 各家定义并不一样；结合 OceanBase 发布会，说说小编对「Agent 友好」能力的理解。</li><li><strong>当 Agent 成为数据库的一等用户，库该长成什么样？</strong> 重点看 seekdb、PowerMem，以及从本地到企业级的一条路径。</li></ol><p><img src="/img/2026-07-06-ai-agent-database-evolution/18.png" alt="AI Agent 时代数据库演进主题图" decoding="async"></p><blockquote><p>🧠 想先上手摸一把？本地可试 <a href="https://github.com/oceanbase/seekdb">seekdb</a>，记忆层可看 <a href="https://github.com/oceanbase/powermem">PowerMem</a>。</p></blockquote><h2 id="Lakebase，为什么在-Agent-时代突然成了热词？"><a href="#Lakebase，为什么在-Agent-时代突然成了热词？" class="headerlink" title="Lakebase，为什么在 Agent 时代突然成了热词？"></a>Lakebase，为什么在 Agent 时代突然成了热词？</h2><p>开篇先唱个反调。</p><p>发布会后不少标题写 OceanBase「定义」了 Lakebase &#x2F; AI 数据库。小编觉得这话偏满：更准确的说法，是 OceanBase 讲清了<strong>自己</strong>对 Lakebase 的理解，而不是给全行业盖章。</p><p>很多人还不熟这个词，先从它是怎么火起来的说起。</p><p><img src="/img/2026-07-06-ai-agent-database-evolution/01.png" alt="Lakebase 概念在 Agent 时代走红示意" loading="lazy" decoding="async"></p><span id="more"></span><p>最早把 Lakebase 作为产品叙事推到台前的，是 Databricks。Databricks 发布 Lakebase 时，号称它是面向 AI apps 和 agents 的新一代 operational database，其实是基于 Serverless Postgres，打通了 Lakehouse 和 OLTP 能力。</p><p>后面 Zilliz 对 Lakebase 的理解又是另一种方式 —— 把 Vector Database 和 Data Lake 融合，围绕向量检索、AI search 和 lake-native storage 打造了一套 Vector 版本的 Lakebase 架构。</p><p>上周 OceanBase 发布 AI Database，提出 unified LakeBase architecture，并推出了 OceanBase Lakebase。更准确地说，Lakebase 不是单独一个“底层数据引擎”，而是 OceanBase 面向 AI 数据平台给出的湖库一体架构和数据底座。</p><p>OceanBase 的理解更像是：继续做进阶版的“一体化”数据库，把数据库的事务一致性、实时服务和可靠性，跟数据湖的对象存储、海量数据管理、开放计算接到一起，再把结构化、半结构化、非结构化、向量、全文、图这些数据形态放进统一治理体系里。它想解决的不是某个单点检索问题，而是想大幅降低 AI 时代企业数据底座的组件拼装复杂度。</p><p>同一个 Lakebase，各家理解完全不一样，这就很有意思了。</p><p>Databricks 的老本行是 Lakehouse，强项在数据湖、分析和 AI 平台。所以它讲 Lakebase，自然会讲成 Lakehouse + Serverless Postgres：在离线分析和湖仓体系里，缝合上在线事务处理能力。</p><p>Milvus 的本质是一个向量数据库。所以 Zilliz 讲 Lakebase，自然会围绕 Vector 和 AI search，把 Lakebase 的概念定义成 Vector Lakebase。</p><p>韩锋老师在<a href="https://mp.weixin.qq.com/s/Uv4b-jof0ZLSSsCn4kSXkA">《“湖库一体”，OB 一体化再升级》</a>里有个说法很贴切：“OceanBase 的产品演进史，本质上就是一部不断打破数据库技术壁垒的‘一体化’进化史。”所以，OceanBase 讲 Lakebase，自然会从“数据库一体化的进化论”来解释：从 OLTP 到 HTAP，再到多模一体化，再到现在的湖库一体。</p><p>其实无论是 Zilliz，还是 OceanBase，乃至于其他数据库，对 Lakebase 的看法并不完全一样，但底层趋势接近：都在自己的维度上做“一体化”的融合。</p><p>Lakebase 的热度，不是因为它新，而是因为它准，它正好戳中了 AI 时代数据系统最难受的地方：非结构化数据越来越多，数据质量压力越来越大，数据管理和 AI 开发割裂，实时数据又要更快地进入分析、训练、评测和在线服务链路。</p><p>AI Native 企业里经常是一套在线库、一套数仓、一套向量库，数据量大了，可能还会再额外增加一套数据湖。每多一套系统，就多了一份同步的开销和不一致风险。</p><p>OceanBase 在对外宣传时，很喜欢说“一体化”这三个字，看上去略显高大上，其实用 OceanBase AI 湖库研发负责人竹翁更朴素的说法，就是：<strong>精简技术栈，高效好运维。</strong> </p><p>也正如韩锋老师所说：</p><blockquote><p>少接几套系统，就少几条数据同步链路；少几条同步链路，就少几个凌晨三点把人叫醒的故障点。</p></blockquote><h2 id="OceanBase-AI-产品体系，有啥值得关注的新东西？"><a href="#OceanBase-AI-产品体系，有啥值得关注的新东西？" class="headerlink" title="OceanBase AI 产品体系，有啥值得关注的新东西？"></a>OceanBase AI 产品体系，有啥值得关注的新东西？</h2><p>发布会上重点讲的 OceanBase Lakebase，只是 OceanBase AI 产品体系中的底层数据平台，它把基于对象存储、存算分离的 OceanBase 和数据湖接起来，把湖、仓、库做成一套引擎，统一支撑湖仓分析负载，和数据库的事务负载。<br><img src="/img/2026-07-06-ai-agent-database-evolution/02.png" alt="OceanBase AI 产品体系分层架构图" loading="lazy" decoding="async"></p><p>官方的原文是：</p><blockquote><p>OceanBase Lakebase 作为底层引擎，承载湖库一体与多模态数据能力，让结构化数据、非结构化数据和向量数据能够在统一架构中被管理、加工、检索和调用。</p></blockquote><p>上面这张图，看起来总觉得比较别扭。从发布会上的内容来看，OceanBase Lakebase 的整体架构大概可以简化成：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">OceanBase Lakebase</span><br><span class="line">    ├── OceanBase</span><br><span class="line">    ├── Spark 引擎整合</span><br><span class="line">    ├── Ray 引擎整合</span><br><span class="line">    └── 对象存储</span><br></pre></td></tr></table></figure><p>其中：</p><ul><li>OceanBase：专注于实时数据处理和分析，提供高效的向量计算、混合搜索、实时加工与分析、事务处理能力。</li><li>Spark：开源集成，提供高性能离线加工能力。</li><li>Ray：开源集成，提供高效的 embedding、训练、推理和 Python 数据处理能力。</li></ul><p>优势也比较明显：一是 OceanBase 在支持湖库能力之前，HTAP + 单机分布式一体化架构的技术能力就已经比较成熟，TP&#x2F;AP&#x2F;AI 能力不输专用数据库和专业数仓；二是现在又增加了传统 Lakehouse 的大数据处理和分析能力，可以直接为企业的 AI 数据平台提供一套非常完整的解决方案。</p><p>除此以外，在发布会上我注意到还有一个 OceanBase 正在逐步成为 “Agent native 引擎” 的概念。不过发布会上只是简略一提，说 OceanBase 中会增加大量和 AI 相关的新特性，可惜都没有细讲。所以，小编正好可以趁机说说自己的理解（非官方，欢迎纠错）：</p><ul><li>支持对象存储、存算分离。这个好理解，就是为了应对 AI 时代持续膨胀的数据量，降低存储成本。</li><li>大对象类型（例如 AI 离不开的向量类型）会自动根据数据的实际大小，选择不同的存储形态。我理解就是数据小，存数据；数据大，存指针，然后指向实际的外部存储空间。</li><li>AI 列。这个东西，从使用的角度来看，我理解会类似于在生成列（GENERATED AS）的定义中加入 AI Function，让数据库根据提示词自动根据表格中的某些行的内容到一个生成列上。好处是所有数据都被包在数据库里，避免数据流入流出带来的风险和延时。</li><li>逻辑表。我理解就是让多个表结构相同的表，只存一份元数据。通过逻辑映射实现低成本共享与隔离，解决海量 Agent 导致的 Schema 爆炸问题。</li><li>unified catalog。这个和数据安全相关，我理解就是类似于用 Oracle 中的 Schema，对湖库中不同格式的数据，进行访问权限的隔离。</li></ul><p>剩下的“多模态”、“一体化”、“开放生态”……都是些老生常谈的东西，这里就不再展开细聊了，可以详见：<a href="https://mp.weixin.qq.com/s/uxpA7aJ24OxcNw1oRoFcRg">《OceanBase 湖库一体 AI 数据库正式发布》</a>。</p><p>除了上面这些东西，还有一个值得继续和大家详细聊一聊的东西，就是 <strong>“Agent 友好”</strong> 这个新时代的数据库特性 —— 因为 Agent 不只读写数据，它还会犯错并不断试错、会复用历史经验，还要支持层出不穷的端侧智能设备。所以也需要记忆和上下文、分支快照和出错回滚、极致轻量化等诸多新能力。</p><p>所以，在小编看来，发布会上重磅推出的 OceanBase Lakebase，只是 AI 数据库体系里的湖库底座。AI 数据库产品体系，显然不只是面向湖库能力的一次功能增强，而是面向 Agent、多模态数据和上下文工程的一次基础设施重建。所以，它还需要 seekdb、PowerMem 等 AI Native 产品来补齐 “Agent 友好” 这个 AI 时代对数据库的新诉求。</p><p><img src="/img/2026-07-06-ai-agent-database-evolution/03.png" alt="Lakebase 湖库一体架构简化示意" loading="lazy" decoding="async"></p><p>发布会上的叙事方式比较宏大，OceanBase 的各位老大们只重点介绍了 OceanBase Lakebase 这个 AI 时代的数据基座。有一些开发者朋友们最关心的是：<strong>我现在马上就能用到的是什么？答案之一就是刚刚提到的 —— seekdb。</strong></p><p><strong>发布会上提到的多模表、混合搜索、AI Function、fork table &#x2F; fork db 等与 AI 和 Agent 相关的能力，都能直接（甚至提前）在 seekdb 上体验到。</strong></p><h2 id="seekdb：给-Agent-准备的“轻量级-AI-Native-数据库”"><a href="#seekdb：给-Agent-准备的“轻量级-AI-Native-数据库”" class="headerlink" title="seekdb：给 Agent 准备的“轻量级 AI Native 数据库”"></a>seekdb：给 Agent 准备的“轻量级 AI Native 数据库”</h2><p><img src="/img/2026-07-06-ai-agent-database-evolution/04.png" alt="seekdb 作为轻量 AI Native 数据库定位" loading="lazy" decoding="async"></p><p>seekdb 是 OceanBase 社区面向 Agent 和 AI 应用的轻量级 AI Native Search Database，项目已开源，详见：<a href="https://github.com/oceanbase/seekdb">https://github.com/oceanbase/seekdb</a></p><p>它的定位不是“再造一个大而全的企业数据库”。它更像是 OceanBase 这条 DB for AI 路线在开发者侧的一个轻量入口：你可以先在本地、单机、嵌入式场景里用起来，再根据规模切到 seekdb server 或 OceanBase。</p><p>最关键的是，它知道 Agent 需要什么。</p><h3 id="第一件事：别让开发者第一步就被部署劝退"><a href="#第一件事：别让开发者第一步就被部署劝退" class="headerlink" title="第一件事：别让开发者第一步就被部署劝退"></a>第一件事：别让开发者第一步就被部署劝退</h3><p><img src="/img/2026-07-06-ai-agent-database-evolution/05.png" alt="seekdb 降低本地部署门槛示意" loading="lazy" decoding="async"></p><p>很多 AI 基础设施死在第一步，开发者刚想试试，就被满是繁文缛节的部署文档劝退了。</p><p>seekdb 这点很务实：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install -U pyseekdb</span><br></pre></td></tr></table></figure><p>pyseekdb 是 seekdb 的 Python SDK。它支持 embedded、本地 server、远程 OceanBase Server。原型阶段可以本地嵌入式运行，不用先搭复杂服务；后面要上规模，再换连接方式。</p><p>这条路，很适合 AI 应用开发。</p><p>今天很多 Agent 项目都是先从一个脚本、一个 Copilot、一个内部小助手长出来的。</p><p>seekdb 的 GitHub README 里把自己概括成一句话：“Write, Search, Fork. The State Store for AI Agents.” Agent 不只是需要存储，它需要持续写入、马上检索、随时试错。</p><h3 id="第二件事：不把-Agent-记忆当成纯向量问题"><a href="#第二件事：不把-Agent-记忆当成纯向量问题" class="headerlink" title="第二件事：不把 Agent 记忆当成纯向量问题"></a>第二件事：不把 Agent 记忆当成纯向量问题</h3><p><img src="/img/2026-07-06-ai-agent-database-evolution/06.png" alt="Agent 记忆需要混合检索而非纯向量" loading="lazy" decoding="async"></p><p>很多人一提 Agent 记忆，第一反应是向量数据库。</p><p>但真实场景里，Agent 的记忆和知识库很少是纯向量问题。</p><p>比如你问一个企业助手：“找一下上个月华东区客户投诉里，和退款相关、且语气比较激烈的案例。”</p><p>这句话里至少有三种检索：</p><ul><li>上个月、华东区、客户投诉，是结构化过滤；</li><li>退款，是全文关键词；</li><li>语气激烈、相似案例，是语义向量检索。</li></ul><p>如果你用 MySQL + Elasticsearch + Milvus 拼，当然也能做。但你要维护数据同步、权限一致、结果融合、排序策略，还要祈祷半夜别掉链子。</p><p>seekdb 的思路是：向量、全文、标量过滤放在一个引擎里，用一条 SQL 或一个 SDK 接口完成混合搜索。</p><p>这不只是省事。对 Agent 来说，这意味着上下文更实时，权限更一致，工程链路更短。</p><h3 id="第三件事：提前给会犯错的-Agent-准备后悔药"><a href="#第三件事：提前给会犯错的-Agent-准备后悔药" class="headerlink" title="第三件事：提前给会犯错的 Agent 准备后悔药"></a>第三件事：提前给会犯错的 Agent 准备后悔药</h3><p><img src="/img/2026-07-06-ai-agent-database-evolution/07.png" alt="为会犯错的 Agent 准备可回滚能力" loading="lazy" decoding="async"></p><p>现在这个时代，最危险的可能已经不是 AI 大模型敢胡说八道了，而是 Agent 敢拿着很高的权限，到处胡操八作。</p><p>Agent 会犯错，行业已经用层出不穷的生产事故一次又一次地交过学费，详见：<a href="https://mp.weixin.qq.com/s/Gm8mIPK4MnUZZ07Ue33rDQ">《700 万人围观 AI 删库跑路，罪魁祸首写下奇葩检讨》</a>。</p><p>上面这篇文章，可以用一句话来概括：完善的 System Prompt 绝对不是 Agent 去操作数据的安全边界。</p><p>对于 DBA 来说，重要的往往是效率和成本。但对 Agent 来说，有可以吃的后悔药，也许更重要。</p><p>seekdb 更实际的做法是 Fork &#x2F; Diff &#x2F; Merge。</p><p>它支持 Fork Table &#x2F; Fork Database，给 Agent 创建一个隔离的数据分支。Agent 可以在分支里改表、写数据、测试 Prompt、跑评测。成功了再 merge，失败了直接 drop。详见：<a href="https://mp.weixin.qq.com/s/7bGbTZPyIn7cX07Zpd4GmA">《seekdb fork table 能力测试报告》</a>里，测试场景包括 A&#x2F;B 实验、数据版本管理、回滚、生产数据隔离测试。<strong>这个能力很像 Git，只不过管理的不是代码分支，而是数据分支。</strong></p><p>如果上面这篇文章里在 AI 创业公司里删库跑路的 Agent 当时操作的是一个 fork 出来的测试分支的 Database，它就可以在里面尽情犯错，数据不会陪它一起消失。</p><p>这就是 Agent 时代数据库该有的基本礼貌：假设 Agent 一定会犯错，然后把爆炸半径关进 fork 出来的测试分支里。</p><h3 id="第四件事：seekdb-M0，把记忆产品往前推一步"><a href="#第四件事：seekdb-M0，把记忆产品往前推一步" class="headerlink" title="第四件事：seekdb M0，把记忆产品往前推一步"></a>第四件事：seekdb M0，把记忆产品往前推一步</h3><p><img src="/img/2026-07-06-ai-agent-database-evolution/08.png" alt="seekdb M0 向前推进记忆产品能力" loading="lazy" decoding="async"></p><p>除了 seekdb 本身，还有一个值得单独提的产品：seekdb M0。</p><p>它在社区文章里被描述为一个专门为 AI Agent 设计的自进化云记忆，支持一键接入、分享经验和持续进化，会在支持 Agent 之间经验共享的同时，缩减 token 成本。</p><p>这里不展开讲产品细节，只说它代表的方向：</p><p>Agent 记忆不应该只停留在“把聊天记录存下来”。它应该能跨会话、跨任务、甚至跨 Agent 沉淀经验。</p><p>比如一个 coding agent 试过某个错误方案，下次另一个 agent 不应该重新踩一遍坑。一个机器人在某个环境里学到的操作偏好，也不应该每次断电之后从零做人。</p><p>这件事继续往下走，就会从“记忆存储”走向“经验系统”。</p><h3 id="第五件事：seekdb-不只适合云上，也适合端侧和边缘"><a href="#第五件事：seekdb-不只适合云上，也适合端侧和边缘" class="headerlink" title="第五件事：seekdb 不只适合云上，也适合端侧和边缘"></a>第五件事：seekdb 不只适合云上，也适合端侧和边缘</h3><p>最近 Google DeepMind CEO 哈萨比斯在演讲中有一个判断：模型蒸馏会让更强的模型能力逐步下沉到端侧，详见：<a href="https://mp.weixin.qq.com/s/TxmPDsVaj9hBomb5jrM2eQ">《人类离 AGI 只剩 4 年，只差最后 3 块拼图》</a></p><p>这个趋势眼看着就要逐步成真了，所以很多 AI 能力，不会永远待在云上。</p><p><img src="/img/2026-07-06-ai-agent-database-evolution/09.png" alt="seekdb 覆盖云上端侧与边缘场景" loading="lazy" decoding="async"></p><p>智能设备、边缘设备、具身智能、智能驾驶，都有一个共同问题：不能每次想起一件事都先回云端翻档案。原因也很现实：移动网络很可能不稳定，但设备的延迟不能太高；外加用户隐私问题、成本问题等等。</p><p>这时，seekdb 的嵌入式形态、低资源门槛、本地混合检索就很有价值。它可以在设备侧保存局部状态、任务轨迹、用户偏好和检索索引。车端、机器人、智能终端都需要一块本地“小脑”：能低延迟检索，也能在必要时和云端大脑同步。</p><p>数据中心侧则可以用 OceanBase Lakebase 做多模态数据回流、治理、训练和评测。设备侧用 seekdb + PowerMem 负责即时反应，中心侧负责长期演进。</p><p>这条路，比“所有记忆都塞进云端大模型上下文窗口”靠谱得多。在发布会上，日照也提到了很多支持智驾的车企，现在就是这样做的 —— OceanBase + seekdb + PowerMem。这类“端侧即时反应 + 中心侧长期演进”的架构方向，正在变得越来越现实。</p><h2 id="PowerMem：让-Agent-不只是“记住”，而是“会整理记忆”"><a href="#PowerMem：让-Agent-不只是“记住”，而是“会整理记忆”" class="headerlink" title="PowerMem：让 Agent 不只是“记住”，而是“会整理记忆”"></a>PowerMem：让 Agent 不只是“记住”，而是“会整理记忆”</h2><p>讲完 seekdb，再看 OceanBase CTO 日照在发布会上提到的另一个 AI 产品 —— PowerMem（项目也已开源，详见：<a href="https://github.com/oceanbase/powermem%EF%BC%89%E3%80%82">https://github.com/oceanbase/powermem）。</a></p><p>如果说 seekdb 更偏“存和搜”，PowerMem 更偏“记和忘”。它不是向量数据库，也不是简单聊天历史。它更像 Agent 的记忆管理层：负责抽取、合并、遗忘、检索和经验沉淀。</p><p>德哥在<a href="https://mp.weixin.qq.com/s/LSW_pYokpQVbtXChR4zzLw">《PowerMem 未来可能成为 OB 的杀手锏》</a>里用了一个很形象的比喻来阐述 PowerMem 和其他记忆产品的不同：</p><blockquote><p>普通的向量数据库(Chroma、Milvus、Pinecone)是“会搜索的文件夹”: 你塞什么它存什么，召回什么它不负责。</p><p>mem0 是“听话的笔记本”:你告诉它“记住 X”，它存；你忘了告诉它，它不会主动记。</p><p>PowerMem 是“会思考的笔记本 + 秘书”: 它会自动从对话里“划重点”，对记忆进行去重和合并冲突、遗忘长期得不到访问的记忆，同时还支持记忆的精准召回。</p></blockquote><p><img src="/img/2026-07-06-ai-agent-database-evolution/10.png" alt="PowerMem 让 Agent 会整理长期记忆" loading="lazy" decoding="async"></p><p>Agent 的长期记忆最怕两种极端：一种是金鱼脑袋。每次新会话都像初次见面，昨天刚说完的偏好，今天又问一遍。另一种是仓库脑袋。什么都记，什么都塞，最后上下文越来越贵、越来越慢、越来越乱。不会遗忘的 Agent，最后不是更聪明，而是更像一个塞满旧便签的抽屉。</p><p>PowerMem 解决的就是 Agent 的长期记忆问题。</p><h3 id="它要知道什么值得记"><a href="#它要知道什么值得记" class="headerlink" title="它要知道什么值得记"></a>它要知道什么值得记</h3><p><img src="/img/2026-07-06-ai-agent-database-evolution/11.png" alt="PowerMem 判断哪些信息值得记住" loading="lazy" decoding="async"></p><p>不是所有聊天记录都值得长期保存。</p><p>“用户喜欢咖啡”可能值得记。</p><p>“用户今天下午 3 点说了一个‘嗯’”大概率不用记。</p><p>“这个项目的数据库从 MySQL 迁到了 OceanBase”值得记。</p><p>“刚才命令行输出了一个临时路径”可能只适合短期上下文。</p><p>PowerMem 做的是从对话、任务轨迹、反馈中抽取关键事实，再变成可检索、可更新、可治理的记忆。</p><h3 id="它会处理记忆冲突"><a href="#它会处理记忆冲突" class="headerlink" title="它会处理记忆冲突"></a>它会处理记忆冲突</h3><p><img src="/img/2026-07-06-ai-agent-database-evolution/12.png" alt="PowerMem 处理相互冲突的记忆条目" loading="lazy" decoding="async"></p><p>记忆不是静态文本。例如：用户昨天说喜欢咖啡，今天又说要戒咖啡了。</p><p>如果系统只会“追加”，记忆很快就会打架。PowerMem 要处理的是记忆演化，不是文本堆积。</p><h3 id="它懂得忘"><a href="#它懂得忘" class="headerlink" title="它懂得忘"></a>它懂得忘</h3><p><img src="/img/2026-07-06-ai-agent-database-evolution/13.png" alt="PowerMem 基于遗忘曲线淘汰旧记忆" loading="lazy" decoding="async"></p><p>这点听起来反直觉，但很重要。</p><p>人类记忆有遗忘机制，不是缺陷，而是压缩策略。Agent 也一样。</p><p>全量上下文方案看似简单，实际代价很高：token 贵、延迟高、注意力衰减，模型还可能在一堆旧信息里翻车。</p><p>PowerMem 的遗忘和衰减机制，就是为了控制噪音和成本，让真正有用的记忆留在前面。</p><h3 id="它不限制后端，但-seekdb-很适合它"><a href="#它不限制后端，但-seekdb-很适合它" class="headerlink" title="它不限制后端，但 seekdb 很适合它"></a>它不限制后端，但 seekdb 很适合它</h3><p>PowerMem 不应该被理解成“只能绑死某个数据库”。它可以适配不同后端。</p><p>但 seekdb 的轻量形态和混合检索能力，显然能提升 PowerMem 的表现。</p><p>PowerMem 管“什么值得记、什么时候该忘、怎么召回更准”；seekdb 管“这些记忆放在哪里、怎么稳定地查出来”。</p><p>一个像记忆管家，一个像记忆仓库和检索引擎。这两个组合起来，才更接近 Agent 真正需要的长期记忆系统。</p><h3 id="Experience-Skill：从记事实，到长经验"><a href="#Experience-Skill：从记事实，到长经验" class="headerlink" title="Experience + Skill：从记事实，到长经验"></a>Experience + Skill：从记事实，到长经验</h3><p><img src="/img/2026-07-06-ai-agent-database-evolution/14.webp" alt="从记事实到沉淀 Experience 与 Skill" loading="lazy" decoding="async"></p><p>PowerMem README 里明确提到 Experience + Skill distillation。相关社区文章也多次提到 seekdb M0 支持 Agent 之间经验共享。</p><p>为了避免把产品边界说得过满，这里可以保守理解为：OceanBase 社区这条记忆产品线，正在从“记事实”走向“沉淀经验和技能”。</p><p>这一步很重要。未来 Agent 的竞争，可能不只是“谁能调用更强的模型”，而是谁能把每次任务里的经验留下来，让下一次少走弯路。</p><h2 id="seekdb-PowerMem-OceanBase：一条从本地到企业级的路"><a href="#seekdb-PowerMem-OceanBase：一条从本地到企业级的路" class="headerlink" title="seekdb + PowerMem + OceanBase：一条从本地到企业级的路"></a>seekdb + PowerMem + OceanBase：一条从本地到企业级的路</h2><p>德哥在 <a href="https://mp.weixin.qq.com/s/v9L5ggFlsWaWlTqXVMsqlA">《OceanBase 在下一盘大棋》</a>里，把 seekdb、PowerMem 和 OceanBase 放在一起做了个总结：</p><blockquote><p>PowerMem 解决“Agent 怎么记住、怎么忘、怎么调出来”；</p><p>seekdb 解决“一条 SQL 把向量、全文、结构化数据查完”；</p><p>OceanBase 解决“上规模后怎么稳、怎么扩、怎么进入企业生产系统”。</p></blockquote><p><img src="/img/2026-07-06-ai-agent-database-evolution/15.webp" alt="seekdb PowerMem 与 OceanBase 演进路径" loading="lazy" decoding="async"></p><p>这条路径很顺：</p><p>本地开发阶段，可以用 pyseekdb，也就是 embedded seekdb，加上 PowerMem，快速给 Agent 加长期记忆。</p><p>中小生产阶段，可以用 seekdb server 加 PowerMem，承接 RAG、智能助手、代码 Agent、企业知识库。</p><p>企业规模阶段，可以用 OceanBase &#x2F; Lakebase 加 PowerMem，承接多模态、治理、权限、一致性和海量 Agent。</p><p>这条路也被德哥在另一篇文章<a href="https://mp.weixin.qq.com/s/dpxtzh6U9bU2UJK-TjjF5Q">《Claude、Codex 疯狂抢入口，OceanBase 闷声焊地基》</a>里说得很准：</p><blockquote><p>Claude、Codex、各种 Agent 平台都在抢入口。</p><p>但当 AI 真要进入企业生产系统，最后绕不开的还是数据底座。</p></blockquote><h2 id="DataStudio-和-DataPilot"><a href="#DataStudio-和-DataPilot" class="headerlink" title="DataStudio 和 DataPilot"></a>DataStudio 和 DataPilot</h2><p>当然，OceanBase 这次发布的不只是 Lakebase 和 PowerMem。</p><p>OceanBase 产品老大颜然还介绍了另外两个产品：统一开发治理平台 DataStudio，以及面向业务的 BI 分析 Agent DataPilot。</p><p><img src="/img/2026-07-06-ai-agent-database-evolution/16.webp" alt="DataStudio 与 DataPilot 协作示意" loading="lazy" decoding="async"></p><p>不过这两个产品小编暂时都还没有上手体验过，暂时不便进行过多的分析和评价，后面有缘再和大家介绍和分享。</p><h2 id="AI-for-DB-很热，但-DB-for-AI-才刚开始"><a href="#AI-for-DB-很热，但-DB-for-AI-才刚开始" class="headerlink" title="AI for DB 很热，但 DB for AI 才刚开始"></a>AI for DB 很热，但 DB for AI 才刚开始</h2><p>最近和很多 DBA、数据库开发者聊天，大家都在关注 AI 怎么改变数据库运维和开发，也就是 AI for DB，这很重要。让 AI 写 SQL、查慢查询、做巡检、生成报表，都是很现实的方向。</p><p>但 OceanBase 这场发布会更像是在讲另一条路：DB for AI。也就是说，数据库怎么反过来支撑 AI。AI 要真正进入企业，不能只靠一个聪明模型，它需要高质量数据，需要实时上下文，长期记忆，安全隔离，试错回滚，多模态治理。这时候，数据库不再只是后台那个“存数据的东西”，它需要进化成 Agent 的地基。</p><p><img src="/img/2026-07-06-ai-agent-database-evolution/17.png" alt="从 AI for DB 转向 DB for AI 的趋势" loading="lazy" decoding="async"></p><p>最后总结一下：小编觉得 OceanBase 这次发布会真正值得关注的，不只是“又发布了一个 AI 数据库”。更重要的是，它把一个问题摆到了桌面上：</p><blockquote><p>当 AI Agent 开始使用数据库，数据库应该变成什么样子？</p></blockquote><p>这个问题，才刚刚开始变得有点儿意思。</p><p><img src="/img/2026-07-06-ai-agent-database-evolution/19.png" alt="Agent 友好数据库能力清单总结" loading="lazy" decoding="async"></p>]]>
    </content>
    <id>https://ilongda.com/2026/2026-07-06-ai-agent-database-evolution/</id>
    <link href="https://ilongda.com/2026/2026-07-06-ai-agent-database-evolution/"/>
    <published>2026-07-06T02:01:03.000Z</published>
    <summary>从 Lakebase 与 AI 数据库谈起：Agent 需要怎样的数据底座？梳理 OceanBase Lakebase、seekdb、PowerMem 等 Agent 友好能力与演进方向。</summary>
    <title>AI Agent 要用数据库了：Lakebase、seekdb 与 PowerMem 怎么理解</title>
    <updated>2026-07-06T02:01:03.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="最新动态" scheme="https://ilongda.com/categories/%E6%9C%80%E6%96%B0%E5%8A%A8%E6%80%81/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="AI Agent" scheme="https://ilongda.com/tags/AI-Agent/"/>
    <category term="MCP" scheme="https://ilongda.com/tags/MCP/"/>
    <category term="Skill" scheme="https://ilongda.com/tags/Skill/"/>
    <category term="Easy Data x AI" scheme="https://ilongda.com/tags/Easy-Data-x-AI/"/>
    <category term="数据基础" scheme="https://ilongda.com/tags/%E6%95%B0%E6%8D%AE%E5%9F%BA%E7%A1%80/"/>
    <category term="开源课程" scheme="https://ilongda.com/tags/%E5%BC%80%E6%BA%90%E8%AF%BE%E7%A8%8B/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"Easy Data x AI 课程共建：补上 Agent 时代的数据基础课","description":"OceanBase 与 Datawhale 发起 Easy Data x AI 开源课程共建，围绕 Agent、RAG、记忆、Skill 与 MCP，用真实工程经验补上数据基础课。","image":"https://ilongda.com/img/2026-07-02-easy-data-ai-course/01.png","wordCount":2493,"datePublished":"2026-07-02T14:44:07.000Z","dateModified":"2026-07-02T14:44:07.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-07-02-easy-data-ai-course/"},"url":"https://ilongda.com/2026/2026-07-02-easy-data-ai-course/","inLanguage":"zh-CN","keywords":["OceanBase","AI Agent","MCP","Skill","Easy Data x AI","数据基础","开源课程"],"articleSection":["最新动态"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"最新动态","item":"https://ilongda.com/categories/最新动态/"},{"@type":"ListItem","position":3,"name":"Easy Data x AI 课程共建：补上 Agent 时代的数据基础课","item":"https://ilongda.com/2026/2026-07-02-easy-data-ai-course/"}]}</script><blockquote><p>社区课程《Easy Data x AI》共建活动启动了！</p><p>从大模型到 Agent，从数据底座到应用实践，我们希望能够和更多共建者一起把这门课做出来。</p><p>现在这门课程缺少的就是你的真实经验，欢迎大家一起来添上几笔~</p></blockquote><p>最近和大家聊 AI Agent，总会绕回几个老问题：记忆系统是产品概念还是能落地的工程方案？Skill、MCP、上下文工程听着都熟，真要做一个能长期跑的 Agent，第一步从哪下手？</p><p><img src="/img/2026-07-02-easy-data-ai-course/01.png" alt="Easy Data x AI 开源课程共建主题图" decoding="async"></p><p>很多教程把答案讲得很漂亮，学习者真正卡住的却是工程选择：架构图好看，动手时却不知道该用向量、关键词还是混合检索；Agent 看上去会“记住”，但记什么、忘什么、冲突了怎么办，往往没有标准答案。</p><p><img src="/img/2026-07-02-easy-data-ai-course/02.png" alt="Agent 工程落地中常见卡点示意" loading="lazy" decoding="async"></p><p>为此我们做了还在内测的开源课程《Easy Data x AI》。它不是又一份“从零学大模型”的资料，而是想把 Data 与 AI 之间最容易踩坑的那段路讲清楚。课程由 Datawhale 与 OceanBase 社区联合共建，已有基础篇、产品向的「道篇」和开发者向的「术篇」。现在更希望社区一起把它写深、写准、写实用。</p><span id="more"></span><h2 id="这门课想解决什么问题？"><a href="#这门课想解决什么问题？" class="headerlink" title="这门课想解决什么问题？"></a>这门课想解决什么问题？</h2><p>现在会调 LLM API 的人越来越多，但能把 Agent 做成一个稳定系统的人，还是稀缺。</p><p>原因也简单：Agent 不是一个 prompt 加几个 tool call。它需要数据层，需要检索，需要记忆，需要任务拆解，需要上下文管理，还需要一套能判断效果的评估方法。LangChain 的 Deep Agents 文档[2]里也把这些能力拆得很细：任务规划、文件系统、子 Agent、长期记忆、Human-in-the-loop、Skill，以及 MCP 工具接入。</p><p>《Easy Data x AI》选择从两条线讲这件事。</p><p>一条是“道篇”，更适合产品同学、运营同学、业务负责人和零基础 AI 爱好者。它不要求你上来就写代码，而是先帮你判断：这个需求适不适合做 Agent？RAG 应该怎么设计才不只是“塞进向量库”？记忆系统到底应该给用户带来什么体验？</p><p>另一条是“术篇”，面向已经能写点代码、能调用 LLM API 的开发者。这里会动手做 Streaming、Tool Use、AI Native 数据层、Agentic RAG、记忆系统和 Skill 到 MCP 的综合实战。</p><p><img src="/img/2026-07-02-easy-data-ai-course/03.png" alt="道篇与术篇双线课程结构示意" loading="lazy" decoding="async"></p><p>一个讲判断力，一个讲动手能力。两条线都需要，因为只会讲概念，最后容易做成 PPT；只会堆代码，又很容易做成一个没人想用的 demo。</p><h2 id="为什么需要共建？"><a href="#为什么需要共建？" class="headerlink" title="为什么需要共建？"></a>为什么需要共建？</h2><p>因为 Agent 这块变化太快，靠几个人闭门写课，很容易慢半拍。</p><p>比如混合检索。Meilisearch 在一篇介绍 hybrid search RAG[3] 的文章里提到，混合检索会同时用关键词搜索和语义搜索，再把更相关的结果送给大模型。这个说法不复杂，但真正落地时，权重怎么调、延迟怎么控、评测怎么做，都不是一句“用混合检索”能解决的。</p><p>再比如 AI Native 数据库。seekdb 官网把自己定义为一个把关系、向量、文本、JSON、GIS 放进同一个引擎的 AI-native search database；OceanBase 的文章《From Complex to Simple: How We Built seekdb for the AI Era[4]》也提到，AI 应用常见的问题不是没有工具，而是工具太碎，数据、索引、检索、重排之间有太多胶水代码。</p><p><img src="/img/2026-07-02-easy-data-ai-course/04.png" alt="课程共建覆盖混合检索与记忆等主题" loading="lazy" decoding="async"></p><p>这些变化，正好对应《Easy Data x AI》里想补的内容：混合检索、Agentic RAG、长期记忆、Skill 标准化、多租户记忆隔离、MCP 实战、评测和成本收益分析。</p><p>所以这门课现在最需要的，不是围观，而是有人来把自己踩过的坑写进去。</p><h2 id="如何参与共建？"><a href="#如何参与共建？" class="headerlink" title="如何参与共建？"></a>如何参与共建？</h2><p>我们已经在贡献指南里列了一批适合大家认领的共建任务，并为这些共建任务设置了不同的难度等级（L1 ~ L3）。</p><p>如果你第一次参与开源共建，可以从简单难度的任务（Good First Issue）L1 开始，把共建流程走通，比如补充 Skill 设计规范、修正文档衔接、完善章节引入。</p><p>如果你上手做过和课程内容有关的实验，可以选择中等难度的任务 L2，比如补充记忆衰减策略、Embedding 模型选型、混合检索的延迟和成本对比。这类内容很适合把真实测试过程写成课程材料。</p><p>如果你有工程经验，可以直接挑战难度更高的任务 L3，比如：多 Agent 记忆冲突的工程化解决、多 Skill 给上下文工程带来爆上下文的解决思路、混合检索上手实战……这些任务做完，不只是给课程添一节内容，也会变成你自己可以拿出来展示的开源作品。</p><p><img src="/img/2026-07-02-easy-data-ai-course/05.png" alt="按 L1 到 L3 认领共建任务流程" loading="lazy" decoding="async"></p><p>贡献方式也很简单：看一眼 课程共建指南[5]，找到你感兴趣的 Issue，留言认领，写完提 PR。哪怕只是修一个事实错误，也算贡献；如果你独立完成扩展篇，还会有正式署名。</p><h2 id="课程共建者的激励与收获"><a href="#课程共建者的激励与收获" class="headerlink" title="课程共建者的激励与收获"></a>课程共建者的激励与收获</h2><p>我们希望每一位参与者不仅留下贡献，也能收获成长。所有被合并 PR 的贡献者都会获得以下激励：</p><h3 id="🏆-贡献者墙"><a href="#🏆-贡献者墙" class="headerlink" title="🏆 贡献者墙"></a>🏆 贡献者墙</h3><p>所有合并过 PR 的贡献者，会自动登上课程仓库 README 的<strong>贡献者墙</strong>（头像 + GitHub 主页 + 贡献量），由 GitHub Action 自动更新，无需手动申请。</p><h3 id="🎁-实体礼品"><a href="#🎁-实体礼品" class="headerlink" title="🎁 实体礼品"></a>🎁 实体礼品</h3><p>按贡献量分档赠送 <strong>OceanBase 社区定制周边</strong>：</p><p>档位</p><p>条件（示例）</p><p>礼品</p><p>入门</p><p>合并 1 个有效的 PR</p><p>OceanBase 定制贴纸 &#x2F; 定制徽章</p><p>进阶</p><p>合并 2 个及以上的内容完善类 PR</p><p>OceanBase 专属马克杯 &#x2F; 专属帆布包</p><p>核心</p><p>独立完成一节扩展篇内容</p><p>OceanBase 布道师礼品套装</p><h3 id="🌟-成长与社区收获"><a href="#🌟-成长与社区收获" class="headerlink" title="🌟 成长与社区收获"></a>🌟 成长与社区收获</h3><ul><li><strong>课程署名</strong>：扩展篇作者会在课程对应章节页面的正式署名。</li><li><strong>纳入 OceanBase 社区布道师体系</strong>：表现突出的共建者可被推荐为「种子布道师」，获得 OceanBase 官方证书。</li><li><strong>讲师 &#x2F; 露出机会</strong>：受邀参与社区直播、线下 Meetup、高校行，输出自己的内容。</li><li><strong>优秀贡献者评选</strong>：定期评选季度优秀贡献者，额外礼品 + 社区公众号专访。</li><li><strong>职业机会</strong>：优秀贡献者可获得蚂蚁集团及 OceanBase 实习 &#x2F; 内推推荐。</li><li><strong>联合社区礼品</strong>：根据课程共建的贡献量，还可获得 OceanBase 社区为大家准备的定制礼物，以及 LangChain 中国社区的礼品。</li></ul><h2 id="适合谁来参与共建？"><a href="#适合谁来参与共建？" class="headerlink" title="适合谁来参与共建？"></a>适合谁来参与共建？</h2><p>如果你是学生，想找一个比“复现论文”更贴近真实工程的练手项目，这门课适合你。</p><p>如果你是开发者，已经会用 LangChain&#x2F;LangGraph、LlamaIndex、向量库或数据库，但想把经验沉淀成别人也能看懂的教程，这门课也适合你。</p><p>如果你是产品或运营同学，平时经常要判断“这个需求能不能用 AI 做”，你也可以参与“道篇”的内容共建。因为很多 Agent 项目的失败，不是模型不够强，而是一开始就没想清楚场景、边界和评价标准。</p><p>还有一种人特别适合来：你刚好被某个问题折磨过。比如记忆冲突，比如上下文爆炸，比如 RAG 查不到该查的内容，比如 Tool Use 只能跑通 demo，一上真实环境就开始摇摆。只要你愿意把这个过程写下来，后面的人就能少走一段弯路。</p><h2 id="最后，欢迎来写一小段"><a href="#最后，欢迎来写一小段" class="headerlink" title="最后，欢迎来写一小段"></a>最后，欢迎来写一小段</h2><p>开源课程最有意思的地方，是它不会在发布那天就结束。</p><p>一门课能不能变好，靠的不是首页写得有多漂亮，而是有没有人愿意把真实经验塞进去：一个更清楚的图，一个更稳的示例，一段更准确的解释，一次踩坑后的修正。</p><p>《Easy Data x AI》现在还在 Alpha 内测阶段，正适合参与。你不需要等自己变成“专家”再来贡献。很多时候，刚学会的人最知道哪里难懂，刚踩过坑的人最知道哪里该补。</p><p><img src="/img/2026-07-02-easy-data-ai-course/06.png" alt="邀请社区共建者补充真实工程经验" loading="lazy" decoding="async"></p><p>如果你愿意，欢迎和我们一起来把这门课写完~</p><h2 id="What’s-more"><a href="#What’s-more" class="headerlink" title="What’s more?"></a>What’s more?</h2><p>顺手再为大家安利一门进阶课。</p><p>这门课同样是开源课程，作者也是《Easy Data x AI》的维护者 —— LangChain 中国区唯一的社区大使张海立老师。</p><p>如果你已经不满足于“理解 Agent”，想直接上手做更完整的 Agent 系统，就可以来看看《Deep Agents 实战[6]》。</p><p>它更偏工程进阶，会围绕 Deep Agents 讲虚拟文件系统、任务规划、子 Agent、异步子 Agent、Skills、长期记忆等能力。LangChain 的 deepagents 仓库[7]也把它描述成一个带文件系统、子 Agent、上下文管理、Skills 等能力的 agent harness。</p><p><img src="/img/2026-07-02-easy-data-ai-course/07.png" alt="课程仓库与相关社区资源入口" loading="lazy" decoding="async"></p><p>所以大家可以把两门课连起来看：《Easy Data x AI》帮你补齐 Data 与 AI 的基础判断，《Deep Agents 实战》带你继续往生产级 Agent 的方向走。</p><p>最后的最后，我们把《Easy Data x AI》课程的共建链接放在了文末的“阅读原文”。欢迎大家挑个顺眼的任务，去 GitHub 上参与共建吧~</p><p><img src="/img/2026-07-02-easy-data-ai-course/08.png" alt="Datawhale 与 OceanBase 联合共建二维码" loading="lazy" decoding="async"></p><p>参考资料</p><p>[1]</p><p>Easy Data x AI: <a href="https://github.com/datawhalechina/easy-data-x-ai">https://github.com/datawhalechina/easy-data-x-ai</a></p><p>[2]</p><p>Deep Agents 文档: <a href="https://docs.langchain.com/oss/python/deepagents/overview">https://docs.langchain.com/oss/python/deepagents/overview</a></p><p>[3]</p><p>hybrid search RAG: <a href="https://www.meilisearch.com/blog/hybrid-search-rag">https://www.meilisearch.com/blog/hybrid-search-rag</a></p><p>[4]</p><p>From Complex to Simple: How We Built seekdb for the AI Era: <a href="https://en.oceanbase.com/blog/23848834048">https://en.oceanbase.com/blog/23848834048</a></p><p>[5]</p><p>课程共建指南: <a href="https://github.com/datawhalechina/easy-data-x-ai/blob/main/CONTRIBUTING.md">https://github.com/datawhalechina/easy-data-x-ai/blob/main/CONTRIBUTING.md</a></p><p>[6]</p><p>Deep Agents 实战: <a href="https://github.com/datawhalechina/deepagents-in-action">https://github.com/datawhalechina/deepagents-in-action</a></p><p>[7]</p><p>deepagents 仓库: <a href="https://github.com/langchain-ai/deepagents">https://github.com/langchain-ai/deepagents</a></p>]]>
    </content>
    <id>https://ilongda.com/2026/2026-07-02-easy-data-ai-course/</id>
    <link href="https://ilongda.com/2026/2026-07-02-easy-data-ai-course/"/>
    <published>2026-07-02T14:44:07.000Z</published>
    <summary>OceanBase 与 Datawhale 发起 Easy Data x AI 开源课程共建，围绕 Agent、RAG、记忆、Skill 与 MCP，用真实工程经验补上数据基础课。</summary>
    <title>Easy Data x AI 课程共建：补上 Agent 时代的数据基础课</title>
    <updated>2026-07-02T14:44:07.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="企业案例" scheme="https://ilongda.com/categories/%E4%BC%81%E4%B8%9A%E6%A1%88%E4%BE%8B/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="向量检索" scheme="https://ilongda.com/tags/%E5%90%91%E9%87%8F%E6%A3%80%E7%B4%A2/"/>
    <category term="混合搜索" scheme="https://ilongda.com/tags/%E6%B7%B7%E5%90%88%E6%90%9C%E7%B4%A2/"/>
    <category term="算秩未来" scheme="https://ilongda.com/tags/%E7%AE%97%E7%A7%A9%E6%9C%AA%E6%9D%A5/"/>
    <category term="生命科学" scheme="https://ilongda.com/tags/%E7%94%9F%E5%91%BD%E7%A7%91%E5%AD%A6/"/>
    <category term="AI 数据合成" scheme="https://ilongda.com/tags/AI-%E6%95%B0%E6%8D%AE%E5%90%88%E6%88%90/"/>
    <category term="多模数据" scheme="https://ilongda.com/tags/%E5%A4%9A%E6%A8%A1%E6%95%B0%E6%8D%AE/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"算秩未来基于 OceanBase：20TB 生命科学语料的混合搜索底座","description":"算秩未来用 OceanBase 承载约 20TB 生命科学训练语料，在一套库内完成标量、全文与向量混合搜索，支撑 AI 数据合成与 RAG 召回。","image":"https://ilongda.com/img/2026-07-01-oceanbase-life-science-hybrid-search/01.webp","wordCount":2448,"datePublished":"2026-07-01T14:44:07.000Z","dateModified":"2026-07-01T14:44:07.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-07-01-oceanbase-life-science-hybrid-search/"},"url":"https://ilongda.com/2026/2026-07-01-oceanbase-life-science-hybrid-search/","inLanguage":"zh-CN","keywords":["OceanBase","向量检索","混合搜索","算秩未来","生命科学","AI 数据合成","多模数据"],"articleSection":["企业案例"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"企业案例","item":"https://ilongda.com/categories/企业案例/"},{"@type":"ListItem","position":3,"name":"算秩未来基于 OceanBase：20TB 生命科学语料的混合搜索底座","item":"https://ilongda.com/2026/2026-07-01-oceanbase-life-science-hybrid-search/"}]}</script><p>算秩未来面向医疗、教育、材料与科研等场景，提供 GPU &#x2F; CPU 算力与 MaaS 服务。训练语料要落库、要能被 Agent &#x2F; RAG 查回来时，他们遇到一个典型难题：标量过滤、全文检索、向量语义检索如果拆到多套系统，同步成本与召回质量都会失控。</p><p>本文分享他们如何以生命科学大模型语料合成为起点，用 OceanBase 搭一套企业级混合搜索底座：约 20TB 原始数据、九张业务表，在同一引擎里覆盖 ID 查询、正则、全文与向量召回。</p><span id="more"></span><h2 id="数据库技术栈：业务数据库走向多模数据平台"><a href="#数据库技术栈：业务数据库走向多模数据平台" class="headerlink" title="数据库技术栈：业务数据库走向多模数据平台"></a>数据库技术栈：业务数据库走向多模数据平台</h2><p>算秩未来是一家年轻的公司，面向医疗、教育、材料、科研机构、政府单位及个人开发者，提供高性能 GPU 集群、弹性无服务器的 CPU 云算力，支撑训练推理和数据生产链路。产品形态从资源交付到算法研发，包括裸金属、云原生平台、机器学习平台与 MaaS（模型即服务）平台。</p><p>业务侧要求实时交付、弹性计费，还有自动运维和异构计算；MaaS 面向开发者后，模型调用量也很大。因此数据库种类偏多，大致分三层：</p><ul><li><strong>在线交易层</strong>：数据量不大，用 MySQL 支撑账号、订单、Token 调用量、计费等表。长远看，数据量上来后 MySQL 仍会被替换。</li><li><strong>缓存与消息层</strong>：Redis 缓存热点；Kafka 承担异步事件、日志传输与消息队列。</li><li><strong>分析与检索层</strong>：OceanBase、Doris、NebulaGraph 支撑 OLAP、日志、实体关系、全文与向量等复杂探索。不少 AI 开源框架自带 PG 协议，因此也接入了 PostgreSQL。</li></ul><p>所有实例容器化部署：MySQL &#x2F; PostgreSQL 用 Operator，OceanBase 用 OceanBase Operator，Kafka 用 Strimzi，Redis 用官方 Helm。容器化推进很快，但坑也不少，方案仍在迭代。</p><h2 id="对-OceanBase-的需求起点：生命科学大模型训练语料合成"><a href="#对-OceanBase-的需求起点：生命科学大模型训练语料合成" class="headerlink" title="对 OceanBase 的需求起点：生命科学大模型训练语料合成"></a>对 OceanBase 的需求起点：生命科学大模型训练语料合成</h2><p>我们将 OceanBase 用在「生命科学大模型语料训练」场景。垂直领域模型需要训练语料，语料原本散落在文件里；算法与算力团队希望落库后，整条训练链路能自动化。<strong>对数据库的核心要求是：既能按唯一 ID 查，又能做正则匹配、全文索引，还要具备向量检索能力。</strong></p><p>压力主要来自三方面：</p><ol><li><strong>规模</strong>：算法侧语料约 20TB、约 31 亿条量级，生物相关文件约 14,070 个，库内设计为 9 张业务表。术语覆盖小分子 &#x2F; SMILES、DNA、RNA、基因、蛋白等，来源含 NIH 等机构。核心诉求是把<strong>文件资产变成可治理、可索引、可追溯的数据资产</strong>。</li><li><strong>查询形态</strong>：从人工查资料，变成 Agent &#x2F; RAG 调用。除唯一索引外，还要标量过滤、全文、正则、语义向量，常常还要组合使用。高精度召回场景下，混合搜索几乎是标配。</li><li><strong>结构多样</strong>：若按传统方式拆库存储，库种越多，同步与链路越碎，成本越高。</li></ol><p>拆开用多套系统时，常见短板是：</p><ul><li>正排快，但盖不住别名与非标准表述</li><li>全文能搜文本，却和业务主键割裂</li><li>向量能找相似，却缺权威业务过滤</li><li>纯向量库的标签过滤往往不够强</li><li>多库同步带来冗余、运维与成本上升</li></ul><p><strong>缺的是一套能扛生命科学混合检索的统一底座。</strong> 我们试过 MySQL、PostgreSQL 和其他分布式库：要么存储太贵，要么引擎性能不够。</p><p>与 OceanBase 交流后，存储引擎设计令人印象深刻：既能明显压低存储成本，性能也往往强于传统向量库；其余特性也贴合我们的选型清单。</p><table><thead><tr><th>选型需求</th><th>OceanBase 如何满足</th></tr></thead><tbody><tr><td>兼容 MySQL 协议</td><td>兼容 MySQL；不少向量库不支持或性能差异大，难用常见 SDK 访问</td></tr><tr><td>分布式性能</td><td>一体化架构 + LSM-Tree，高压缩；约 20TB 数据可压约 30%</td></tr><tr><td>容器化部署</td><td>全云原生环境，提供体系化的容器部署能力</td></tr><tr><td>标量 &#x2F; 全文 &#x2F; 向量</td><td>原生混合检索，并具备部分图能力</td></tr><tr><td>企业级稳定</td><td>稳定性经市场验证</td></tr><tr><td>弹性扩展</td><td>企业级管理 + 原生混合检索，适合做统一输出底座，降低多系统复杂度</td></tr></tbody></table><h2 id="模型设计：从原始文档到可查询的关系模型"><a href="#模型设计：从原始文档到可查询的关系模型" class="headerlink" title="模型设计：从原始文档到可查询的关系模型"></a>模型设计：从原始文档到可查询的关系模型</h2><p>选型后需要对模型进行设计，将原始文档（Json 格式）文本落库。借助 AI 工具提效，我们能够在几十分钟内完成代码编写，跑完直接落库。</p><p><img src="/img/2026-07-01-oceanbase-life-science-hybrid-search/01.webp" alt="生命科学语料从文档到关系模型映射" decoding="async"></p><p>整个阶段需要筛选出关键字段，变成结构化表结构。需要设计哪些字段单独提出、哪些字段放 Json 类型。存在多层嵌套，有父子表关系，拆了三张父子表。</p><p>索引设计方面 OceanBase 同时支持标量、全文、向量。结构保留原始 Json，保证原始数据来源source，因为应用需要上下文可回溯，最后返回数据时需要把原文返回给模型。</p><p>以基因、蛋白、小分子为例，有 Molecule以及Molecule SMILES分子表达式，在不同库中的表达式不一样，存在复杂关系。OceanBase主要用于处理复杂关系查询。数据属于数据资产，不会归档，没有按时间做分区，而是用 CID 加 ID 进行全局唯一 Hash 分区，每个表 32 个分区。</p><p>核心原则是：C 端统一分区，Json 和索引保证稳定，提供差异化检索服务。希望数据结构化后能够精准召回。</p><p><img src="/img/2026-07-01-oceanbase-life-science-hybrid-search/02.webp" alt="业务表与全文向量索引协同设计示意" loading="lazy" decoding="async"></p><h2 id="查询实践：同一数据底座覆盖三类生命科学召回"><a href="#查询实践：同一数据底座覆盖三类生命科学召回" class="headerlink" title="查询实践：同一数据底座覆盖三类生命科学召回"></a>查询实践：同一数据底座覆盖三类生命科学召回</h2><p>查询条件涉及专业术语，小分子主要通过CID，DNA、蛋白质通过 NCBI、UniProt ID 返回。基因中心法则等通过相关 Json Tag 做模糊匹配。涉及标量唯一检索、正则模糊匹配、向量检索等多种入口。四个入口+结构化模型+混合专业化，让搜索从确定性命中到可组合调用。</p><p>目前该项目还在进行中，只做了前半部分。框架定义为三层。</p><ul><li>L1：精确查找，通过唯一 ID（CID 或 InChI）精确命中。</li><li>L2：模糊查找，通过基因名等做全文检索。</li><li>L3：语义查找，通过向量检索召回。</li></ul><blockquote><p>基因序列补充说明：每个基因序列看似简单，实际很长，一个分子的基因序列可能几百 MB 甚至几个 GB。遇到 OceanBase 大字段 500 MB 限制，需要拆分处理。L2 模糊查找通过基因名在 OceanBase 全文检索，以及其他阶段字段做小检索。接下来我们将通过向量检索对基因序列向量化并存入库，通过相似检索召回需要的基因，从确定命中到相似发现，形成可编排的企业级检索链路。</p></blockquote><p>OceanBase 在L2层，既能管理业务数据，也能承接搜索所需的向量和上下文，比如将上层的数据存为多模态，向应用层或 AI 提供能力。整个 OceanBase 3 副本 1:1:1 部署，通过 OBProxy 访问。</p><p><img src="/img/2026-07-01-oceanbase-life-science-hybrid-search/03.png" alt="标量全文向量三类召回统一查询示意" loading="lazy" decoding="async"></p><p>在部署前期，我们在 OceanBase 前加了一层 OBProxy（业务从 OBProxy 进来访问OB Server），全部通过 OB Operator 管理，过程中遇到一些问题。</p><ul><li>Dashboard 扩容 Zone 后 add server 超时偏短，Pod创建成功但OBZone &#x2F; OBServer状态异常。需手动执行 alter system add server，再用 OBResourceRescue重置 OBServer状态。</li><li>扩容 Zone 只支持 nodeSelector，缺少 pod affinity 配置入口。</li><li>Dashboard 上缩容节点或 Zone 存在状态机不一致问题，容易误操作，且修复集群状态比较繁琐。</li><li>拓扑、任务进度、异常原因和恢复建议没有在同一视图中连接起来。</li></ul><p>基于此，我们希望OceanBase能够尽快将运维体验和 AI 搜索能力一起补齐。</p><ul><li>Dashboard + Operator 提供一键扩容：预检查、affinity、进度、失败恢复和回滚 Runbook。</li><li>增强 PostgreSQL 协议兼容，降低 PostgreSQL 生态应用、驱动和 SQL 迁移成本。</li><li>补齐图检索 &#x2F; 知识图谱关系召回，与标量、全文、向量形成GraphRAG混合链路。</li></ul><h3 id="业务价值：一套系统解决多种问题"><a href="#业务价值：一套系统解决多种问题" class="headerlink" title="业务价值：一套系统解决多种问题"></a>业务价值：一套系统解决多种问题</h3><p>使用 OceanBase 后，业务的演进路线越来越清晰，价值越来越凸显。数据从文献文本变成了数据库中可查询、多维度、可精准召回的数据资产。通过数据库实现多维度的标量、唯一键、全文检索，命中率更高，链路更短。 <strong>整个链路只需一套系统就能解决问题，不再需要 MySQL、Elasticsearch、 Milvus或其他大型数据库拼凑。对我们来说，这就是最优解。</strong></p><p><img src="/img/2026-07-01-oceanbase-life-science-hybrid-search/04.webp" alt="混合搜索底座覆盖多类业务查询" loading="lazy" decoding="async"></p><p>基于OceanBase，技术落地路线从生命科学可用检索演变为智能搜索。当前，阶段1的数据入库与基础查询和阶段2的模糊与全文召回已经落地，阶段3与阶段4正在进行中。 最终目标是： 统一数据底座 + 可编排搜索链路 + 面向 AI 的高质量上下文返回。</p><p><img src="/img/2026-07-01-oceanbase-life-science-hybrid-search/05.webp" alt="统一数据底座降低多库同步成本" loading="lazy" decoding="async"></p><p>用统一数据底座，承接 AI 时代的企业混合搜索。</p><blockquote><p>OceanBase 混合搜索方案将精确查询、模糊检索和语义召回统一到企业级数据架构中，让大规模复杂数据既能被可靠管理，也能被 AI 高效调用。</p></blockquote><p><img src="/img/2026-07-01-oceanbase-life-science-hybrid-search/06.webp" alt="OceanBase 混合搜索业务价值总结" loading="lazy" decoding="async"></p><p>添加社区小助手，加入微信交流群~</p>]]>
    </content>
    <id>https://ilongda.com/2026/2026-07-01-oceanbase-life-science-hybrid-search/</id>
    <link href="https://ilongda.com/2026/2026-07-01-oceanbase-life-science-hybrid-search/"/>
    <published>2026-07-01T14:44:07.000Z</published>
    <summary>算秩未来用 OceanBase 承载约 20TB 生命科学训练语料，在一套库内完成标量、全文与向量混合搜索，支撑 AI 数据合成与 RAG 召回。</summary>
    <title>算秩未来基于 OceanBase：20TB 生命科学语料的混合搜索底座</title>
    <updated>2026-07-01T14:44:07.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="实战分享" scheme="https://ilongda.com/categories/%E5%AE%9E%E6%88%98%E5%88%86%E4%BA%AB/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="AI Agent" scheme="https://ilongda.com/tags/AI-Agent/"/>
    <category term="PowerMem" scheme="https://ilongda.com/tags/PowerMem/"/>
    <category term="Python" scheme="https://ilongda.com/tags/Python/"/>
    <category term="GLM-5.2" scheme="https://ilongda.com/tags/GLM-5-2/"/>
    <category term="TypeScript" scheme="https://ilongda.com/tags/TypeScript/"/>
    <category term="长程任务" scheme="https://ilongda.com/tags/%E9%95%BF%E7%A8%8B%E4%BB%BB%E5%8A%A1/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"GLM-5.2 长程任务实测：把 PowerMem SDK 从 Python 对齐到 TypeScript","description":"GLM-5.2 长程任务实测：用大模型把 OceanBase PowerMem SDK 从 Python 功能对齐到 TypeScript，覆盖边界、评测、七轮迭代与交叉评审。","image":"https://ilongda.com/img/2026-06-29-glm-52-powermem-typescript-sdk/01.webp","wordCount":5487,"datePublished":"2026-06-29T14:44:08.000Z","dateModified":"2026-06-29T14:44:08.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-06-29-glm-52-powermem-typescript-sdk/"},"url":"https://ilongda.com/2026/2026-06-29-glm-52-powermem-typescript-sdk/","inLanguage":"zh-CN","keywords":["OceanBase","AI Agent","PowerMem","Python","GLM-5.2","TypeScript","长程任务"],"articleSection":["实战分享"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"实战分享","item":"https://ilongda.com/categories/实战分享/"},{"@type":"ListItem","position":3,"name":"GLM-5.2 长程任务实测：把 PowerMem SDK 从 Python 对齐到 TypeScript","item":"https://ilongda.com/2026/2026-06-29-glm-52-powermem-typescript-sdk/"}]}</script><blockquote><p>GLM-5.2 是智谱开放的新一代大模型（约 1M 上下文，兼容 Claude Code 协议）。</p><p>PowerMem 是 OceanBase 开源的 AI 记忆引擎，为 LLM 应用提供长期记忆、检索与智能遗忘。</p><p>当两者碰上：用真实工程任务，测模型能不能把 TypeScript SDK 对齐到 Python 主线。</p></blockquote><blockquote><p>✨ 文中仓库：<a href="https://github.com/oceanbase/powermem">oceanbase&#x2F;powermem</a>。对多语言 SDK 或 Agent 记忆感兴趣，可以直接去看 TypeScript 目录怎么演进。</p></blockquote><h2 id="灵光一闪：一个撞上门来的真实-case"><a href="#灵光一闪：一个撞上门来的真实-case" class="headerlink" title="灵光一闪：一个撞上门来的真实 case"></a>灵光一闪：一个撞上门来的真实 case</h2><p>这个灵感来得很突然。</p><p>起因是有幸受邀参与 GLM-5.2 模型长程任务执行的测试计划，需要在智谱和 AGI Bar 联合举办的活动中分享一个内测 case。</p><p>正巧手上在做的 Agent 平台项目要用到 OceanBase PowerMem 的 TypeScript 版本 SDK。但翻了翻 PowerMem 的 GitHub 仓库，发现 TypeScript SDK 的迭代节奏没跟上 Python SDK，存在一些滞后。</p><p>GLM-5.2 一个绝佳的长程任务测试 case，就这么撞上门来了——让 GLM-5.2 去完成 PowerMem 从 Python SDK 到 TypeScript SDK 的功能拉平，把滞后的迭代节奏都给补齐。</p><p><img src="/img/2026-06-29-glm-52-powermem-typescript-sdk/01.webp" alt="GLM-5.2 与 PowerMem 长程任务实测场景" decoding="async"></p><span id="more"></span><p>欢迎大家关注 OceanBase 社区公众号 “老纪的技术唠嗑局”。在这里，我们会持续为大家更新与 #AI 和 #Data 相关的技术内容~</p><h2 id="PowerMem：为什么它是长程任务的天然试金石"><a href="#PowerMem：为什么它是长程任务的天然试金石" class="headerlink" title="PowerMem：为什么它是长程任务的天然试金石"></a>PowerMem：为什么它是长程任务的天然试金石</h2><p>PowerMem 覆盖的能力很多，核心能力面铺得很广，而每一项背后都是一块独立的工程模块：</p><p><img src="/img/2026-06-29-glm-52-powermem-typescript-sdk/02.webp" alt="PowerMem 多模块能力构成长程任务试金石" loading="lazy" decoding="async"></p><ul><li>长期记忆的存储、检索、更新、删除和批量管理</li><li>来源管理 (SourceStore) 和技能管理 (SkillStore)</li><li>基于艾宾浩斯曲线的智能遗忘</li><li>多 Agent 协作、Scope 和 Permission 控制</li><li>HTTP server 和 Dashboard 可视化</li><li>向量、全文、图和时间信号的混合检索</li></ul><p>PowerMem 在多语言 SDK 上铺得比较开，官方目前维护 Python、TypeScript、Go、Java 等几种主流语言。其中 Python SDK 是主维护版本，行为规范最完整、更新最活跃，几乎每天都有提交；TypeScript SDK 则在早期完成了核心能力的实现，但近期没能完全跟上 Python 的节奏，两个版本之间存在一些功能层面的错位和对齐空间。</p><p>于是一个工程问题浮出水面：如何把 Python SDK 已经沉淀下来的行为规范，完整、可控地映射到 TypeScript 版本上？这事并不容易，很考验模型的能力——它要求模型做的是工程判断，而不只是写代码。TypeScript 仓库已经有大量能力，模型既不能为了显得“做了很多”而从零重写，也不能机械照搬 Python 的命名和风格。它必须先识别已有实现，再判断哪些地方需要补代码、哪些地方应该补测试、哪些地方只需写入 known-gaps。</p><p>这个任务的验证面也很完整：可以看 type-check、test、build、lint，可以看 git diff，可以看 upstream 是否被误改，可以看测试是否依赖真实 API Key，还可以看模型是否诚实记录了 baseline 失败和剩余缺口。</p><p>所以这个 case，一方面能看 GLM-5.2 能不能在一个持续数小时、多轮变化、带真实约束的工程任务里始终保持正确方向，另一方面也能顺手给 PowerMem TypeScript SDK 做一次完整的功能复盘和对齐。</p><p>嗯，一举两得。</p><h2 id="划定边界：把“翻译”和“对齐”分清楚"><a href="#划定边界：把“翻译”和“对齐”分清楚" class="headerlink" title="划定边界：把“翻译”和“对齐”分清楚"></a>划定边界：把“翻译”和“对齐”分清楚</h2><p>真实的工程 case 定下来之后，接着要想的是怎么开始。</p><p>想让模型顺利上手，首先得把它落成一份模型能接住的工程任务：从哪个仓库出发、能改什么不能改什么、最终交付物有哪些、哪些行为必须保留……这一整套边界定清楚，模型的表现才能被客观评审。</p><p>具体到 PowerMem 这次任务，主要涉及两个仓库：</p><ul><li>upstream-powermem，即 Python 主仓库，只读参考、不允许修改，它是行为来源。</li><li>candidate-powermem-ts，即 TypeScript 候选仓库，是模型的主要修改对象，必须保留现有项目结构和 API 风格。</li></ul><p>在此之上，我还规定了几条核心要求：</p><p><img src="/img/2026-06-29-glm-52-powermem-typescript-sdk/03.webp" alt="Python 与 TypeScript SDK 对齐边界示意" loading="lazy" decoding="async"></p><ol><li>读懂 Python 主仓库的 PowerMem 行为。</li><li>读懂 TypeScript 当前实现和已有测试。</li><li>识别 TypeScript 已有能力，避免重复实现。</li><li>建立 Python API 到 TypeScript API 的行为 mapping。</li><li>对关键差异补充实现、测试或 known-gaps。</li><li>编写 Vitest parity tests，用测试证明行为对齐。</li><li>保证 type-check、test、build、lint 等结果可复现。</li><li>输出迁移文档和最终报告。</li></ol><p>这个 case 里最容易踩的坑，是把任务理解成“翻译”。真正的目标是行为对齐：这个 API 在 Python 里的真实行为是什么？TypeScript 里有没有实现？如果有，行为是否等价？如果不完全等价，该修代码、补测试，还是作为差异记录？如果要修，能不能最小修改、不破坏现有架构？每一步都是判断题。</p><h2 id="评测设计：挖好坑，才测得出真本事"><a href="#评测设计：挖好坑，才测得出真本事" class="headerlink" title="评测设计：挖好坑，才测得出真本事"></a>评测设计：挖好坑，才测得出真本事</h2><p>任务边界定下来之后，还得设计怎么评——用什么标准衡量最终结果的好坏。</p><p>如果只盯着最终仓库看，很容易掉进两个对称的陷阱：要么模型把环境历史问题包装成自己修好的业务 bug，要么反过来把环境问题算到模型头上。所以评测不能只看终态，得提前埋下一些过程观察点和隐藏验收点。</p><p>正式测试前，需要先记录 baseline。其实 PowerMem 候选仓库在 baseline 阶段的 type-check、test、build 都是失败的，但失败原因是 npm 安装不完整以及 Windows 上 npm optional dependency 的问题，而非候选代码本身的 bug。这份 baseline 记录很关键，它能挡住一个常见的评测误差：要么把环境历史问题算到模型头上，要么让模型把 baseline 问题包装成自己的功劳。</p><p>同时，我为 GLM-5.2 的任务执行埋了一批隐藏验收点：</p><p><img src="/img/2026-06-29-glm-52-powermem-typescript-sdk/04.webp" alt="长程任务评测维度与验收坑位设计" loading="lazy" decoding="async"></p><ol><li>是否误改 Python 主仓库。</li><li>是否从零重写 TypeScript 仓库。</li><li>是否识别 TypeScript 已有核心实现。</li><li>是否伪造测试结果。</li><li>是否依赖真实 API Key。</li><li>是否覆盖批量操作。</li><li>是否有 known-gaps。</li><li>是否保留 TypeScript API 风格。</li><li>需求变更时是否增量修改。</li><li>故障修复时是否最小修改。</li><li>是否有 PR 级交付意识。</li><li>是否区分 baseline 问题和候选实现问题。</li></ol><p>这些点不会提前告知模型，但会在最终审查中逐项评估。在长程任务里，最危险的往往不是写错一行代码，而是方向漂移、无谓重写、掩盖失败、改动范围失控，或者把环境问题和业务问题搅在一起。埋下这些点不是为了刁难，而是为了测出真正的工程能力。</p><h2 id="七轮任务执行总览"><a href="#七轮任务执行总览" class="headerlink" title="七轮任务执行总览"></a>七轮任务执行总览</h2><p>准备工作做完，GLM-5.2 可以正式开跑了。</p><p>整个任务按阶段推进，每一阶段对应一个明确的子目标——既给模型设了工程检查点，也方便后续评审按阶段复盘。</p><p><img src="/img/2026-06-29-glm-52-powermem-typescript-sdk/05.webp" alt="GLM-5.2 七轮任务执行总览时间线" loading="lazy" decoding="async"></p><p>过程一共分成七轮，见下表。</p><table><thead><tr><th>轮次</th><th>内容</th><th>关键词</th></tr></thead><tbody><tr><td>R1</td><td>主任务：核心 SDK 行为对齐</td><td>审计、最小补丁、parity tests</td></tr><tr><td>R2</td><td>批量 API 复核</td><td>业务代码 0 改动、补测试</td></tr><tr><td>R3</td><td>文档债修复</td><td>最小修复、不碰业务代码</td></tr><tr><td>R4</td><td>深度功能对齐</td><td>差异矩阵</td></tr><tr><td>R5</td><td>深水区真实实现</td><td>Source&#x2F;Skill&#x2F;Ebbinghaus&#x2F;HTTP</td></tr><tr><td>R6</td><td>文档与开发者体验收尾</td><td>README、examples、导出</td></tr><tr><td>R7</td><td>最终一致性审查</td><td>验证、报告、HTML</td></tr></tbody></table><p>从 R1 到 R7，大致可以分成两段：R1 到 R3 偏向核心 SDK 的行为对齐，工程纪律优先；R4 到 R7 偏向深度功能和文档收尾，复杂度和稳定性是重点。下面就按这两段拆开看。</p><h2 id="R1-到-R3：先审后写的工程纪律"><a href="#R1-到-R3：先审后写的工程纪律" class="headerlink" title="R1 到 R3：先审后写的工程纪律"></a>R1 到 R3：先审后写的工程纪律</h2><p>R1 到 R3 这三轮，最能看出模型有没有“正确起步”。</p><h3 id="R1：先审计，再动手"><a href="#R1：先审计，再动手" class="headerlink" title="R1：先审计，再动手"></a>R1：先审计，再动手</h3><p>R1 里模型没有上来就写代码，而是先做审计。</p><p>PowerMem TypeScript 不是空仓库，它已经实现了 12 个核心 Memory API。所以 GLM-5.2 没有重写 Memory 类，而是做了 4 处最小行为对齐：</p><ul><li>update 空 content 校验，对齐 Python 的 ValueError 行为</li><li>getAll 默认 order 显式设为 desc</li><li>count 包 try-catch，异常时返回 0</li><li>deleteAll 在存在 graphStore 时同步清理</li></ul><p>这一轮业务代码只动了 <code>src/powermem/core/memory.ts</code> 一处，其余主要是新增测试、文档和示例。</p><p>改动出乎意料地小，稍微有点意外。</p><h3 id="R2：需求变更，克制住不重写"><a href="#R2：需求变更，克制住不重写" class="headerlink" title="R2：需求变更，克制住不重写"></a>R2：需求变更，克制住不重写</h3><p>接着是 R2，这是一次需求变更：要求复核 addBatch、getAll、count、deleteAll、reset 五个批量 API，并明确不重写、不删除。</p><p>模型先审计了已有状态，判断这些 API 在第一轮已经覆盖，第二轮重点不该是再改业务代码，而是补测试和文档。于是 R2 业务代码 0 改动，只追加了 22 个 batch parity tests，并更新了 migration 文档和最终报告。</p><h3 id="R3：故障修复，只动文档不碰代码"><a href="#R3：故障修复，只动文档不碰代码" class="headerlink" title="R3：故障修复，只动文档不碰代码"></a>R3：故障修复，只动文档不碰代码</h3><p>R3 是一次故障修复，属于临时加入的一轮——R1、R2 之后发现了一些问题，比如 api-mapping 文档里关于 getAll 默认 order 的描述自相矛盾。但重新审核后，模型把它归类为“文档 - 代码不一致”而非实现问题，最终只修了文档中的相关行，没碰业务代码，也没删测试。</p><p>前三轮，我没让 GLM-5.2 一上来就推倒重来，而是先审计、后判断、再做最小改动——这在长程工程任务里，是一种相对严格的规范行为。</p><h2 id="R4-到-R7：复杂度飙升后还稳得住吗"><a href="#R4-到-R7：复杂度飙升后还稳得住吗" class="headerlink" title="R4 到 R7：复杂度飙升后还稳得住吗"></a>R4 到 R7：复杂度飙升后还稳得住吗</h2><p>接下来是 R4 到 R7。如果说前三轮证明的是基本工程纪律，那么后四轮更能体现复杂长程任务的真实能力。</p><h3 id="R4：认知负荷最高的一轮"><a href="#R4：认知负荷最高的一轮" class="headerlink" title="R4：认知负荷最高的一轮"></a>R4：认知负荷最高的一轮</h3><p>从 R4 开始，任务从核心 SDK API 的表面对齐，扩展到深度功能对齐。这是整个 case 里认知负荷最高的一轮：前几轮处理的是 12 个核心 Memory API 这种相对集中的目标，而 R4 一下子把视野拉到全仓库——Python 仓库共 183 个源文件，TypeScript 仓库 80 多个源文件，两边逐一对照。涉及的深层模块有 SourceStore、SkillStore、SkillManager、ScopeController、PermissionController、HttpMemoryClient、EbbinghausAlgorithm、IntelligentMemoryManager 等几十个，每个 API 都要明确：Python 里在哪、TypeScript 里在哪、当前状态如何、该怎么处理。</p><p>为了不让这些差异散落在零碎笔记里，GLM-5.2 审计了大量 Python 与 TypeScript 文件后，汇总出一份 deep-feature-gap-matrix。每条记录都带 Python 来源文件、TypeScript 对应位置、状态归类、优先级和本轮处理策略。状态分成五类：</p><ul><li>已对齐：TypeScript 已有对应实现，行为也一致，不需再动</li><li>部分对齐：两边都有实现但行为有差异，要决定是改 TypeScript，还是文档化为已知差异</li><li>未实现：TypeScript 完全没有，需要在 R5 里补真代码或补 stub</li><li>不适合对齐：Python 侧能力依赖 Python 生态或外部服务，TypeScript 侧没必要硬怼，直接记入 known-gaps</li><li>需要人工确认：差异本身比较模糊，模型不敢自己拍板，标出来留给后续人工评审</li></ul><p>每条还标了优先级：P0 必须本轮处理、P1 应当本轮处理、P2 可放到后续 PR。这个优先级机制让 R5 的施工顺序一目了然——先 P0 再 P1，P2 留到后面。</p><p>这份矩阵，在 R5 里就是真正的施工图纸，每实现一块就回头打个勾，避免掉进“看起来实现了、其实只是 stub”的坑。</p><p><img src="/img/2026-06-29-glm-52-powermem-typescript-sdk/06.webp" alt="第四轮高认知负荷任务执行细节" loading="lazy" decoding="async"></p><h3 id="R5：啃下深水区"><a href="#R5：啃下深水区" class="headerlink" title="R5：啃下深水区"></a>R5：啃下深水区</h3><p>R5 是整个任务里代码复杂度最高的一轮，从“补丁式修改”正式进入“新增实现”阶段。R4 生成的差异矩阵在这里化作施工图纸，每一行“未实现”或“部分对齐”都得落到真实代码上。</p><p>这一轮新增的模块横跨好几个完全不同的技术域：存储抽象与参考实现的 SourceStore&#x2F;SkillStore、数值计算类的 EbbinghausAlgorithm、LLM-driven 的 SkillManager、语义对齐类的 ScopeController 和 PermissionController，还有走 HTTP 协议的 HttpMemoryClient。每一块的实现风格、测试方式、外部依赖都不一样，却要在同一轮里同时推进，模块之间还得保持接口和数据流连贯，不能各写各的、最后拼不上。</p><p>复杂度不只在于模块多，更在于每个模块背后都有判断题：哪些能力直接照搬 Python 不现实、需要重新设计抽象层？哪些行为必须做数值对齐而非逻辑对齐？哪些测试不能依赖真实外部服务、得把 LLM、fetch、数据库这些依赖全部注入化？这些都很考验模型的整体工程判断。</p><p>这一轮跑下来，最终测试达到 649 passed &#x2F; 2 skipped &#x2F; 0 failed，比 R4 之前多出几百个 case；整个仓库的真实实现占比提升到约 92%，stub 压到约 8%。剩下的 stub 集中在 OceanBase 原生能力和少量高层串联 API 上，而且这些缺口都被显式记录在 known-gaps 里——没有藏在代码注释里，也没有被悄悄忽略。</p><h3 id="R6-与-R7：文档收尾与最终审查"><a href="#R6-与-R7：文档收尾与最终审查" class="headerlink" title="R6 与 R7：文档收尾与最终审查"></a>R6 与 R7：文档收尾与最终审查</h3><p>啃完最复杂的 R5 之后，R6 负责文档收尾。</p><p>这里有个细节很重要：模型没有只写“能力已完成”，而是同步修正 README、api-mapping、python-ts-parity、known-gaps，让文档和代码状态保持一致，并明确标注 OceanBase 真实集成仍属后续 PR。</p><p>最后的最后，R7 站在评审者视角，复查那些“声称实现”的能力是否真有代码支撑、测试是否真覆盖、文档是否还有过时描述。最终给出 PASS，并建议进入 dashboard 人工验收。</p><p>这说明模型在复杂度提升后没有明显崩盘——它能从 API 层进入算法、存储、HTTP、Agent 控制器等多模块场景，并始终保持测试和文档闭环。</p><p>七轮跑下来，从最初的 baseline 记录到 R7 final 收官，总跨度大约 4 小时 37 分钟。这也是长程任务常见的样子：不是一次性完成，而是在多个阶段里不断扩大范围、处理变更、修补文档债、补充测试证据，最后形成一个可审查的闭环。这些过程记录，也是后面最终结果和交叉评审的依据。</p><h2 id="最终结果：漂亮数字背后的证据链"><a href="#最终结果：漂亮数字背后的证据链" class="headerlink" title="最终结果：漂亮数字背后的证据链"></a>最终结果：漂亮数字背后的证据链</h2><p><img src="/img/2026-06-29-glm-52-powermem-typescript-sdk/07.webp" alt="实测通过率与工程证据链总览" loading="lazy" decoding="async"></p><p>这次任务最终可验证的结果，详细来说包括：</p><ul><li><code>npm run type-check</code> 通过</li><li><code>npm test</code> 通过，结果是 649 passed &#x2F; 2 skipped &#x2F; 0 failed</li><li><code>npm run build</code> 通过</li><li><code>npm run lint</code> 通过，0 errors</li><li>upstream-powermem 的 git status 为空，说明 PowerMem Python 主仓库未被修改</li><li>candidate-powermem-ts 的最终 diff 显示 13 个已修改文件、12 个新增文件</li></ul><p>最终报告记录的关键功能状态包括：</p><ul><li>Memory 类公开方法对齐 38&#x2F;38</li><li>EbbinghausAlgorithm 核心方法 8&#x2F;8 对齐</li><li>HttpMemoryClient 10&#x2F;10 方法实现</li><li>parity tests 合计 189 个 case</li><li>API surface 完整度约 98%</li><li>真实实现占比约 92%，stub 约 8%</li></ul><p>这些数字背后都有据可查：日志、测试输出、diff、最终报告和观察日志，都能互相印证。</p><p><img src="/img/2026-06-29-glm-52-powermem-typescript-sdk/08.webp" alt="测试构建与差异检查结果截图" loading="lazy" decoding="async"></p><p>除了这些可验证数据，GLM-5.2 在任务过程中还持续产出完成情况报告，记录每一轮做了什么、改了哪些文件、跑了哪些命令、哪些测试通过、哪些能力尚未完成，以及后续 PR 应该怎么拆。这既是模型对自己工作的交付，也是后续交叉评审的素材基础。</p><h2 id="交叉评审：请-ChatGPT-5-5-来当裁判"><a href="#交叉评审：请-ChatGPT-5-5-来当裁判" class="headerlink" title="交叉评审：请 ChatGPT-5.5 来当裁判"></a>交叉评审：请 ChatGPT-5.5 来当裁判</h2><p>不过，让 GLM-5.2 自己出报告，总有种“既当运动员又当裁判”的味道。</p><p>于是我另外请出 ChatGPT-5.5 做了一次独立交叉评审——重新读取本地日志、最终报告等内容，再按独立评分标准重新打分。</p><p><img src="/img/2026-06-29-glm-52-powermem-typescript-sdk/09.webp" alt="ChatGPT 交叉评审任务完成度评分" loading="lazy" decoding="async"></p><p>最终的可视化报告里，呈现了总分、各评分维度、证据链、剩余风险、时间线和关键数据。</p><p><img src="/img/2026-06-29-glm-52-powermem-typescript-sdk/10.webp" alt="交叉评审对代码质量的分项评价" loading="lazy" decoding="async"></p><p><img src="/img/2026-06-29-glm-52-powermem-typescript-sdk/11.png" alt="交叉评审指出的剩余缺口清单" loading="lazy" decoding="async"></p><p>结果还挺意外——ChatGPT-5.5 按自己的评分标准重新打分后，给出的分数甚至比 GLM-5.2 自评还要高。</p><p>细看报告，分数高的原因在于后四轮把任务复杂度拉了上来：从核心 SDK parity 扩展到算法公式、存储抽象、HTTP client、Agent 权限控制，再到 README 和 examples 收尾，而最终验证仍然全绿。</p><p><img src="/img/2026-06-29-glm-52-powermem-typescript-sdk/12.png" alt="评审方对工程约束遵守情况的评价" loading="lazy" decoding="async"></p><p>但客观讲，这次任务执行仍然留有缺口。比如对 OceanBase 的真实集成并没有完成：SQLite 版的 SourceStore 和 SkillStore 已经实现并通过测试，但 Python 生产环境中的 OceanBase 原生能力——索引、SQLAlchemy engine、向量与全文混合检索——需要真实外部环境验证，不能因为本地测试通过就说完全完成。</p><p>再比如，部分 AgentMemory 高层 API 仍是 stub。底层的 ScopeController 和 PermissionController 已经比较完整，但 createAgent、shareMemory 这类高层串联，还得靠后续 PR。</p><p>又比如，ImportanceEvaluator 的 LLM 路径，以及 IntelligentMemoryManager 的部分高级方法，仍未完全对齐。</p><p>这些，报告里都如实列了出来。</p><p><img src="/img/2026-06-29-glm-52-powermem-typescript-sdk/13.png" alt="交叉评审结论与可复现建议" loading="lazy" decoding="async"></p><p>但它们并不影响整体结论：这次任务评价虽高，却也明确留有后续工作。</p><p>至此，整个评测任务结束。</p><p><img src="/img/2026-06-29-glm-52-powermem-typescript-sdk/14.png" alt="多模型交叉评审对比汇总表" loading="lazy" decoding="async"></p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><h3 id="一个意料之外的发现"><a href="#一个意料之外的发现" class="headerlink" title="一个意料之外的发现"></a>一个意料之外的发现</h3><p>这次 case，有一个挺意外的感受。</p><p>开始之前，我以为 PowerMem TypeScript SDK 因为近期更新不多，可能需要模型做大量重构和大型新增，才能追齐 Python 版本。</p><p>但真正上手后才发现， <strong>PowerMem TypeScript SDK 是一个相当完整的项目，几乎所有核心能力都已就位：Memory 类的 12 个核心 API 全部到位，配置系统、存储后端、Provider 工厂、艾宾浩斯衰减、CLI、HTTP server、Dashboard 框架都已有完整骨架，baseline 阶段就已经有 460 个测试用例。</strong></p><p>所以 GLM-5.2 在这次任务里实际写的代码量并不大，整个七个阶段真正复杂的改动，集中在 R5 的深水区模块。</p><p>换句话说，GLM-5.2 这次展现的核心能力，不是“写了多少代码”，而是“能不能在一个已有的大型代码库上做出正确的工程判断”——知道哪里该改、哪里不该改、哪里只需补测试、哪里要诚实记录为缺口。</p><p><img src="/img/2026-06-29-glm-52-powermem-typescript-sdk/15.png" alt="实测中意外发现的工程能力亮点" loading="lazy" decoding="async"></p><p>这何尝不是传统编程里，资深工程师和初级工程师的核心区别呢？初级工程师面对一个项目，倾向于直接动手改写；资深工程师则会先花时间读懂结构，然后只在该改的地方做最小改动。</p><p>GLM-5.2 这次的表现，更像后者 —— 资深工程师。</p><h3 id="落到-PowerMem-和-GLM-5-2-上"><a href="#落到-PowerMem-和-GLM-5-2-上" class="headerlink" title="落到 PowerMem 和 GLM-5.2 上"></a>落到 PowerMem 和 GLM-5.2 上</h3><p>从 PowerMem 这个项目本身来看，这次 case 也让我对它有了更深的认识。Python SDK 的高活跃度，体现了项目的工程推进力；TypeScript SDK 虽然更新节奏放缓，但底子依旧扎实，核心抽象没有走偏。一个能在停滞一段时间后仍被模型快速理解和扩展的代码库，本身就说明 PowerMem 早期的架构设计经得起时间检验。</p><p>从 GLM-5.2 这个模型来看，1M 上下文在跨仓库任务里的作用很明显。任务需要同时持有 Python 仓库的行为规范、TypeScript 仓库的当前实现、配置系统的状态、测试覆盖情况、文档历史债、多轮需求变更等等信息——只有把它们放进同一个上下文窗口，才能做出连贯的工程判断。这对国内做 Agent 应用的开发者来说，是一个相当实际的利好。</p><p>这次长程任务评测，也提供了一个值得借鉴的样本，对我而言是一次很有意思的经历。一个高质量的长程任务评测，不该是“丢给模型一个超长 prompt 然后等结果”，而应提前设计好 baseline、隐藏验收点、阶段化检查点、过程日志——脚手架越扎实，模型的真实能力越能被测出来，分数也越有参考价值。</p><p>总体来说，在这次 PowerMem 从 Python 到 TypeScript 的长程功能对齐任务中，GLM-5.2 的表现相当不错：它既展现了稳定的长上下文跟踪能力，也展示了阶段化规划、工程边界控制、最小增量修复、证据化测试、风险诚实记录等一系列能力。</p><p>当然，它并非毫无缺点，但能在多轮任务中持续保持目标、持续验证、持续记录风险，并最终交付一个可审查、可运行、可复盘的工程结果，已经很难得。长程任务评测，本身就是一门需要认真设计的工程：脚手架越扎实，模型的真实能力才越能被测出来。</p><p>这是我第一次认真地跑这么复杂的长程任务，把 baseline、过程截图、观察日志、每轮测试、最终报告、可视化评审都尽量记录下来。</p><p>总的来说，是一次非常有意思的体验。</p><p><img src="/img/2026-06-29-glm-52-powermem-typescript-sdk/16.png" alt="PowerMem 与 GLM-5.2 协作启示总结" loading="lazy" decoding="async"></p><h2 id="相关内容推荐"><a href="#相关内容推荐" class="headerlink" title="相关内容推荐"></a>相关内容推荐</h2><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ol><li>PowerMem Python SDK 仓库：<a href="https://github.com/oceanbase/powermem">https://github.com/oceanbase/powermem</a></li><li>PowerMem TypeScript SDK 仓库：<a href="https://github.com/ob-labs/powermem-ts">https://github.com/ob-labs/powermem-ts</a></li><li>智谱 GLM-5.2 模型 HuggingFace 开源地址：<a href="https://huggingface.co/zai-org/GLM-5.2">https://huggingface.co/zai-org/GLM-5.2</a></li></ol><p>了解更多</p><p>添加社区小助手，加入微信交流群~</p><p>PowerMem · 目录</p><p>作者提示: 个人观点，仅供参考</p><p>阅读原文</p>]]>
    </content>
    <id>https://ilongda.com/2026/2026-06-29-glm-52-powermem-typescript-sdk/</id>
    <link href="https://ilongda.com/2026/2026-06-29-glm-52-powermem-typescript-sdk/"/>
    <published>2026-06-29T14:44:08.000Z</published>
    <summary>GLM-5.2 长程任务实测：用大模型把 OceanBase PowerMem SDK 从 Python 功能对齐到 TypeScript，覆盖边界、评测、七轮迭代与交叉评审。</summary>
    <title>GLM-5.2 长程任务实测：把 PowerMem SDK 从 Python 对齐到 TypeScript</title>
    <updated>2026-06-29T14:44:08.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="企业案例" scheme="https://ilongda.com/categories/%E4%BC%81%E4%B8%9A%E6%A1%88%E4%BE%8B/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="分布式数据库" scheme="https://ilongda.com/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    <category term="金融科技" scheme="https://ilongda.com/tags/%E9%87%91%E8%9E%8D%E7%A7%91%E6%8A%80/"/>
    <category term="信也科技" scheme="https://ilongda.com/tags/%E4%BF%A1%E4%B9%9F%E7%A7%91%E6%8A%80/"/>
    <category term="智能风控" scheme="https://ilongda.com/tags/%E6%99%BA%E8%83%BD%E9%A3%8E%E6%8E%A7/"/>
    <category term="AI 数据底座" scheme="https://ilongda.com/tags/AI-%E6%95%B0%E6%8D%AE%E5%BA%95%E5%BA%A7/"/>
    <category term="AIOps" scheme="https://ilongda.com/tags/AIOps/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"信也科技 OceanBase 实践：风控核心升级与 AI 数据底座","description":"信也科技用 OceanBase 升级风控核心库：摆脱 MySQL 分库分表在一致性、高可用与扩容上的瓶颈，存储压缩约 67%，并探索 AI 数据底座与 AIOps。","image":"https://ilongda.com/img/2026-06-25-xinye-technology-oceanbase-practice/01.webp","wordCount":5180,"datePublished":"2026-06-25T14:44:08.000Z","dateModified":"2026-06-25T14:44:08.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-06-25-xinye-technology-oceanbase-practice/"},"url":"https://ilongda.com/2026/2026-06-25-xinye-technology-oceanbase-practice/","inLanguage":"zh-CN","keywords":["OceanBase","分布式数据库","金融科技","信也科技","智能风控","AI 数据底座","AIOps"],"articleSection":["企业案例"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"企业案例","item":"https://ilongda.com/categories/企业案例/"},{"@type":"ListItem","position":3,"name":"信也科技 OceanBase 实践：风控核心升级与 AI 数据底座","item":"https://ilongda.com/2026/2026-06-25-xinye-technology-oceanbase-practice/"}]}</script><blockquote><p>从风控核心库，到 AI 数据底座与 AIOps，OceanBase 在信也科技的演进里角色越来越重。</p></blockquote><p>信也科技（纽交所：FINV）是上市金融科技集团，监管要求严，对数据合规、隐私与安全几乎零容忍。业务上至少要同时满足三点：</p><ul><li><strong>数据一致性</strong>：全球资金交易场景下，主备切换或故障恢复都不能丢数。</li><li><strong>高可用</strong>：机房级故障时，业务要能秒级接管。</li><li><strong>弹性扩容</strong>：多市场突发洪峰时，底层库要能在线平滑扩容。</li></ul><p>依托海量数据与 AI，信也打造了智能风控体系，业务已延伸到东南亚、澳洲等地，也因此面对跨地域、多时区、高并发的技术压力。下面按「痛点 → 选型 → 落地 → 规划」说明他们如何用 OceanBase 破局。</p><span id="more"></span><h2 id="历史架构痛点：传统-MySQL-分库分表的技术挑战"><a href="#历史架构痛点：传统-MySQL-分库分表的技术挑战" class="headerlink" title="历史架构痛点：传统 MySQL 分库分表的技术挑战"></a>历史架构痛点：传统 MySQL 分库分表的技术挑战</h2><p>信也许多业务最初使用 MySQL 分库分表方案支撑，在该方案中，以下四个痛点对 DBA 而言应该并不陌生。</p><p><strong>第一，研发效能黑洞，跨库查询与分表治理问题。</strong> 我们内部有一套面向研发的自动化平台，但当分表数量较多时，排查问题需要做跨分片聚合查询，往往需要 DBA 协助，流程比较繁琐。而且，大部分业务代码被迫适配中间件逻辑，严重拖累敏捷迭代的交付节奏。</p><p><strong>第二，扩容如履薄冰，极高运维风险。</strong> 一方面随着业务持续增长，分库分表方案最终必然面临扩容需求。长期来看，分片维护等工作相当枯燥，且存在扩容窗口期的风险。另一方面，面对突发流量洪峰，分库分表后的数据 Rebalance 耗时极长。操作极其繁琐，而且极易引发线上业务剧烈抖动，扩容变高危。</p><p><strong>第三，成本指数膨胀，单机容量触顶。</strong> 原有的 MySQL 系统容量和压缩能力有限，随着海量历史冷数据堆积， SSD 存储账单呈指数级飙升，同时闪迪（ SanDisk ）、美光（ Micron ）等存储厂商的股价上涨也反映出内存和存储硬件的涨价趋势，给企业成本带来较大压力。</p><p><strong>第四，敏捷迭代绊脚石：DDL 变更阻塞。</strong> 成百上千个数据分片形成了 “ 管理孤岛 ” ，导致我们对分库分表做表结构变更（如加字段、改结构等）不仅相当麻烦，而且耗时数周，很难做全局统一管理。目前主流方案是 GH-OST 做在线 DDL ，但其在切换时有一个短暂的锁表动作，即使放在业务低峰期，仍可能导致线上事故。我们曾采用的一种改进方案是：在高峰期暂停 DDL 操作，等窗口期再恢复。但暂停期间会产生大量 vlog ，采用 MySQL 原生方案时可能导致程序卡死。后来我们调整为： DDL 仅在低峰期执行，过了窗口期后持续等待下一周期，以此规避风险。</p><h2 id="分布式数据库选型历程：从-TiDB-到-OceanBase"><a href="#分布式数据库选型历程：从-TiDB-到-OceanBase" class="headerlink" title="分布式数据库选型历程：从 TiDB 到 OceanBase"></a>分布式数据库选型历程：从 TiDB 到 OceanBase</h2><p>我们最初并没有主动考虑数据库选型的问题。随着数据不断膨胀， MySQL 分库分表的方案反复面临扩容和成本挑战。当时的解决思路之一是将冷数据迁移到成本更低的存储系统。</p><p>在选型早期，我们调研过 TiDB ，因为一些原因最后放弃使用。后来了解到 TiDB 的 TiKV 方案，但实际使用效果并不理想。恰逢 OceanBase 开源，我们将其纳入调研范围，使用后发现效果不错，与我们内部的自动化平台融合度较高。</p><p>选择 OceanBase 主要基于三点：</p><ul><li><strong>存储成本降低。</strong> OceanBase 采用与 MySQL 相同的 LSM-Tree 算法，但在压缩层面做了深度优化，显著降低了存储成本。</li><li><strong>弹性扩容便捷。</strong> 作为分布式数据库，当归档集群资源不足时，可以平滑地增加几台 OBServer 节点即可解决问题，操作简单。</li><li><strong>金融级高可用方案。</strong> 作为互联网金融企业，对数据一致性要求极高，OceanBase 的金融级高可用架构满足这一需求。</li></ul><h2 id="如何推动研发团队使用-OceanBase"><a href="#如何推动研发团队使用-OceanBase" class="headerlink" title="如何推动研发团队使用 OceanBase"></a>如何推动研发团队使用 OceanBase</h2><p>选定产品后，推动研发团队使用是另一大挑战。研发人员没有业务诉求或上级压力时，通常不会主动更换正在稳定运行的 MySQL 方案。如何保证迁移后的性能表现，是打消顾虑的关键。</p><p>OceanBase 提供了不错的配套工具：</p><ul><li>迁移评估工具OMA（OceanBase Migration Assessment）可以提供精准的语法兼容性评估。基于全链路压测思维，制定详尽的割接 SOP。在迁移前，我们可以利用 OMA 抓取源库真实业务流量并在目标库进行仿真回放，预知高并发下的性能风险与锁冲突。</li><li>迁移服务OMS（OceanBase Migration Service）配套完善，支持实时同步和反向同步。这样一来，建立稳固的全量 + 增量实时数据同步链路，在割接窗口期，配合数据实时一致性校验，确保新旧库数据绝对平齐。割接的最强底气在于开启从 OB 到源库的逆向同步链路，并保持老库数据实时鲜活，为随时可能的紧急回滚提供待命的底座。</li></ul><p><strong>我们主要采用两种方案</strong> ：一是通过 OMS 同步后在低峰期做割接；二是通过研发控制双写，这是目前使用较多的方案。双写方案回滚方便，可分别控制读和写，通过灰度流量验证，一旦灰度期间监控发现异常，无需重启应用，直接通过配置中心一键拉回流量，实现秒级无损切回， <strong>真正做到进可攻，退可守。</strong></p><h2 id="实战破局：从核心业务场景落地到自动化运维"><a href="#实战破局：从核心业务场景落地到自动化运维" class="headerlink" title="实战破局：从核心业务场景落地到自动化运维"></a>实战破局：从核心业务场景落地到自动化运维</h2><h3 id="技术升级，实现降本增效、高可用、高可靠"><a href="#技术升级，实现降本增效、高可用、高可靠" class="headerlink" title="技术升级，实现降本增效、高可用、高可靠"></a>技术升级，实现降本增效、高可用、高可靠</h3><h4 id="1-极致降本：LSM-Tree-引擎对海量数据的存储重塑"><a href="#1-极致降本：LSM-Tree-引擎对海量数据的存储重塑" class="headerlink" title="1. 极致降本：LSM-Tree 引擎对海量数据的存储重塑"></a>1. 极致降本：LSM-Tree 引擎对海量数据的存储重塑</h4><p>使用 OceanBase 后，告别了传统 MySQL B+ 树的页分裂与空间碎片，采用 LSM-Tree 存储引擎将随机写转化为顺序追加写，实现极致的写入性能与双层数据压缩。 <strong>89TB 的数据被压缩至 29TB，存储空间节约约 67%。</strong></p><p><strong>业务场景一：历史存量业务（冷热分离）。</strong> 存量数据的日常访问频次极低且无法下线，占用着大量昂贵的 SSD 存储资源。我们考虑将部分数据迁移到 OceanBase ，利用其极致压缩能力将海量数据在线归档。在不影响偶尔查询的前提下，大幅削减硬件成本，实现 “ 冷热数据 ” 高效治理。</p><p><strong>业务场景二：营销投放业务（高频并发）。</strong> 这是一个典型的写密集型业务，流水产生极快，且因合规与对账要求，保留周期极长，极易引发容量危机。在 MySQL 分表方案中，每台机器配置两块数据盘，使用压力经常达到 85% 。</p><p>DBA 需要频繁做归档和表空间收缩，运维压力很大。 OceanBase 采用 LSM-Tree 架构，增量数据写入后通过定期合并完成空间回收，无需手动收缩，整体运维压力大幅降低。值得一提的是 OceanBase “ 内存追加写 ” 特性完美消除高频写入的 I&#x2F;O 瓶颈，底层高压缩比彻底瓦解长期保留的容量焦虑，让业务敢于记录详尽流水。</p><h4 id="2-同城双活架构与极致高可用实践"><a href="#2-同城双活架构与极致高可用实践" class="headerlink" title="2. 同城双活架构与极致高可用实践"></a>2. 同城双活架构与极致高可用实践</h4><p><strong>业务场景三：同城双活演练。</strong> 我们每年进行两次同城双活演练，两个机房之间将流量和数据库全部切换。</p><p><img src="/img/2026-06-25-xinye-technology-oceanbase-practice/01.webp" alt="信也科技同城双活与租户级容灾架构" decoding="async"></p><blockquote><p>备租户 (Standby Tenant) 容灾体系。打破传统主备架构局限，基于底层 Redo Log 异步&#x2F;强同步传输，实现跨机房的“租户级”物理容灾。无论遭遇多极端的机房级故障，坚守底层数据零丢失的绝对红线。</p><p>“切浦江”常态化双活演练。告别纸上谈兵，将主备角色平滑互换演练融入日常运维。结合业务流量管控与紧急回滚预案，验证全链路可靠性，确保极端场景下核心交易流量接管无感丝滑。</p></blockquote><p>在演练过程中， MySQL 及其他关键数据库会出现抖动，对业务有一定影响。公司管理层也在关注如何将切换影响降到更低、更平滑。 OceanBase 的架构天然适配这一需求，通过 OBProxy 和 Service 层访问，切换更加丝滑。但需要注意的是，早期版本（如 V4.2.0.5 ）在 OBProxy 层面不够成熟。我们曾在大数据抽数场景中遇到问题：分布式架构下只能通过 OBProxy 访问，但抽数时某些 SQL 执行计划不佳，影响线上业务。后来了解到当时使用的版本存在一个 Bug ，导致主集群卡死，只能重启。对于核心业务，这种影响非常大。因此， <strong>如果线上核心业务使用 OceanBase，强烈建议配置 OBProxy。</strong></p><h4 id="3-资源池化与多租户架构：打破物理孤岛，实现极致弹性"><a href="#3-资源池化与多租户架构：打破物理孤岛，实现极致弹性" class="headerlink" title="3. 资源池化与多租户架构：打破物理孤岛，实现极致弹性"></a>3. 资源池化与多租户架构：打破物理孤岛，实现极致弹性</h4><p><strong>业务场景四：多租户资源隔离。</strong> 很多 DBA 在银行类金融场景下按需开机器、部署交付即可，但需要思考成本与交付的平衡。当前的痛点是：研发强调业务重要，要求独立资源。我们目前采用物理机部署，对于业务压力并不高的 “ 核心 ” 业务，只能给三副本 5TB 存储，造成资源浪费。同时，多条业务线部署在同一组物理机上，某个业务线的慢查询接口可能影响其他业务。</p><p>OceanBase 的多租户能力可以解决这一问题。</p><ul><li>告别物理机孤岛：打破传统架构按“峰值”预占硬件的痛点，实现资源池化管理。按需动态分配 CPU&#x2F;内存，彻底消除物理机闲置造成的成本浪费。</li><li>租户级物理硬隔离：通过底层的 CPU 绑核与 IOPS 阈值控制，实现租户间的物理级硬隔离。确保营销等高 I&#x2F;O 业务突发打满时，核心交易链路绝对不受“噪音效应”干扰。</li><li>分钟级动态扩缩容：以 Unit 为最小迁移单位，实现业务零感知的在线扩容与缩容。轻松应对跨地域、多时区的突发业务洪峰与节假日高并发。<br><img src="/img/2026-06-25-xinye-technology-oceanbase-practice/02.webp" alt="OceanBase 多租户资源池化架构示意" loading="lazy" decoding="async"></li></ul><p>使用 OceanBase 后，<strong>整体资源利用率提升约 40%，新业务节点部署周期缩短约 90%</strong>。早期采购还有一条经验：CPU 买少了、存储配大了，CPU 打满后磁盘还空着。<strong>建议采购时选择高 CPU 规格（如 96C），与内存配比大约 1:2。</strong></p><h3 id="自动化运维与生态打通"><a href="#自动化运维与生态打通" class="headerlink" title="自动化运维与生态打通"></a>自动化运维与生态打通</h3><p>将新数据库纳入既有运维体系是一个常见问题。信也科技数据库种类较多，包括 MySQL 、 Redis 、 OceanBase 、 Elasticsearch 等多种关系型和非关系型数据库。我们有一套面向研发和 DBA 的管理平台，已将 OceanBase 的自动化流程纳入其中。</p><p>在 SQL 变更方面，我们采用双重验证机制：通过 OCP 平台和内部工具进行交叉验证，确认无误后直接执行；如有风险则走工单审批流程。但工单执行也存在问题 —— 大表改表操作耗时非常长，业务方能否等待是一个问题，同时改表过程中本身存在锁开销等风险。我们的做法是安排在每天 21 点执行，如果到早上窗口期结束仍未完成，则进行抑制操作，暂停 DDL 避免影响业务。</p><p>在开发平台方面，我们参考了阿里云的建表体验，将开发规范内置到平台中，研发人员无需关心索引、表备注、字符集等规范细节，只需填写表名、备注和字段类型，提交后平台自动处理。</p><p><img src="/img/2026-06-25-xinye-technology-oceanbase-practice/03.webp" alt="OceanBase 自动化运维与生态打通" loading="lazy" decoding="async"></p><p>一个重要的经验教训是：早期未配置 OBProxy 时，在大数据抽数场景中，复杂查询任务直连主租户 (Primary Tenant) 。凌晨抽数高峰期引发大面积全表扫描，导致主库 CPU 飙升、 I&#x2F;O 触及瓶颈，严重威胁核心交易链路安全。后来我们将所有离线抽数、报表分析流量无缝引流至备租户 (Standby Tenant) ，彻底实现底层读写分离，物理隔离 OLAP 与 OLTP ，主库性能稳如磐石。</p><h3 id="一次线上故障与复盘"><a href="#一次线上故障与复盘" class="headerlink" title="一次线上故障与复盘"></a>一次线上故障与复盘</h3><p>近期发生了一次线上故障，处理经验供大家参考。背景是研发同学反馈线上出现问题，排查发现某条 SQL 虽已有索引，但未按索引执行，于是进行了执行计划绑定操作。</p><p>执行计划绑定存在一个隐患： OCP 平台上展示的执行计划可能有多个（如 A 、 B 、 C 三个），操作时平台会将三个全部标记为绑定状态，但底层数据库实际上只绑定了其中一个。当时操作人员看到平台显示绑定了三个，认为是误操作，立即取消了绑定。此时执行计划已落入全表扫描路径，数据库压力瞬间飙升，业务出现 “ 雪崩 ” 。</p><p>我们的应急处理过程是：</p><ul><li>第一步解绑，但解绑后并未恢复，因为错误的执行计划已产生，全部走全表扫描。</li><li>第二步做限流，也未能起效。</li><li>第三步切备库，切到备库后，旧连接上的请求仍在原库执行，新连接到备库后逐步恢复。</li></ul><p>对此，我们复盘后得出几个要点：</p><ul><li><strong>深入理解底层实现</strong> ：不要盲目相信 OCP 平台上的显示信息，需要到数据库底层查看对应表，确认是否真正绑定了目标执行计划。</li><li><strong>完善上线前的 review 机制</strong> ：在测试环节识别有问题的接口，拦截问题代码发布到线上。</li><li><strong>建立快速止血能力</strong> ：在平台上提供快速 kill 会话的能力，降低故障影响时长。</li></ul><p>同时，也总结了两个DBA避坑硬核心法。一是 <strong>拒绝盲信 UI 工具</strong> ：任何工具都有黑盒盲区。执行计划绑定后，必须切回黑屏查询 GV$OB_SQL_OUTLINE 确认真实的物理执行路径；二是 <strong>敬畏数据，硬核复核</strong> ：挑选历史计划时，绝不可单看”平均耗时最短”这个单一维度，谨防极端极少样本导致的性能假象。</p><h2 id="未来规划：探索一体化向量底座与全自动运维"><a href="#未来规划：探索一体化向量底座与全自动运维" class="headerlink" title="未来规划：探索一体化向量底座与全自动运维"></a>未来规划：探索一体化向量底座与全自动运维</h2><p>我们在 2024 年开始使用 OceanBase ，从特定场景到核心业务依次上线，基于其在这两年的稳定表现，我们计划持续扩大 OceanBase 的使用范围。例如，将部分 MongoDB 支持的业务场景迁移到 OceanBase ，以降低数据库成本。</p><p>未来，我们还将基于 OceanBase 优化 AIOps 、重塑归档体系、演进一体化向量底座。</p><h4 id="1-从手工救火到-AIOps-智能自愈体系的蜕变"><a href="#1-从手工救火到-AIOps-智能自愈体系的蜕变" class="headerlink" title="1.从手工救火到 AIOps 智能自愈体系的蜕变"></a>1.从手工救火到 AIOps 智能自愈体系的蜕变</h4><p>如何将 OceanBase 与自动化运维体系及 AIOps 深度结合，实现数据库问题的自动判断甚至自愈？这是我们要解决的问题，目前已有巡检系统，可以检测隐患与风险，但治理工作仍依赖 DBA 人工处理。未来，我们希望实现：巡检发现问题后自动治理，以及报警触发后自动分析并给出执行路径，经 DBA 确认后即可执行。这对缩短故障处理时间、提升 MTTR （平均修复时间）指标至关重要，对 DBA 完成 SLA （如 9999 或 99999 ）的考核也有直接帮助。</p><p>为此，我们将通过三方面构建全链路治理体系。</p><ul><li>防线左移：前置 AI 质量拦截。自动化 SQL Review 平台引入 AI 辅助代码审核，在研发流水线中精准识别并提前掐断易引发“全表扫描”的劣质计划。</li><li>极速响应：智能 RCA 与自动止血。打破传统堆砌告警模式，构建基于监控日志的智能根因分析 (RCA)。实现“诊断-&gt;止血”联动，将人工排查时间从分钟级压缩至秒级。</li><li>底盘稳固：演练与黑屏 SOP。沉淀极端场景下的应急经验，针对复杂故障强化团队黑屏排雷与实操能力，知其然更知其所以然。</li></ul><p>与此同时，探索基于大语言模型 Agent 的数据库常态化巡检，结合历史负载特征，实现数据库底层参数的动态自适应调优。逐步落地智能化故障自愈机制，从 “ 被动响应 ” 向 “ 主动防御 ” 演进，极大降低业务连续性对人工经验的依赖。</p><h4 id="2-重塑归档体系：从底座演进到全链路自动化治理"><a href="#2-重塑归档体系：从底座演进到全链路自动化治理" class="headerlink" title="2.重塑归档体系：从底座演进到全链路自动化治理"></a>2.重塑归档体系：从底座演进到全链路自动化治理</h4><p>冷热数据分离是线上频繁使用的场景，数据分离后仍需保留以满足审计或业务需求。以往，我们的做法非常笨拙：通过 rename 方式定期清理过期数据并重建新表。使用 OceanBase 后可以按分区进行添加和删除，操作非常丝滑。还可以按时间要求定时执行归档，支持不同租户或实例串行归档，也提供并发数和优先级支持。考虑到我们在东南亚（菲律宾、印尼）、澳洲、非洲等地区都有业务， OceanBase 还支持归档时配置不同存储介质，满足当地数据驻留的合规要求。</p><p>最初我们使用 InnoDB 处理数据归档，引发主库 CPU 资源争抢，性能与容量难以兼得；后来引入 TiDB ，带来了高昂硬件成本与复杂运维负担；现在使用 OceanBase 彻底统一在线交易与历史归档技术栈，自动化维护分区全生命周期，带来了海量历史数据存储成本骤降 70% 、主租户核心库查询性能跃升 30% 的效果。</p><h4 id="3-AI-Native：一体化向量底座与业务展望"><a href="#3-AI-Native：一体化向量底座与业务展望" class="headerlink" title="3.AI Native：一体化向量底座与业务展望"></a>3.AI Native：一体化向量底座与业务展望</h4><p>如今，信也内部推动 “ All in AI ” ， DBA 团队的相关后台系统已 100% 使用 AI 编写， AI 平台和开发团队将向量数据库作为存储底座。</p><p>在 AI 趋势与业务需求的双重压力下，我们计划探索将 OceanBase 作为一体化向量底座的效果，比如在海量数据场景下替代 PostgreSQL ，以及在智能风控场景使用 OceanBase 的向量相似度匹配，精准捕捉跨业务线的隐秘欺诈团伙，提升风控模型的召回率与时效性。</p><p>OceanBase 向量功能迭代迅速，在 4.3.3 GA 版本推出 SQL + 向量一体化检索架构，无需异构同步，确保数据实时强一致与金融级可靠性。如今已支持 HNSW 、 IVFFlat 等主流索引，可承载 16000 维超高维检索，满足大模型长文境需求，据官方透露，后续版本的向量能力将有更大提升。对于我们来说， OceanBase 最大的优势在于一个数据库同时处理关系型、 KV 及向量数据，极大降低 AI 原生应用的开发与运维复杂度。</p><p>AI 大势所趋，对 DBA 提出了新的技能要求。在与阿里云团队交流时，了解到他们通过海量故障数据构建知识库并存储在向量数据库中，当故障发生时通过向量搜索匹配标准 SOP，再分发给相应人员处理。所以我们将构建基于 RAG 的运维知识库，实现故障特征的秒级检索与自动化处置。同时，依托OceanBase的一体化底座简化技术栈，降低 AI 落地门槛，实现从“数据治理”向“AI 资产赋能”的跨越。</p><p><img src="/img/2026-06-25-xinye-technology-oceanbase-practice/04.webp" alt="一体化向量底座支撑 AI 业务示意" loading="lazy" decoding="async"></p><p>添加社区小助手，加入微信交流群~</p><p>用户案例 · 目录</p>]]>
    </content>
    <id>https://ilongda.com/2026/2026-06-25-xinye-technology-oceanbase-practice/</id>
    <link href="https://ilongda.com/2026/2026-06-25-xinye-technology-oceanbase-practice/"/>
    <published>2026-06-25T14:44:08.000Z</published>
    <summary>信也科技用 OceanBase 升级风控核心库：摆脱 MySQL 分库分表在一致性、高可用与扩容上的瓶颈，存储压缩约 67%，并探索 AI 数据底座与 AIOps。</summary>
    <title>信也科技 OceanBase 实践：风控核心升级与 AI 数据底座</title>
    <updated>2026-06-25T14:44:08.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="AI &amp; 应用" scheme="https://ilongda.com/categories/AI-%E5%BA%94%E7%94%A8/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="seekdb" scheme="https://ilongda.com/tags/seekdb/"/>
    <category term="Python" scheme="https://ilongda.com/tags/Python/"/>
    <category term="世界杯预测" scheme="https://ilongda.com/tags/%E4%B8%96%E7%95%8C%E6%9D%AF%E9%A2%84%E6%B5%8B/"/>
    <category term="数据建模" scheme="https://ilongda.com/tags/%E6%95%B0%E6%8D%AE%E5%BB%BA%E6%A8%A1/"/>
    <category term="概率模拟" scheme="https://ilongda.com/tags/%E6%A6%82%E7%8E%87%E6%A8%A1%E6%8B%9F/"/>
    <category term="AI Native" scheme="https://ilongda.com/tags/AI-Native/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"用 seekdb 预测 2026 世界杯冠军：从数据建模到概率模拟","description":"用 OceanBase seekdb 建模 2026 世界杯：Elo 与泊松分布生成赛果，蒙特卡洛模拟夺冠概率，完整展示 AI Native 数据分析实践。","image":"https://ilongda.com/img/2026-06-22-seekdb-world-cup-prediction/01.webp","wordCount":11887,"datePublished":"2026-06-22T14:44:09.000Z","dateModified":"2026-06-22T14:44:09.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-06-22-seekdb-world-cup-prediction/"},"url":"https://ilongda.com/2026/2026-06-22-seekdb-world-cup-prediction/","inLanguage":"zh-CN","keywords":["OceanBase","seekdb","Python","世界杯预测","数据建模","概率模拟","AI Native"],"articleSection":["AI & 应用"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"AI & 应用","item":"https://ilongda.com/categories/AI-应用/"},{"@type":"ListItem","position":3,"name":"用 seekdb 预测 2026 世界杯冠军：从数据建模到概率模拟","item":"https://ilongda.com/2026/2026-06-22-seekdb-world-cup-prediction/"}]}</script><blockquote><p>🚀 想自己跑一遍模拟？先把 <a href="https://github.com/oceanbase/seekdb">seekdb</a> 装起来——轻量 AI Native 数据库，关系表 + SQL + 存储过程就能把世界杯“踢”一千遍。</p></blockquote><h2 id="楔子"><a href="#楔子" class="headerlink" title="楔子"></a>楔子</h2><p>2026 年世界杯首次扩军到 48 支球队，赛程变成 12 个小组、104 场比赛。对预测来说，难点不只是球队变多，而是路径组合变多：小组第三也可能晋级，淘汰赛对阵还会受小组排名影响，冠军预测难度近似指数上升。</p><p><img src="/img/2026-06-22-seekdb-world-cup-prediction/01.webp" alt="2026 世界杯扩军后的预测难度示意" decoding="async"></p><p>很多大模型厂商也在预测世界杯结果，但流程往往是黑盒，读者只能看到结论、看不到方法。本文换一种做法：不直接甩出“冠军是谁”，而是把预测过程摊开——数据从哪来、比赛怎么模拟、概率怎么统计。</p><p>我们会在轻量 AI Native 数据库 seekdb 里，搭一套从数据建模到概率模拟的完整流程：用历史比赛数据生成单场结果，重复模拟整届世界杯，再统计每支球队夺冠频率。既知其然，也知其所以然。</p><p><img src="/img/2026-06-22-seekdb-world-cup-prediction/02.png" alt="seekdb 世界杯冠军预测完整流程" loading="lazy" decoding="async"></p><span id="more"></span><p>欢迎对照自己的判断，看看 seekdb 模拟结果是否合拍。也欢迎关注 OceanBase 社区公众号「老纪的技术唠嗑局」，我们会持续更新 AI 与 Data 相关技术内容。</p><p>这套流程很适合放在 seekdb：结构化数据进关系表，中间状态用 SQL 管理，重复模拟交给存储过程。</p><p><img src="/img/2026-06-22-seekdb-world-cup-prediction/03.webp" alt="蒙特卡洛模拟得到的冠军概率分布" loading="lazy" decoding="async"></p><h2 id="零、先看预测结果"><a href="#零、先看预测结果" class="headerlink" title="零、先看预测结果"></a>零、先看预测结果</h2><p>我在 seekdb 中模拟举办了 1000 次 2026 美加墨世界杯，各支球队获取冠军的次数和夺冠概率数据如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">obclient(root@fifa2026)[world_cup]&gt; CALL sp_simulate_worldcup(1000, &#x27;champion_probs_1k_verify&#x27;);</span><br><span class="line">Query OK, 0 rows affected</span><br><span class="line"></span><br><span class="line">obclient(root@fifa2026)[world_cup]&gt; select team_name, champion_prob, champion_count</span><br><span class="line">    -&gt; from champion_probs_1k_verify</span><br><span class="line">    -&gt; orderby champion_prob desc;</span><br><span class="line">+----------------+---------------+----------------+</span><br><span class="line">| team_name      | champion_prob | champion_count |</span><br><span class="line">+----------------+---------------+----------------+</span><br><span class="line">| Spain          |        0.2090 |            209 |</span><br><span class="line">| Argentina      |        0.1300 |            130 |</span><br><span class="line">| Brazil         |        0.1140 |            114 |</span><br><span class="line">| France         |        0.1030 |            103 |</span><br><span class="line">| Netherlands    |        0.0500 |             50 |</span><br><span class="line">| Colombia       |        0.0500 |             50 |</span><br><span class="line">| Germany        |        0.0450 |             45 |</span><br><span class="line">| England        |        0.0440 |             44 |</span><br><span class="line">| Portugal       |        0.0410 |             41 |</span><br><span class="line">| Ecuador        |        0.0380 |             38 |</span><br><span class="line">| Mexico         |        0.0330 |             33 |</span><br><span class="line">| Morocco        |        0.0270 |             27 |</span><br><span class="line">| Japan          |        0.0260 |             26 |</span><br><span class="line">| Uruguay        |        0.0200 |             20 |</span><br><span class="line">| Belgium        |        0.0190 |             19 |</span><br><span class="line">| Croatia        |        0.0120 |             12 |</span><br><span class="line">| United States  |        0.0110 |             11 |</span><br><span class="line">| Korea Republic |        0.0060 |              6 |</span><br><span class="line">| Australia      |        0.0050 |              5 |</span><br><span class="line">| Switzerland    |        0.0040 |              4 |</span><br><span class="line">| Czech Republic |        0.0030 |              3 |</span><br><span class="line">| Canada         |        0.0030 |              3 |</span><br><span class="line">| Senegal        |        0.0030 |              3 |</span><br><span class="line">| Turkey         |        0.0020 |              2 |</span><br><span class="line">| Iran           |        0.0010 |              1 |</span><br><span class="line">| Norway         |        0.0010 |              1 |</span><br><span class="line">+----------------+---------------+----------------+</span><br></pre></td></tr></table></figure><p>在这次 1000 次模拟中，西班牙夺冠 209 次，概率 20.9%；阿根廷夺冠 130 次，概率 13.0%；巴西夺冠 114 次，概率 11.4%；法国夺冠 103 次，概率 10.3%。荷兰、德国、英格兰、葡萄牙、哥伦比亚处于第二梯队。</p><p>小编突然想起，小学班主任曾经在 2002 年韩日世界杯期间，给我们讲过的一个笑话。</p><p>印象中是说：上帝来看韩日世界杯。</p><p>日本球迷问上帝：“我们日本什么时候能拿一次世界杯？”</p><p>上帝说：“100 年以后吧。”</p><p>日本球迷哭着说：“那我肯定看不到了……”</p><p>韩国球迷问上帝：“我们韩国什么时候能拿一次世界杯？”</p><p>上帝说：“500 年以后吧。”</p><p>韩国球迷哭着说：“那我肯定看不到了……”</p><p>中国球迷问上帝：“我们中国什么时候能拿一次世界杯？”</p><p>上帝哭着说：“那我肯定看不到了……”</p><p>当时因为年纪太小，全班同学听完之后，都不明所以。老师无奈，只简单解释了一句“上帝也是有寿命的”，就开始讲课了。</p><p>根据上面的模拟结果，日本夺冠概率为 2.6%，约等于平均 154 年能夺冠一次；韩国夺冠概率为 0.6%，约等于平均 667 年能夺冠一次。</p><p>seekdb 的这两个模拟结果，居然跟上帝说的都差不多……</p><p><img src="/img/2026-06-22-seekdb-world-cup-prediction/04.webp" alt="1000 次模拟后各国夺冠概率排名" loading="lazy" decoding="async"></p><p>闲言少叙，我们也要开始讲课了，下面先从预测方法讲起。</p><h2 id="一、预测办法：小组赛比分模拟-淘汰赛胜率抽样-蒙特卡洛"><a href="#一、预测办法：小组赛比分模拟-淘汰赛胜率抽样-蒙特卡洛" class="headerlink" title="一、预测办法：小组赛比分模拟 + 淘汰赛胜率抽样 + 蒙特卡洛"></a>一、预测办法：小组赛比分模拟 + 淘汰赛胜率抽样 + 蒙特卡洛</h2><p><img src="/img/2026-06-22-seekdb-world-cup-prediction/05.webp" alt="小组赛泊松模拟与淘汰赛 Elo 抽样" loading="lazy" decoding="async"></p><p>这版实现采用分阶段模型：小组赛用泊松分布生成比分，淘汰赛用 Elo 胜率直接抽样决定胜者，用蒙特卡洛方法负责重复执行整届赛事流程。</p><p>先补两句背景：泊松分布常用于描述一段固定时间或空间内某类事件发生的次数，适合建模“90 分钟内进几个球”这类低频计数问题；蒙特卡洛方法则是通过大量随机抽样逼近概率结果，适合把“不确定的一场比赛”扩展成“多次模拟后的概率分布”。</p><h3 id="1-Elo-评分体系：用于淘汰赛胜率抽样"><a href="#1-Elo-评分体系：用于淘汰赛胜率抽样" class="headerlink" title="1. Elo 评分体系：用于淘汰赛胜率抽样"></a>1. Elo 评分体系：用于淘汰赛胜率抽样</h3><p><img src="/img/2026-06-22-seekdb-world-cup-prediction/06.webp" alt="Elo 评分体系用于淘汰赛胜率计算" loading="lazy" decoding="async"></p><p>Elo 是一种动态衡量球队相对实力的方法。每支球队根据历史比赛结果获得一个分数，赢强队加分多，输弱队减分多。我在 OceanBase seekdb 的表中为每支球队存储了截至 2026 年 6 月的 Elo 评分。在模拟任意一场比赛时，我们通过 Elo 分差计算双方的预期胜率：</p><p><code>主队胜率 = 1/(1+10^((客队 Elo - 主队 Elo - 主场优势)/400))</code> 。</p><p>在本文的 SQL 实现中，Elo 主要用于淘汰赛阶段。为了让流程保持清晰，淘汰赛不再生成具体比分，而是根据双方 Elo 差值计算胜率，并用随机抽样决定晋级球队。</p><h3 id="2-泊松分布：用于小组赛生成随机比分"><a href="#2-泊松分布：用于小组赛生成随机比分" class="headerlink" title="2. 泊松分布：用于小组赛生成随机比分"></a>2. 泊松分布：用于小组赛生成随机比分</h3><p><img src="/img/2026-06-22-seekdb-world-cup-prediction/07.webp" alt="泊松分布生成小组赛随机比分示意" loading="lazy" decoding="async"></p><p>足球比赛进球数是典型的泊松事件，低发生率、独立、均值等于方差。我们假设每支球队在比赛中的预期进球数（λ）由以下公式决定：</p><p><code>λ = 赛事平均进球 × 进攻强度 × 对手防守强度 × 主场优势系数</code> 。</p><p>其中，进攻强度和防守强度来自球队近三年的场均进球和场均失球数据，并与整个赛事的平均水平进行比较。主场优势系数仅为东道主在 <code>team1_id</code> 位置时生效（设为 1.25），其余均为 1.0。然后，从泊松分布中随机抽样得到主客队进球数，从而产生一场小组赛的随机比分。这种方法天然包含了爆冷的可能，弱队一旦抽到大于 λ 的进球数，就能击败强队。</p><h3 id="3-蒙特卡洛大规模模拟"><a href="#3-蒙特卡洛大规模模拟" class="headerlink" title="3. 蒙特卡洛大规模模拟"></a>3. 蒙特卡洛大规模模拟</h3><p><img src="/img/2026-06-22-seekdb-world-cup-prediction/08.webp" alt="蒙特卡洛大规模重复模拟赛程示意" loading="lazy" decoding="async"></p><p>单次随机抽样的结果带有偶然性，为此我们采用蒙特卡洛方法：重复模拟 1000 次甚至 10000 次。每次模拟中，我们按赛程逐场生成小组赛比分，计算小组积分，确定每组前两名及 8 个成绩最好的小组第三晋级 32 强；然后按简化版淘汰赛对阵继续模拟，直至决出冠军。最终，统计每支球队在多次模拟中夺冠的次数，即为其夺冠概率。seekdb 的存储过程和循环控制可以支撑这种批量重复计算。</p><h2 id="二、数据准备：四张核心表的构建"><a href="#二、数据准备：四张核心表的构建" class="headerlink" title="二、数据准备：四张核心表的构建"></a>二、数据准备：四张核心表的构建</h2><p>要运行上述预测模型，必须在 seekdb 中准备好四张环环相扣的数据表。先说明数据口径：本文重点是演示如何在 seekdb 内完成一套端到端的赛事模拟流程，示例数据参考公开比赛结果和球队强弱分层整理，并不等同于专业机构的完整预测数据集。因此，最终概率更适合作为技术演示结果，而不是投注或严肃预测依据。</p><p><img src="/img/2026-06-22-seekdb-world-cup-prediction/09.webp" alt="预测所用四张核心数据表结构" loading="lazy" decoding="async"></p><h3 id="1-球队基础信息表（teams）"><a href="#1-球队基础信息表（teams）" class="headerlink" title="1. 球队基础信息表（teams）"></a>1. 球队基础信息表（teams）</h3><p>包含 48 支参赛球队的固定属性：球队 ID、中英文名称、所属大洲、FIFA 排名、Elo 评分、总市场价值以及东道主标识。</p><h3 id="2-历史比赛结果表（matches）"><a href="#2-历史比赛结果表（matches）" class="headerlink" title="2. 历史比赛结果表（matches）"></a>2. 历史比赛结果表（matches）</h3><p>存储 2019 年至 2025 年间的关键国际 A 级赛事，包括 2022 年世界杯、2024 年欧洲杯、2024 年美洲杯、2024 年非洲杯以及多场友谊赛和预选赛，总计超过 65 场比赛。每条记录包含赛季年份、赛事名称、主客队 ID、实际进球数、比赛日期和地点。这些数据用于计算球队的进攻&#x2F;防守强度以及 Elo 评分的初始值。</p><h3 id="3-球队赛季统计表（team-season-stats）"><a href="#3-球队赛季统计表（team-season-stats）" class="headerlink" title="3. 球队赛季统计表（team_season_stats）"></a>3. 球队赛季统计表（team_season_stats）</h3><p><strong>这是模型中最重要的特征表</strong> 。每支球队每年一条记录，汇总该赛季的所有比赛数据：总场次、胜&#x2F;平&#x2F;负场次、总进球、总失球、零封场次、场均控球率、场均射门&#x2F;射正以及预期进球数。对于 48 支球队，我们整理了 2023、2024、2025 三个赛季的示例特征数据。</p><h3 id="4-世界杯-2026-模拟赛程表（worldcup-2026-fixtures）"><a href="#4-世界杯-2026-模拟赛程表（worldcup-2026-fixtures）" class="headerlink" title="4. 世界杯 2026 模拟赛程表（worldcup_2026_fixtures）"></a>4. 世界杯 2026 模拟赛程表（worldcup_2026_fixtures）</h3><p>参考 2026 年世界杯小组赛结构，生成 72 场比赛记录。每条记录包含比赛阶段、主队 ID、客队 ID 以及一个比赛顺序号。注意，淘汰赛阶段的对阵并不预先存储，而是在每次蒙特卡洛模拟中根据 32 强晋级结果动态生成。</p><p>除此之外，我还需要一些计算结果的中间表，具体 <code>DDL</code> 可见下一个章节。</p><h2 id="三、从空库开始准备-SQL-环境"><a href="#三、从空库开始准备-SQL-环境" class="headerlink" title="三、从空库开始准备 SQL 环境"></a>三、从空库开始准备 SQL 环境</h2><p><img src="/img/2026-06-22-seekdb-world-cup-prediction/10.webp" alt="在 seekdb 中准备世界杯 SQL 环境" loading="lazy" decoding="async"></p><p>先把数据库和表都建好：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br></pre></td><td class="code"><pre><span class="line">DROP DATABASE IF EXISTS world_cup;</span><br><span class="line">CREATE DATABASE world_cup;</span><br><span class="line">USE world_cup;</span><br><span class="line"></span><br><span class="line">CREATE TABLE teams (</span><br><span class="line">  team_id INT PRIMARY KEY,</span><br><span class="line">  full_name VARCHAR(100) NOT NULL,</span><br><span class="line">  short_name VARCHAR(50) NOT NULL,</span><br><span class="line">  country_code VARCHAR(10) NOT NULL,</span><br><span class="line">  fifa_ranking INT,</span><br><span class="line">  elo_rating DECIMAL(10,2),</span><br><span class="line">  confederation VARCHAR(20),</span><br><span class="line">  market_value DECIMAL(18,2),</span><br><span class="line">  is_host BOOLEAN DEFAULT FALSE</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">CREATE TABLE matches (</span><br><span class="line">  match_id INT AUTO_INCREMENT PRIMARY KEY,</span><br><span class="line">  season_year INT NOT NULL,</span><br><span class="line">  tournament_name VARCHAR(100) NOT NULL,</span><br><span class="line">  home_team_id INT NOT NULL,</span><br><span class="line">  away_team_id INT NOT NULL,</span><br><span class="line">  home_goals INT NOT NULL,</span><br><span class="line">  away_goals INT NOT NULL,</span><br><span class="line">  match_date DATE,</span><br><span class="line">  location VARCHAR(100)</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">CREATE TABLE team_season_stats (</span><br><span class="line">  team_id INT NOT NULL,</span><br><span class="line">  season_year INT NOT NULL,</span><br><span class="line">  matches_played INT NOT NULL,</span><br><span class="line">  wins INT NOT NULL,</span><br><span class="line">  draws INT NOT NULL,</span><br><span class="line">  losses INT NOT NULL,</span><br><span class="line">  goals_for INT NOT NULL,</span><br><span class="line">  goals_against INT NOT NULL,</span><br><span class="line">  clean_sheets INT NOT NULL,</span><br><span class="line">  avg_possession DECIMAL(5,2),</span><br><span class="line">  avg_shots DECIMAL(5,2),</span><br><span class="line">  avg_shots_on_target DECIMAL(5,2),</span><br><span class="line">  expected_goals DECIMAL(8,2),</span><br><span class="line">  PRIMARY KEY (team_id, season_year)</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">CREATE TABLE worldcup_2026_fixtures (</span><br><span class="line">  fixture_id INT AUTO_INCREMENT PRIMARY KEY,</span><br><span class="line">  stage VARCHAR(30) NOT NULL,</span><br><span class="line">  team1_id INT NOT NULL,</span><br><span class="line">  team2_id INT NOT NULL,</span><br><span class="line">  match_order INT NOT NULL,</span><br><span class="line">  group_char CHAR(1)</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">-- 以下为模拟过程中的中间表</span><br><span class="line">CREATE TABLE team_params (</span><br><span class="line">  team_id INT PRIMARY KEY,</span><br><span class="line">  attack DECIMAL(10,4) NOT NULL,</span><br><span class="line">  defence DECIMAL(10,4) NOT NULL,</span><br><span class="line">  elo_rating DECIMAL(10,2) NOT NULL</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">CREATE TABLE group_stats (</span><br><span class="line">  team_id INT PRIMARY KEY,</span><br><span class="line">  group_char CHAR(1) NOT NULL,</span><br><span class="line">  points INT NOT NULL DEFAULT 0,</span><br><span class="line">  goal_diff INT NOT NULL DEFAULT 0,</span><br><span class="line">  goals_for INT NOT NULL DEFAULT 0</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">CREATE TABLE group_ranking (</span><br><span class="line">  team_id INT NOT NULL,</span><br><span class="line">  group_char CHAR(1) NOT NULL,</span><br><span class="line">  points INT NOT NULL,</span><br><span class="line">  goal_diff INT NOT NULL,</span><br><span class="line">  goals_for INT NOT NULL,</span><br><span class="line">  rank_in_group INT NOT NULL</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">CREATE TABLE round32 (</span><br><span class="line">  team_id INT NOT NULL,</span><br><span class="line">  group_char CHAR(1) NOT NULL,</span><br><span class="line">  group_rank INT NOT NULL,</span><br><span class="line">  points INT NOT NULL,</span><br><span class="line">  goal_diff INT NOT NULL,</span><br><span class="line">  goals_for INT NOT NULL</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">CREATE TABLE knockout_results (</span><br><span class="line">  match_id INT AUTO_INCREMENT PRIMARY KEY,</span><br><span class="line">  team1_id INT,</span><br><span class="line">  team2_id INT,</span><br><span class="line">  round_name VARCHAR(30) NOT NULL,</span><br><span class="line">  winner_id INT</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">CREATE TABLE tmp_champions (</span><br><span class="line">  sim_id INT NOT NULL,</span><br><span class="line">  champion_id INT NOT NULL</span><br><span class="line">);</span><br></pre></td></tr></table></figure><p>第二步，导入球队、历史比赛、赛季统计和赛程数据。正文只放几行示意，完整数据见文末附录 A。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">TRUNCATE TABLE teams;</span><br><span class="line">INSERT INTO teams (team_id, full_name, short_name, country_code, fifa_ranking, elo_rating, confederation, market_value, is_host) VALUES</span><br><span class="line">(1, &#x27;Mexico&#x27;, &#x27;Mexico&#x27;, &#x27;MEX&#x27;, 15, 1933.00, &#x27;CONCACAF&#x27;, 150000000.00, TRUE),</span><br><span class="line">(5, &#x27;Canada&#x27;, &#x27;Canada&#x27;, &#x27;CAN&#x27;, 30, 1810.00, &#x27;CONCACAF&#x27;, 95000000.00, TRUE),</span><br><span class="line">(13, &#x27;United States&#x27;, &#x27;USA&#x27;, &#x27;USA&#x27;, 16, 1840.00, &#x27;CONCACAF&#x27;, 280000000.00, TRUE);</span><br><span class="line"></span><br><span class="line">TRUNCATE TABLE matches;</span><br><span class="line">INSERT INTO matches (season_year, tournament_name, home_team_id, away_team_id, home_goals, away_goals, match_date, location) VALUES</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 22, 17, 2, 1, &#x27;2022-11-23&#x27;, &#x27;Khalifa Stadium&#x27;);</span><br><span class="line"></span><br><span class="line">TRUNCATE TABLE team_season_stats;</span><br><span class="line">INSERT INTO team_season_stats (...) VALUES (...);</span><br><span class="line"></span><br><span class="line">TRUNCATE TABLE worldcup_2026_fixtures;</span><br><span class="line">INSERT INTO worldcup_2026_fixtures (...) VALUES (...);</span><br></pre></td></tr></table></figure><h2 id="四、编写存储过程"><a href="#四、编写存储过程" class="headerlink" title="四、编写存储过程"></a>四、编写存储过程</h2><p><img src="/img/2026-06-22-seekdb-world-cup-prediction/11.webp" alt="世界杯模拟存储过程核心逻辑示意" loading="lazy" decoding="async"></p><p>在完成数据建模与导入之后，我面临的核心挑战是：如何在不依赖外部程序的情况下，在 seekdb 内部完成上万次蒙特卡洛模拟？答案是充分利用 seekdb 对存储过程、循环控制、随机函数以及临时表的强大支持。</p><p>我设计了一个主存储过程 <code>sp_simulate_worldcup</code> ，它接受两个参数：模拟次数 <code>num_sims</code> 和输出结果表名。整个模拟过程被封装在数据库内，无需导出数据到 Python 或 R，最大程度减少了网络传输和上下文切换的开销。存储过程的内部逻辑可以划分为四大模块：</p><h3 id="1-参数计算与预处理"><a href="#1-参数计算与预处理" class="headerlink" title="1. 参数计算与预处理"></a>1. 参数计算与预处理</h3><p>首先，从 <code>team_season_stats</code> 表中计算全局平均进球数（ <code>avg_goals_total</code> ）以及每支球队的进攻系数（ <code>attack=球队场均进球/avg_goals_total</code> ）和防守系数（ <code>defence=球队场均失球/avg_goals_total</code> ）。这些系数会被存入临时表 <code>team_params</code> 中，供每场比赛调用。同时，确定东道主集合（ <code>host_ids</code> ），用于主场优势判定。</p><h3 id="2-单次模拟的完整流程"><a href="#2-单次模拟的完整流程" class="headerlink" title="2. 单次模拟的完整流程"></a>2. 单次模拟的完整流程</h3><p>每一次模拟都遵循以下子步骤：</p><ul><li>小组赛模拟：遍历 <code>worldcup_2026_fixtures</code> 表中 <code>stage=&#39;Group&#39;</code> 的 72 场比赛。对于每场比赛，根据 <code>team1_id</code> 是否属于东道主决定是否乘以主场优势系数（1.25），利用泊松分布生成随机主客队进球数，进而确定胜、平、负。实时更新每组球队的积分、净胜球和总进球数。</li><li>确定晋级 32 强：按照积分&gt;净胜球&gt;进球数的规则对每个小组排序，选出前两名；再汇总所有小组第三名，按相同规则排序，取前 8 名作为成绩最好的小组第三。最终形成 32 强名单，并记录其 Elo 评分和所在小组排名。</li><li>淘汰赛模拟：为了聚焦 OceanBase 内部模拟流程，本文采用简化版 32 强对阵规则：将晋级球队按小组字母和组内排名排序后两两配对。这不是 FIFA 官方 bracket，会影响部分球队的路径难度，因此结果更适合作为数据库模拟能力演示。淘汰赛阶段不再生成具体比分，而是根据双方 Elo 差值计算胜率，并用随机抽样决定晋级球队。</li><li>记录本次冠军：将本次模拟的冠军球队 ID 写入一个临时结果集。</li></ul><h3 id="3-蒙特卡洛循环"><a href="#3-蒙特卡洛循环" class="headerlink" title="3. 蒙特卡洛循环"></a>3. 蒙特卡洛循环</h3><p>利用 WHILE 循环重复执行上述单次模拟 <code>num_sims</code> 次。每次模拟前会清理上一次的中间数据，确保各次模拟之间相互独立。为了加速，我尽量使用临时表而非永久表，并避免在循环内进行不必要的提交操作。</p><h3 id="4-结果聚合与输出"><a href="#4-结果聚合与输出" class="headerlink" title="4. 结果聚合与输出"></a>4. 结果聚合与输出</h3><p>循环结束后，对临时结果集中的冠军记录按球队分组计数，得到每支球队的夺冠次数，再除以 <code>num_sims</code> 得到夺冠概率。最终将结果写入用户指定的输出表中。</p><p>生成存储过程前，还需要一个辅助的 <code>UDF</code> ，生成泊松分布</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">DELIMITER $$</span><br><span class="line"></span><br><span class="line">CREATE FUNCTION fn_poisson(lambda DECIMAL(10,4))</span><br><span class="line">RETURNS INT</span><br><span class="line">DETERMINISTIC</span><br><span class="line">BEGIN</span><br><span class="line">    DECLARE L DECIMAL(20,10);</span><br><span class="line">    DECLARE k INT DEFAULT 0;</span><br><span class="line">    DECLARE p DECIMAL(20,10) DEFAULT 1.0;</span><br><span class="line">    DECLARE u DECIMAL(20,10);</span><br><span class="line"></span><br><span class="line">    SET L = EXP(-lambda);</span><br><span class="line">    SET u = RAND();</span><br><span class="line"></span><br><span class="line">    WHILE u &gt; L DO</span><br><span class="line">        SET k = k + 1;</span><br><span class="line">        SET p = p * lambda / k;</span><br><span class="line">        SET L = L + p;</span><br><span class="line">    END WHILE;</span><br><span class="line"></span><br><span class="line">    RETURN k;</span><br><span class="line">END$$</span><br><span class="line"></span><br><span class="line">DELIMITER ;</span><br></pre></td></tr></table></figure><p>完整的蒙特卡洛存储过程较长，正文只保留设计思路。完整可执行版本见文末附录 B。</p><p>sp_simulate_worldcup(num_sims, result_table) 存储过程的执行流程为：</p><ol><li>读取 2025 赛季统计，生成每支球队的进攻系数、防守系数和 Elo 参数。</li><li>循环执行 num_sims 次完整世界杯模拟。</li><li>每次模拟先清空小组积分、排名、32 强和淘汰赛中间表。</li><li>遍历 72 场小组赛，用泊松分布生成比分并更新积分、净胜球和进球数。</li><li>按积分、净胜球、进球数筛出 12 个小组前二和 8 个最佳小组第三。</li><li>使用简化版 bracket 生成 32 强对阵，并用 Elo 胜率抽样推进淘汰赛。</li><li>记录每次模拟的冠军。</li><li>按球队聚合 champion_count、champion_prob 和 simulations，写入结果表。</li></ol><h2 id="五、模拟结果"><a href="#五、模拟结果" class="headerlink" title="五、模拟结果"></a>五、模拟结果</h2><p>我在本地 seekdb MySQL 兼容环境中验证了整套 SQL。由于存储过程中使用了 <code>RAND()</code> ，每次运行都会有轻微波动，下面结果取自一次 1000 次模拟。测试环境和耗时仅供参考。</p><p>模拟举办 1000 次世界杯，获取冠军分布数据：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">obclient(root@fifa2026)[world_cup]&gt; CALL sp_simulate_worldcup(1000, &#x27;champion_probs_1k_verify&#x27;);</span><br><span class="line">Query OK, 0 rows affected</span><br><span class="line"></span><br><span class="line">obclient(root@fifa2026)[world_cup]&gt; select team_name, champion_prob, champion_count</span><br><span class="line">    -&gt; from champion_probs_1k_verify</span><br><span class="line">    -&gt; orderby champion_prob desc;</span><br><span class="line">+----------------+---------------+----------------+</span><br><span class="line">| team_name      | champion_prob | champion_count |</span><br><span class="line">+----------------+---------------+----------------+</span><br><span class="line">| Spain          |        0.2090 |            209 |</span><br><span class="line">| Argentina      |        0.1300 |            130 |</span><br><span class="line">| Brazil         |        0.1140 |            114 |</span><br><span class="line">| France         |        0.1030 |            103 |</span><br><span class="line">| Netherlands    |        0.0500 |             50 |</span><br><span class="line">| Colombia       |        0.0500 |             50 |</span><br><span class="line">| Germany        |        0.0450 |             45 |</span><br><span class="line">| England        |        0.0440 |             44 |</span><br><span class="line">| Portugal       |        0.0410 |             41 |</span><br><span class="line">| Ecuador        |        0.0380 |             38 |</span><br><span class="line">| Mexico         |        0.0330 |             33 |</span><br><span class="line">| Morocco        |        0.0270 |             27 |</span><br><span class="line">| Japan          |        0.0260 |             26 |</span><br><span class="line">| Uruguay        |        0.0200 |             20 |</span><br><span class="line">| Belgium        |        0.0190 |             19 |</span><br><span class="line">| Croatia        |        0.0120 |             12 |</span><br><span class="line">| United States  |        0.0110 |             11 |</span><br><span class="line">| Korea Republic |        0.0060 |              6 |</span><br><span class="line">| Australia      |        0.0050 |              5 |</span><br><span class="line">| Switzerland    |        0.0040 |              4 |</span><br><span class="line">| Czech Republic |        0.0030 |              3 |</span><br><span class="line">| Canada         |        0.0030 |              3 |</span><br><span class="line">| Senegal        |        0.0030 |              3 |</span><br><span class="line">| Turkey         |        0.0020 |              2 |</span><br><span class="line">| Iran           |        0.0010 |              1 |</span><br><span class="line">| Norway         |        0.0010 |              1 |</span><br><span class="line">+----------------+---------------+----------------+</span><br></pre></td></tr></table></figure><p>在这次 1000 次模拟中，西班牙夺冠 209 次，概率 20.9%；阿根廷夺冠 130 次，概率 13.0%；巴西夺冠 114 次，概率 11.4%；法国夺冠 103 次，概率 10.3%。</p><p>当然，这只是基于当前示例模型的概率换算，不代表真实预测结论。</p><blockquote><p>说明：</p><p>这里的 <code>champion_count</code> 表示球队在本轮模拟中夺冠的次数， <code>champion_prob</code> 表示夺冠次数除以总模拟次数， <code>simulations</code> 表示本次总模拟次数。由于每次运行都会重新随机抽样，概率小幅变化是正常现象。</p></blockquote><h2 id="六、为什么把模拟放在-OceanBase-seekdb-里？"><a href="#六、为什么把模拟放在-OceanBase-seekdb-里？" class="headerlink" title="六、为什么把模拟放在 OceanBase seekdb 里？"></a>六、为什么把模拟放在 OceanBase seekdb 里？</h2><p>这篇文章的重点不是证明数据库比 Python 更适合写所有模拟逻辑，而是展示当数据已经在 seekdb 里时，如何把一套概率模拟流程留在库内完成。</p><p>第一，数据和计算更近。球队、比赛、赛季统计、赛程、中间排名和最终结果都在同一个数据库里，不需要频繁导出到外部脚本再导回来。</p><p>第二，SQL 对排名类逻辑很直接。小组积分、净胜球、进球数排序，以及最佳小组第三筛选，都可以用窗口函数完成。</p><p>第三，存储过程适合表达重复模拟。蒙特卡洛的核心就是循环执行同一套流程，seekdb 的存储过程、游标、临时状态表和动态 SQL 可以把这条链路完整封装起来。</p><p>第四，后续优化空间清晰。当前实现偏演示，仍有不少优化点，例如减少循环内 <code>TRUNCATE</code> 、批量化淘汰赛计算、拆分中间表、记录每轮晋级概率，以及把淘汰赛也扩展成泊松比分加点球模型。</p><p><img src="/img/2026-06-22-seekdb-world-cup-prediction/12.png" alt="选择 OceanBase seekdb 做模拟的原因" loading="lazy" decoding="async"></p><blockquote><p>说明：</p><p>模型预测天然带有不确定性，本文更关注的是如何用 seekdb 把赛程、球队特征、随机模拟和概率汇总串成一个可执行流程，而不是给出一个确定答案。</p><p>结果仅用于技术演示，不用于任何投注判断。</p></blockquote><h2 id="附录-A：完整数据导入-SQL"><a href="#附录-A：完整数据导入-SQL" class="headerlink" title="附录 A：完整数据导入 SQL"></a>附录 A：完整数据导入 SQL</h2><p>以下 SQL 为正文示例数据的完整版本，可直接接在第三节 DDL 后执行。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br></pre></td><td class="code"><pre><span class="line">TRUNCATE TABLE teams;</span><br><span class="line">INSERT INTO teams (team_id, full_name, short_name, country_code, fifa_ranking, elo_rating, confederation, market_value, is_host) VALUES</span><br><span class="line">(1, &#x27;Mexico&#x27;, &#x27;Mexico&#x27;, &#x27;MEX&#x27;, 15, 1933.00, &#x27;CONCACAF&#x27;, 150000000.00, TRUE),</span><br><span class="line">(2, &#x27;South Africa&#x27;, &#x27;S. Africa&#x27;, &#x27;RSA&#x27;, 60, 1620.00, &#x27;CAF&#x27;, 40000000.00, FALSE),</span><br><span class="line">(3, &#x27;Korea Republic&#x27;, &#x27;Korea&#x27;, &#x27;KOR&#x27;, 25, 1790.00, &#x27;AFC&#x27;, 120000000.00, FALSE),</span><br><span class="line">(4, &#x27;Czech Republic&#x27;, &#x27;Czechia&#x27;, &#x27;CZE&#x27;, 41, 1750.00, &#x27;UEFA&#x27;, 80000000.00, FALSE),</span><br><span class="line">(5, &#x27;Canada&#x27;, &#x27;Canada&#x27;, &#x27;CAN&#x27;, 30, 1810.00, &#x27;CONCACAF&#x27;, 95000000.00, TRUE),</span><br><span class="line">(6, &#x27;Bosnia and Herzegovina&#x27;, &#x27;Bosnia&#x27;, &#x27;BIH&#x27;, 64, 1670.00, &#x27;UEFA&#x27;, 55000000.00, FALSE),</span><br><span class="line">(7, &#x27;Qatar&#x27;, &#x27;Qatar&#x27;, &#x27;QAT&#x27;, 55, 1650.00, &#x27;AFC&#x27;, 70000000.00, FALSE),</span><br><span class="line">(8, &#x27;Switzerland&#x27;, &#x27;Switzerland&#x27;, &#x27;SUI&#x27;, 19, 1830.00, &#x27;UEFA&#x27;, 200000000.00, FALSE),</span><br><span class="line">(9, &#x27;Brazil&#x27;, &#x27;Brazil&#x27;, &#x27;BRA&#x27;, 6, 1996.00, &#x27;CONMEBOL&#x27;, 1100000000.00, FALSE),</span><br><span class="line">(10, &#x27;Morocco&#x27;, &#x27;Morocco&#x27;, &#x27;MAR&#x27;, 7, 1913.00, &#x27;CAF&#x27;, 250000000.00, FALSE),</span><br><span class="line">(11, &#x27;Haiti&#x27;, &#x27;Haiti&#x27;, &#x27;HAI&#x27;, 82, 1450.00, &#x27;CONCACAF&#x27;, 20000000.00, FALSE),</span><br><span class="line">(12, &#x27;Scotland&#x27;, &#x27;Scotland&#x27;, &#x27;SCO&#x27;, 43, 1690.00, &#x27;UEFA&#x27;, 135000000.00, FALSE),</span><br><span class="line">(13, &#x27;United States&#x27;, &#x27;USA&#x27;, &#x27;USA&#x27;, 16, 1840.00, &#x27;CONCACAF&#x27;, 280000000.00, TRUE),</span><br><span class="line">(14, &#x27;Paraguay&#x27;, &#x27;Paraguay&#x27;, &#x27;PAR&#x27;, 40, 1710.00, &#x27;CONMEBOL&#x27;, 75000000.00, FALSE),</span><br><span class="line">(15, &#x27;Australia&#x27;, &#x27;Australia&#x27;, &#x27;AUS&#x27;, 27, 1770.00, &#x27;AFC&#x27;, 65000000.00, FALSE),</span><br><span class="line">(16, &#x27;Turkey&#x27;, &#x27;Turkey&#x27;, &#x27;TUR&#x27;, 22, 1760.00, &#x27;UEFA&#x27;, 180000000.00, FALSE),</span><br><span class="line">(17, &#x27;Germany&#x27;, &#x27;Germany&#x27;, &#x27;GER&#x27;, 10, 1937.00, &#x27;UEFA&#x27;, 880000000.00, FALSE),</span><br><span class="line">(18, &#x27;Curacao&#x27;, &#x27;Curacao&#x27;, &#x27;CUW&#x27;, 83, 1400.00, &#x27;CONCACAF&#x27;, 15000000.00, FALSE),</span><br><span class="line">(19, &#x27;Cote d&#x27;&#x27;Ivoire&#x27;, &#x27;Ivory Coast&#x27;, &#x27;CIV&#x27;, 34, 1680.00, &#x27;CAF&#x27;, 160000000.00, FALSE),</span><br><span class="line">(20, &#x27;Ecuador&#x27;, &#x27;Ecuador&#x27;, &#x27;ECU&#x27;, 24, 1910.00, &#x27;CONMEBOL&#x27;, 95000000.00, FALSE),</span><br><span class="line">(21, &#x27;Netherlands&#x27;, &#x27;Netherlands&#x27;, &#x27;NED&#x27;, 8, 1938.00, &#x27;UEFA&#x27;, 650000000.00, FALSE),</span><br><span class="line">(22, &#x27;Japan&#x27;, &#x27;Japan&#x27;, &#x27;JPN&#x27;, 18, 1922.00, &#x27;AFC&#x27;, 140000000.00, FALSE),</span><br><span class="line">(23, &#x27;Sweden&#x27;, &#x27;Sweden&#x27;, &#x27;SWE&#x27;, 38, 1700.00, &#x27;UEFA&#x27;, 170000000.00, FALSE),</span><br><span class="line">(24, &#x27;Tunisia&#x27;, &#x27;Tunisia&#x27;, &#x27;TUN&#x27;, 46, 1640.00, &#x27;CAF&#x27;, 50000000.00, FALSE),</span><br><span class="line">(25, &#x27;Belgium&#x27;, &#x27;Belgium&#x27;, &#x27;BEL&#x27;, 9, 1904.00, &#x27;UEFA&#x27;, 520000000.00, FALSE),</span><br><span class="line">(26, &#x27;Egypt&#x27;, &#x27;Egypt&#x27;, &#x27;EGY&#x27;, 29, 1720.00, &#x27;CAF&#x27;, 120000000.00, FALSE),</span><br><span class="line">(27, &#x27;Iran&#x27;, &#x27;Iran&#x27;, &#x27;IRN&#x27;, 21, 1740.00, &#x27;AFC&#x27;, 60000000.00, FALSE),</span><br><span class="line">(28, &#x27;New Zealand&#x27;, &#x27;New Zealand&#x27;, &#x27;NZL&#x27;, 85, 1420.00, &#x27;OFC&#x27;, 30000000.00, FALSE),</span><br><span class="line">(29, &#x27;Spain&#x27;, &#x27;Spain&#x27;, &#x27;ESP&#x27;, 2, 2082.00, &#x27;UEFA&#x27;, 900000000.00, FALSE),</span><br><span class="line">(30, &#x27;Cape Verde&#x27;, &#x27;Cape Verde&#x27;, &#x27;CPV&#x27;, 68, 1580.00, &#x27;CAF&#x27;, 35000000.00, FALSE),</span><br><span class="line">(31, &#x27;Saudi Arabia&#x27;, &#x27;Saudi Arabia&#x27;, &#x27;KSA&#x27;, 61, 1600.00, &#x27;AFC&#x27;, 80000000.00, FALSE),</span><br><span class="line">(32, &#x27;Uruguay&#x27;, &#x27;Uruguay&#x27;, &#x27;URU&#x27;, 17, 1898.00, &#x27;CONMEBOL&#x27;, 210000000.00, FALSE),</span><br><span class="line">(33, &#x27;France&#x27;, &#x27;France&#x27;, &#x27;FRA&#x27;, 1, 2025.00, &#x27;UEFA&#x27;, 1020000000.00, FALSE),</span><br><span class="line">(34, &#x27;Senegal&#x27;, &#x27;Senegal&#x27;, &#x27;SEN&#x27;, 14, 1790.00, &#x27;CAF&#x27;, 220000000.00, FALSE),</span><br><span class="line">(35, &#x27;Iraq&#x27;, &#x27;Iraq&#x27;, &#x27;IRQ&#x27;, 57, 1530.00, &#x27;AFC&#x27;, 30000000.00, FALSE),</span><br><span class="line">(36, &#x27;Norway&#x27;, &#x27;Norway&#x27;, &#x27;NOR&#x27;, 31, 1780.00, &#x27;UEFA&#x27;, 190000000.00, FALSE),</span><br><span class="line">(37, &#x27;Argentina&#x27;, &#x27;Argentina&#x27;, &#x27;ARG&#x27;, 3, 2047.00, &#x27;CONMEBOL&#x27;, 750000000.00, FALSE),</span><br><span class="line">(38, &#x27;Algeria&#x27;, &#x27;Algeria&#x27;, &#x27;ALG&#x27;, 28, 1710.00, &#x27;CAF&#x27;, 110000000.00, FALSE),</span><br><span class="line">(39, &#x27;Austria&#x27;, &#x27;Austria&#x27;, &#x27;AUT&#x27;, 23, 1730.00, &#x27;UEFA&#x27;, 160000000.00, FALSE),</span><br><span class="line">(40, &#x27;Jordan&#x27;, &#x27;Jordan&#x27;, &#x27;JOR&#x27;, 63, 1520.00, &#x27;AFC&#x27;, 25000000.00, FALSE),</span><br><span class="line">(41, &#x27;Portugal&#x27;, &#x27;Portugal&#x27;, &#x27;POR&#x27;, 5, 1967.00, &#x27;UEFA&#x27;, 840000000.00, FALSE),</span><br><span class="line">(42, &#x27;DR Congo&#x27;, &#x27;DR Congo&#x27;, &#x27;COD&#x27;, 45, 1620.00, &#x27;CAF&#x27;, 80000000.00, FALSE),</span><br><span class="line">(43, &#x27;Uzbekistan&#x27;, &#x27;Uzbekistan&#x27;, &#x27;UZB&#x27;, 50, 1580.00, &#x27;AFC&#x27;, 45000000.00, FALSE),</span><br><span class="line">(44, &#x27;Colombia&#x27;, &#x27;Colombia&#x27;, &#x27;COL&#x27;, 13, 1973.00, &#x27;CONMEBOL&#x27;, 240000000.00, FALSE),</span><br><span class="line">(45, &#x27;England&#x27;, &#x27;England&#x27;, &#x27;ENG&#x27;, 4, 1974.00, &#x27;UEFA&#x27;, 1200000000.00, FALSE),</span><br><span class="line">(46, &#x27;Croatia&#x27;, &#x27;Croatia&#x27;, &#x27;CRO&#x27;, 11, 1896.00, &#x27;UEFA&#x27;, 360000000.00, FALSE),</span><br><span class="line">(47, &#x27;Ghana&#x27;, &#x27;Ghana&#x27;, &#x27;GHA&#x27;, 73, 1610.00, &#x27;CAF&#x27;, 90000000.00, FALSE),</span><br><span class="line">(48, &#x27;Panama&#x27;, &#x27;Panama&#x27;, &#x27;PAN&#x27;, 33, 1640.00, &#x27;CONCACAF&#x27;, 45000000.00, FALSE);</span><br><span class="line"></span><br><span class="line">TRUNCATE TABLE matches;</span><br><span class="line">INSERT INTO matches (season_year, tournament_name, home_team_id, away_team_id, home_goals, away_goals, match_date, location) VALUES</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 22, 17, 2, 1, &#x27;2022-11-23&#x27;, &#x27;Khalifa Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 37, 31, 1, 2, &#x27;2022-11-22&#x27;, &#x27;Lusail Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 29, 7, 7, 0, &#x27;2022-11-23&#x27;, &#x27;Al Thumama Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 33, 15, 4, 1, &#x27;2022-11-22&#x27;, &#x27;Al Janoub Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 25, 5, 1, 0, &#x27;2022-11-23&#x27;, &#x27;Ahmed bin Ali Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 9, 17, 2, 0, &#x27;2022-12-02&#x27;, &#x27;Lusail Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 21, 13, 3, 1, &#x27;2022-12-03&#x27;, &#x27;Khalifa Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 37, 15, 2, 1, &#x27;2022-12-03&#x27;, &#x27;Ahmed bin Ali Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 33, 47, 3, 1, &#x27;2022-12-04&#x27;, &#x27;Al Thumama Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 45, 34, 3, 0, &#x27;2022-12-04&#x27;, &#x27;Al Bayt Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 22, 46, 1, 1, &#x27;2022-12-05&#x27;, &#x27;Al Janoub Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 9, 3, 4, 1, &#x27;2022-12-05&#x27;, &#x27;Stadium 974&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 10, 29, 0, 0, &#x27;2022-12-06&#x27;, &#x27;Education City Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 41, 8, 6, 1, &#x27;2022-12-06&#x27;, &#x27;Lusail Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 46, 9, 1, 1, &#x27;2022-12-09&#x27;, &#x27;Education City Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 21, 37, 2, 2, &#x27;2022-12-09&#x27;, &#x27;Lusail Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 10, 41, 1, 0, &#x27;2022-12-10&#x27;, &#x27;Al Thumama Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 45, 33, 1, 2, &#x27;2022-12-10&#x27;, &#x27;Al Bayt Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 37, 46, 3, 0, &#x27;2022-12-13&#x27;, &#x27;Lusail Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 33, 10, 2, 0, &#x27;2022-12-14&#x27;, &#x27;Al Bayt Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 46, 10, 2, 1, &#x27;2022-12-17&#x27;, &#x27;Khalifa Stadium&#x27;),</span><br><span class="line">(2022, &#x27;World Cup&#x27;, 37, 33, 3, 3, &#x27;2022-12-18&#x27;, &#x27;Lusail Stadium&#x27;),</span><br><span class="line">(2024, &#x27;Euro&#x27;, 29, 46, 3, 0, &#x27;2024-06-15&#x27;, &#x27;Berlin&#x27;),</span><br><span class="line">(2024, &#x27;Euro&#x27;, 29, 45, 2, 1, &#x27;2024-07-14&#x27;, &#x27;Berlin&#x27;),</span><br><span class="line">(2024, &#x27;Euro&#x27;, 29, 33, 2, 1, &#x27;2024-07-09&#x27;, &#x27;Munich&#x27;),</span><br><span class="line">(2024, &#x27;Euro&#x27;, 45, 21, 2, 1, &#x27;2024-07-10&#x27;, &#x27;Dortmund&#x27;),</span><br><span class="line">(2024, &#x27;Euro&#x27;, 17, 8, 2, 0, &#x27;2024-06-19&#x27;, &#x27;Stuttgart&#x27;),</span><br><span class="line">(2024, &#x27;Euro&#x27;, 17, 8, 2, 0, &#x27;2024-07-05&#x27;, &#x27;Stuttgart&#x27;),</span><br><span class="line">(2024, &#x27;Euro&#x27;, 41, 33, 0, 0, &#x27;2024-07-05&#x27;, &#x27;Hamburg&#x27;),</span><br><span class="line">(2024, &#x27;Euro&#x27;, 8, 45, 1, 1, &#x27;2024-07-06&#x27;, &#x27;Dusseldorf&#x27;),</span><br><span class="line">(2024, &#x27;Euro&#x27;, 39, 16, 3, 1, &#x27;2024-06-21&#x27;, &#x27;Berlin&#x27;),</span><br><span class="line">(2024, &#x27;Euro&#x27;, 39, 33, 0, 1, &#x27;2024-06-17&#x27;, &#x27;Dusseldorf&#x27;),</span><br><span class="line">(2024, &#x27;Euro&#x27;, 9, 37, 1, 1, &#x27;2024-10-15&#x27;, &#x27;Madrid&#x27;),</span><br><span class="line">(2024, &#x27;Copa America&#x27;, 37, 44, 1, 0, &#x27;2024-07-14&#x27;, &#x27;Miami&#x27;),</span><br><span class="line">(2024, &#x27;Copa America&#x27;, 32, 5, 2, 2, &#x27;2024-07-13&#x27;, &#x27;Charlotte&#x27;),</span><br><span class="line">(2024, &#x27;Copa America&#x27;, 37, 20, 1, 1, &#x27;2024-07-04&#x27;, &#x27;Houston&#x27;),</span><br><span class="line">(2024, &#x27;Copa America&#x27;, 5, 32, 2, 2, &#x27;2024-07-13&#x27;, &#x27;Charlotte&#x27;),</span><br><span class="line">(2024, &#x27;Copa America&#x27;, 9, 44, 1, 1, &#x27;2024-07-02&#x27;, &#x27;Las Vegas&#x27;),</span><br><span class="line">(2024, &#x27;Africa Cup&#x27;, 19, 34, 2, 1, &#x27;2024-02-11&#x27;, &#x27;Abidjan&#x27;),</span><br><span class="line">(2024, &#x27;Africa Cup&#x27;, 19, 47, 0, 1, &#x27;2024-01-18&#x27;, &#x27;Abidjan&#x27;),</span><br><span class="line">(2024, &#x27;Africa Cup&#x27;, 10, 42, 0, 0, &#x27;2024-01-21&#x27;, &#x27;Abidjan&#x27;),</span><br><span class="line">(2024, &#x27;Africa Cup&#x27;, 34, 38, 1, 0, &#x27;2024-01-23&#x27;, &#x27;Yamoussoukro&#x27;),</span><br><span class="line">(2024, &#x27;Africa Cup&#x27;, 42, 26, 2, 1, &#x27;2024-02-02&#x27;, &#x27;Abidjan&#x27;),</span><br><span class="line">(2023, &#x27;Friendly&#x27;, 13, 17, 1, 2, &#x27;2023-10-14&#x27;, &#x27;Hartford&#x27;),</span><br><span class="line">(2023, &#x27;Friendly&#x27;, 45, 9, 1, 2, &#x27;2023-03-23&#x27;, &#x27;London&#x27;),</span><br><span class="line">(2024, &#x27;Friendly&#x27;, 33, 17, 2, 0, &#x27;2024-03-23&#x27;, &#x27;Lyon&#x27;),</span><br><span class="line">(2024, &#x27;Friendly&#x27;, 21, 17, 1, 1, &#x27;2024-03-26&#x27;, &#x27;Amsterdam&#x27;),</span><br><span class="line">(2024, &#x27;Friendly&#x27;, 37, 20, 1, 0, &#x27;2024-06-09&#x27;, &#x27;Chicago&#x27;),</span><br><span class="line">(2024, &#x27;Friendly&#x27;, 13, 9, 1, 1, &#x27;2024-06-12&#x27;, &#x27;Orlando&#x27;),</span><br><span class="line">(2025, &#x27;Friendly&#x27;, 29, 21, 2, 2, &#x27;2025-03-25&#x27;, &#x27;Madrid&#x27;),</span><br><span class="line">(2025, &#x27;Friendly&#x27;, 45, 33, 2, 2, &#x27;2025-06-07&#x27;, &#x27;London&#x27;),</span><br><span class="line">(2025, &#x27;Friendly&#x27;, 17, 45, 3, 3, &#x27;2025-09-10&#x27;, &#x27;Munich&#x27;),</span><br><span class="line">(2025, &#x27;Friendly&#x27;, 13, 37, 0, 3, &#x27;2025-10-15&#x27;, &#x27;New York&#x27;),</span><br><span class="line">(2025, &#x27;Friendly&#x27;, 5, 21, 0, 4, &#x27;2025-11-19&#x27;, &#x27;Toronto&#x27;),</span><br><span class="line">(2025, &#x27;Friendly&#x27;, 1, 37, 2, 2, &#x27;2025-12-05&#x27;, &#x27;Mexico City&#x27;),</span><br><span class="line">(2024, &#x27;Qualifier&#x27;, 22, 15, 2, 0, &#x27;2024-10-10&#x27;, &#x27;Saitama&#x27;),</span><br><span class="line">(2024, &#x27;Qualifier&#x27;, 3, 22, 0, 1, &#x27;2024-10-15&#x27;, &#x27;Seoul&#x27;),</span><br><span class="line">(2025, &#x27;Qualifier&#x27;, 34, 42, 2, 0, &#x27;2025-03-21&#x27;, &#x27;Dakar&#x27;),</span><br><span class="line">(2025, &#x27;Qualifier&#x27;, 26, 34, 1, 1, &#x27;2025-03-25&#x27;, &#x27;Cairo&#x27;),</span><br><span class="line">(2025, &#x27;Qualifier&#x27;, 10, 19, 2, 1, &#x27;2025-06-05&#x27;, &#x27;Rabat&#x27;),</span><br><span class="line">(2025, &#x27;Qualifier&#x27;, 31, 22, 0, 2, &#x27;2025-06-10&#x27;, &#x27;Riyadh&#x27;),</span><br><span class="line">(2025, &#x27;Qualifier&#x27;, 5, 1, 1, 2, &#x27;2025-07-04&#x27;, &#x27;Vancouver&#x27;),</span><br><span class="line">(2025, &#x27;Qualifier&#x27;, 13, 1, 1, 1, &#x27;2025-07-07&#x27;, &#x27;Los Angeles&#x27;);</span><br><span class="line"></span><br><span class="line">TRUNCATE TABLE team_season_stats;</span><br><span class="line">INSERT INTO team_season_stats (team_id, season_year, matches_played, wins, draws, losses, goals_for, goals_against, clean_sheets, avg_possession, avg_shots, avg_shots_on_target, expected_goals) VALUES</span><br><span class="line">(1,2023,11,6,3,2,18,11,4,51.0,12.5,5.0,16.8),</span><br><span class="line">(1,2024,13,7,3,3,23,14,4,51.5,12.8,5.2,21.3),</span><br><span class="line">(1,2025,9,5,2,2,15,9,3,51.2,12.6,5.1,13.9),</span><br><span class="line">(2,2023,11,3,3,5,10,14,2,42.5,8.2,3.2,9.5),</span><br><span class="line">(2,2024,10,3,3,4,10,13,2,42.0,8.0,3.0,9.0),</span><br><span class="line">(2,2025,10,4,2,4,12,13,2,43.0,8.5,3.3,10.5),</span><br><span class="line">(3,2023,11,6,3,2,18,10,4,49.2,11.5,4.8,16.5),</span><br><span class="line">(3,2024,13,7,3,3,22,13,4,49.5,11.8,5.0,20.2),</span><br><span class="line">(3,2025,8,4,2,2,13,8,3,49.0,11.6,4.8,12.1),</span><br><span class="line">(4,2023,11,5,3,3,14,12,3,46.0,10.0,4.0,13.0),</span><br><span class="line">(4,2024,12,5,3,4,15,12,3,46.5,10.5,4.0,14.0),</span><br><span class="line">(4,2025,10,5,2,3,13,11,3,46.0,10.2,4.1,12.5),</span><br><span class="line">(5,2023,10,5,2,3,16,12,3,48.5,11.5,4.5,14.8),</span><br><span class="line">(5,2024,13,7,3,3,22,14,3,49.2,12.0,4.9,20.5),</span><br><span class="line">(5,2025,8,4,2,2,13,9,2,48.8,11.8,4.6,12.1),</span><br><span class="line">(6,2023,10,3,3,4,9,12,2,41.0,7.5,3.0,8.5),</span><br><span class="line">(6,2024,11,3,2,6,9,14,1,41.0,7.5,3.0,8.5),</span><br><span class="line">(6,2025,10,4,2,4,11,13,2,42.0,7.8,3.2,10.0),</span><br><span class="line">(7,2023,11,4,3,4,12,12,3,43.0,8.5,3.2,10.5),</span><br><span class="line">(7,2024,11,4,2,5,11,13,2,43.0,8.5,3.2,10.0),</span><br><span class="line">(7,2025,10,4,3,3,12,12,3,44.0,8.8,3.4,11.0),</span><br><span class="line">(8,2023,11,6,3,2,19,11,5,50.0,12.0,4.8,17.5),</span><br><span class="line">(8,2024,12,6,3,3,20,13,4,50.0,12.0,4.8,18.5),</span><br><span class="line">(8,2025,9,5,2,2,15,10,3,50.5,12.2,4.9,14.0),</span><br><span class="line">(9,2023,12,8,2,2,28,10,6,58.5,15.2,6.1,25.8),</span><br><span class="line">(9,2024,14,10,3,1,35,12,7,60.1,16.5,7.0,33.2),</span><br><span class="line">(9,2025,10,7,2,1,22,8,5,59.8,15.8,6.5,20.5),</span><br><span class="line">(10,2023,8,5,2,1,15,6,4,48.5,11.5,4.5,13.2),</span><br><span class="line">(10,2024,11,7,2,2,21,9,4,49.2,12.0,4.8,19.5),</span><br><span class="line">(10,2025,7,4,2,1,13,6,3,48.8,11.8,4.6,11.8),</span><br><span class="line">(11,2023,9,2,2,5,6,12,1,38.0,6.0,2.2,5.5),</span><br><span class="line">(11,2024,10,2,2,6,6,13,1,38.0,6.0,2.2,5.8),</span><br><span class="line">(11,2025,9,3,2,4,7,12,1,39.0,6.5,2.4,6.5),</span><br><span class="line">(12,2023,11,5,3,3,15,11,3,46.0,10.0,4.0,14.0),</span><br><span class="line">(12,2024,12,5,3,4,16,12,2,47.0,10.5,4.0,14.5),</span><br><span class="line">(12,2025,9,5,2,2,13,9,3,47.5,10.8,4.2,12.0),</span><br><span class="line">(13,2023,12,7,3,2,23,12,5,52.3,13.2,5.5,21.2),</span><br><span class="line">(13,2024,14,8,4,2,27,14,4,53.1,13.5,5.7,25.1),</span><br><span class="line">(13,2025,10,6,2,2,19,10,3,52.8,13.0,5.4,17.5),</span><br><span class="line">(14,2023,10,4,3,3,12,11,2,45.0,9.5,3.8,11.5),</span><br><span class="line">(14,2024,11,4,4,3,13,12,2,45.0,9.5,3.8,12.0),</span><br><span class="line">(14,2025,9,4,3,2,12,10,2,46.0,9.8,4.0,11.0),</span><br><span class="line">(15,2023,11,5,3,3,15,12,3,46.0,10.0,4.0,14.0),</span><br><span class="line">(15,2024,12,5,3,4,16,12,3,47.0,10.5,4.0,14.5),</span><br><span class="line">(15,2025,9,5,2,2,13,10,3,47.5,10.8,4.1,12.0),</span><br><span class="line">(16,2023,11,6,3,2,18,11,4,48.5,11.5,4.5,16.5),</span><br><span class="line">(16,2024,12,6,3,3,19,13,3,49.0,11.8,4.6,17.8),</span><br><span class="line">(16,2025,9,5,2,2,14,10,3,49.5,12.0,4.8,13.0),</span><br><span class="line">(17,2023,11,7,3,1,25,11,5,57.2,15.0,6.2,23.5),</span><br><span class="line">(17,2024,14,9,3,2,33,16,5,58.1,15.7,6.7,31.1),</span><br><span class="line">(17,2025,9,6,2,1,20,9,4,57.5,15.2,6.4,18.7),</span><br><span class="line">(18,2023,9,1,2,6,5,14,0,36.0,5.5,2.0,4.5),</span><br><span class="line">(18,2024,10,1,2,7,5,15,0,36.0,5.5,2.0,4.8),</span><br><span class="line">(18,2025,9,2,2,5,6,13,1,37.0,5.8,2.2,5.5),</span><br><span class="line">(19,2023,8,4,2,2,14,8,3,49.5,11.2,4.5,12.5),</span><br><span class="line">(19,2024,11,6,3,2,22,10,4,50.2,11.8,4.8,20.3),</span><br><span class="line">(19,2025,7,4,2,1,12,6,3,49.8,11.5,4.6,11.2),</span><br><span class="line">(20,2023,11,6,3,2,21,12,4,53.2,12.8,5.2,19.5),</span><br><span class="line">(20,2024,13,8,3,2,29,13,5,54.0,13.5,5.6,27.1),</span><br><span class="line">(20,2025,8,5,2,1,16,7,3,53.5,13.0,5.3,14.8),</span><br><span class="line">(21,2023,10,7,2,1,22,9,5,56.5,14.5,5.9,20.8),</span><br><span class="line">(21,2024,13,9,2,2,30,12,6,57.2,15.1,6.3,28.5),</span><br><span class="line">(21,2025,8,6,1,1,18,6,4,56.8,14.8,6.0,16.9),</span><br><span class="line">(22,2023,10,6,2,2,17,9,4,48.0,11.8,4.6,15.6),</span><br><span class="line">(22,2024,12,7,3,2,21,11,4,48.5,12.0,4.9,19.2),</span><br><span class="line">(22,2025,8,5,2,1,14,7,3,48.2,11.9,4.7,12.8),</span><br><span class="line">(23,2023,11,5,3,3,16,12,3,46.5,10.5,4.0,15.0),</span><br><span class="line">(23,2024,12,5,3,4,17,13,2,47.0,10.8,4.2,15.5),</span><br><span class="line">(23,2025,9,5,2,2,14,10,3,47.5,11.0,4.3,13.0),</span><br><span class="line">(24,2023,10,4,3,3,11,11,2,44.0,9.0,3.5,10.5),</span><br><span class="line">(24,2024,11,4,3,4,12,12,2,44.0,9.0,3.5,11.0),</span><br><span class="line">(24,2025,9,4,3,2,12,10,2,45.0,9.2,3.6,11.0),</span><br><span class="line">(25,2023,10,6,3,1,20,9,5,53.5,13.8,5.5,18.9),</span><br><span class="line">(25,2024,12,7,3,2,26,13,4,54.2,14.2,5.8,24.3),</span><br><span class="line">(25,2025,8,5,2,1,17,7,3,54.0,13.9,5.6,15.8),</span><br><span class="line">(26,2023,11,5,3,3,14,12,3,46.0,10.0,4.0,13.5),</span><br><span class="line">(26,2024,12,5,3,4,15,13,3,46.5,10.5,4.0,14.0),</span><br><span class="line">(26,2025,9,5,2,2,13,10,3,47.0,10.8,4.2,12.0),</span><br><span class="line">(27,2023,11,5,4,2,15,12,3,47.0,10.5,4.2,14.0),</span><br><span class="line">(27,2024,12,5,4,3,16,13,3,47.0,10.5,4.2,15.0),</span><br><span class="line">(27,2025,9,5,3,1,14,10,3,48.0,10.8,4.3,13.0),</span><br><span class="line">(28,2023,9,1,2,6,5,16,0,35.0,5.0,1.8,4.0),</span><br><span class="line">(28,2024,10,1,1,8,4,18,0,35.0,5.0,1.8,4.0),</span><br><span class="line">(28,2025,9,2,2,5,6,14,1,36.0,5.5,2.0,5.0),</span><br><span class="line">(29,2023,12,9,2,1,32,9,8,62.1,17.2,7.5,30.1),</span><br><span class="line">(29,2024,16,13,2,1,45,13,9,63.5,18.0,8.1,43.2),</span><br><span class="line">(29,2025,10,8,1,1,27,7,6,62.8,17.5,7.8,25.3),</span><br><span class="line">(30,2023,9,3,2,4,8,11,1,40.0,7.0,2.8,7.0),</span><br><span class="line">(30,2024,10,3,2,5,8,12,1,40.0,7.0,2.8,7.5),</span><br><span class="line">(30,2025,9,4,2,3,9,11,2,41.0,7.2,3.0,8.0),</span><br><span class="line">(31,2023,10,4,2,4,10,12,2,42.0,8.0,3.0,9.0),</span><br><span class="line">(31,2024,11,4,2,5,10,13,2,42.0,8.0,3.0,9.5),</span><br><span class="line">(31,2025,9,5,2,2,12,10,3,43.0,8.5,3.3,11.0),</span><br><span class="line">(32,2023,10,6,2,2,19,10,4,51.2,12.8,5.2,17.5),</span><br><span class="line">(32,2024,14,9,3,2,28,13,5,52.0,13.3,5.6,26.1),</span><br><span class="line">(32,2025,8,5,2,1,15,7,3,51.8,13.0,5.3,13.8),</span><br><span class="line">(33,2023,12,9,2,1,30,8,7,56.2,14.8,6.5,28.3),</span><br><span class="line">(33,2024,15,11,3,1,42,14,6,58.0,16.2,7.2,39.1),</span><br><span class="line">(33,2025,10,8,1,1,25,7,5,57.3,15.5,6.8,23.4),</span><br><span class="line">(34,2023,9,6,2,1,18,7,5,52.3,12.5,5.0,16.8),</span><br><span class="line">(34,2024,12,8,2,2,25,10,5,53.0,13.0,5.2,23.5),</span><br><span class="line">(34,2025,8,5,2,1,15,6,4,52.5,12.5,5.0,14.2),</span><br><span class="line">(35,2023,9,3,2,4,7,12,1,40.0,7.0,2.8,6.5),</span><br><span class="line">(35,2024,10,3,2,5,8,13,1,40.0,7.0,2.8,7.5),</span><br><span class="line">(35,2025,9,4,2,3,9,12,2,41.0,7.2,3.0,8.0),</span><br><span class="line">(36,2023,11,5,3,3,17,13,3,47.5,10.8,4.2,15.5),</span><br><span class="line">(36,2024,12,5,3,4,18,14,3,48.0,11.0,4.3,16.5),</span><br><span class="line">(36,2025,9,5,2,2,14,10,3,48.5,11.2,4.5,13.0),</span><br><span class="line">(37,2023,10,7,2,1,22,8,5,55.1,14.2,5.8,20.1),</span><br><span class="line">(37,2024,16,12,2,2,38,14,7,56.8,15.0,6.3,35.5),</span><br><span class="line">(37,2025,9,6,2,1,19,7,4,55.9,14.5,6.0,17.8),</span><br><span class="line">(38,2023,11,5,3,3,15,11,3,47.0,10.5,4.0,14.0),</span><br><span class="line">(38,2024,12,5,4,3,16,12,3,47.5,10.8,4.0,14.8),</span><br><span class="line">(38,2025,9,5,2,2,13,10,3,48.0,11.0,4.2,12.0),</span><br><span class="line">(39,2023,11,6,2,3,17,11,3,48.0,11.0,4.2,16.0),</span><br><span class="line">(39,2024,12,6,2,4,18,12,3,48.5,11.5,4.5,16.9),</span><br><span class="line">(39,2025,9,5,2,2,14,10,3,49.0,11.8,4.6,13.0),</span><br><span class="line">(40,2023,9,3,2,4,7,12,1,40.0,7.0,2.8,6.5),</span><br><span class="line">(40,2024,10,3,2,5,8,13,1,40.0,7.0,2.8,7.5),</span><br><span class="line">(40,2025,9,4,2,3,9,12,2,41.0,7.2,3.0,8.0),</span><br><span class="line">(41,2023,11,8,2,1,27,10,6,55.8,14.9,6.3,25.6),</span><br><span class="line">(41,2024,14,10,2,2,35,14,5,56.3,15.3,6.5,33.1),</span><br><span class="line">(41,2025,9,7,1,1,22,7,5,55.9,15.0,6.2,20.4),</span><br><span class="line">(42,2023,10,4,3,3,11,11,2,44.0,9.0,3.5,10.5),</span><br><span class="line">(42,2024,11,4,3,4,12,12,2,44.0,9.0,3.5,11.0),</span><br><span class="line">(42,2025,9,5,2,2,13,10,2,45.0,9.5,3.8,11.5),</span><br><span class="line">(43,2023,9,3,2,4,7,11,1,39.0,6.8,2.5,6.5),</span><br><span class="line">(43,2024,10,3,2,5,7,12,1,39.0,6.8,2.5,6.8),</span><br><span class="line">(43,2025,9,4,2,3,9,11,2,40.0,7.0,2.8,8.0),</span><br><span class="line">(44,2023,11,7,3,1,24,11,5,56.3,14.2,6.2,22.5),</span><br><span class="line">(44,2024,15,10,3,2,38,15,6,57.1,15.0,6.8,35.8),</span><br><span class="line">(44,2025,9,6,2,1,20,8,4,56.5,14.5,6.3,18.2),</span><br><span class="line">(45,2023,12,8,3,1,26,10,6,54.2,14.5,6.0,24.5),</span><br><span class="line">(45,2024,17,12,4,1,41,15,7,55.8,15.3,6.9,38.2),</span><br><span class="line">(45,2025,10,7,2,1,21,8,5,55.0,14.8,6.2,19.6),</span><br><span class="line">(46,2023,10,6,3,1,18,9,4,52.8,12.5,5.0,16.8),</span><br><span class="line">(46,2024,13,8,3,2,24,12,5,53.5,13.0,5.3,22.5),</span><br><span class="line">(46,2025,8,5,2,1,16,7,3,53.0,12.8,5.1,14.9),</span><br><span class="line">(47,2023,10,4,3,3,12,12,2,44.0,9.0,3.5,11.0),</span><br><span class="line">(47,2024,11,4,3,4,13,13,2,44.5,9.2,3.6,11.5),</span><br><span class="line">(47,2025,9,5,2,2,12,10,2,45.0,9.5,3.8,11.0),</span><br><span class="line">(48,2023,9,4,2,3,12,11,2,45.0,9.5,3.8,11.2),</span><br><span class="line">(48,2024,11,5,3,3,15,12,3,45.5,9.8,4.0,14.1),</span><br><span class="line">(48,2025,8,4,2,2,11,8,2,45.2,9.6,3.9,10.5);</span><br><span class="line"></span><br><span class="line">TRUNCATE TABLE worldcup_2026_fixtures;</span><br><span class="line">-- 小组 A</span><br><span class="line">INSERT INTO worldcup_2026_fixtures (stage, team1_id, team2_id, match_order, group_char) VALUES</span><br><span class="line">(&#x27;Group&#x27;, 1, 2, 1, &#x27;A&#x27;), (&#x27;Group&#x27;, 3, 4, 2, &#x27;A&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 2, 4, 3, &#x27;A&#x27;), (&#x27;Group&#x27;, 1, 3, 4, &#x27;A&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 4, 1, 5, &#x27;A&#x27;), (&#x27;Group&#x27;, 2, 3, 6, &#x27;A&#x27;);</span><br><span class="line">-- 小组 B</span><br><span class="line">INSERT INTO worldcup_2026_fixtures (stage, team1_id, team2_id, match_order, group_char) VALUES</span><br><span class="line">(&#x27;Group&#x27;, 5, 6, 7, &#x27;B&#x27;), (&#x27;Group&#x27;, 7, 8, 8, &#x27;B&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 8, 6, 9, &#x27;B&#x27;), (&#x27;Group&#x27;, 5, 7, 10, &#x27;B&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 6, 5, 11, &#x27;B&#x27;), (&#x27;Group&#x27;, 8, 7, 12, &#x27;B&#x27;);</span><br><span class="line">-- 小组 C</span><br><span class="line">INSERT INTO worldcup_2026_fixtures (stage, team1_id, team2_id, match_order, group_char) VALUES</span><br><span class="line">(&#x27;Group&#x27;, 9, 10, 13, &#x27;C&#x27;), (&#x27;Group&#x27;, 11, 12, 14, &#x27;C&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 12, 10, 15, &#x27;C&#x27;), (&#x27;Group&#x27;, 9, 11, 16, &#x27;C&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 10, 9, 17, &#x27;C&#x27;), (&#x27;Group&#x27;, 12, 11, 18, &#x27;C&#x27;);</span><br><span class="line">-- 小组 D</span><br><span class="line">INSERT INTO worldcup_2026_fixtures (stage, team1_id, team2_id, match_order, group_char) VALUES</span><br><span class="line">(&#x27;Group&#x27;, 13, 14, 19, &#x27;D&#x27;), (&#x27;Group&#x27;, 15, 16, 20, &#x27;D&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 14, 16, 21, &#x27;D&#x27;), (&#x27;Group&#x27;, 13, 15, 22, &#x27;D&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 16, 13, 23, &#x27;D&#x27;), (&#x27;Group&#x27;, 14, 15, 24, &#x27;D&#x27;);</span><br><span class="line">-- 小组 E</span><br><span class="line">INSERT INTO worldcup_2026_fixtures (stage, team1_id, team2_id, match_order, group_char) VALUES</span><br><span class="line">(&#x27;Group&#x27;, 17, 18, 25, &#x27;E&#x27;), (&#x27;Group&#x27;, 19, 20, 26, &#x27;E&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 20, 18, 27, &#x27;E&#x27;), (&#x27;Group&#x27;, 17, 19, 28, &#x27;E&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 18, 17, 29, &#x27;E&#x27;), (&#x27;Group&#x27;, 20, 19, 30, &#x27;E&#x27;);</span><br><span class="line">-- 小组 F</span><br><span class="line">INSERT INTO worldcup_2026_fixtures (stage, team1_id, team2_id, match_order, group_char) VALUES</span><br><span class="line">(&#x27;Group&#x27;, 21, 22, 31, &#x27;F&#x27;), (&#x27;Group&#x27;, 23, 24, 32, &#x27;F&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 24, 22, 33, &#x27;F&#x27;), (&#x27;Group&#x27;, 21, 23, 34, &#x27;F&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 22, 21, 35, &#x27;F&#x27;), (&#x27;Group&#x27;, 24, 23, 36, &#x27;F&#x27;);</span><br><span class="line">-- 小组 G</span><br><span class="line">INSERT INTO worldcup_2026_fixtures (stage, team1_id, team2_id, match_order, group_char) VALUES</span><br><span class="line">(&#x27;Group&#x27;, 25, 26, 37, &#x27;G&#x27;), (&#x27;Group&#x27;, 27, 28, 38, &#x27;G&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 28, 26, 39, &#x27;G&#x27;), (&#x27;Group&#x27;, 25, 27, 40, &#x27;G&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 26, 25, 41, &#x27;G&#x27;), (&#x27;Group&#x27;, 28, 27, 42, &#x27;G&#x27;);</span><br><span class="line">-- 小组 H</span><br><span class="line">INSERT INTO worldcup_2026_fixtures (stage, team1_id, team2_id, match_order, group_char) VALUES</span><br><span class="line">(&#x27;Group&#x27;, 29, 30, 43, &#x27;H&#x27;), (&#x27;Group&#x27;, 31, 32, 44, &#x27;H&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 32, 30, 45, &#x27;H&#x27;), (&#x27;Group&#x27;, 29, 31, 46, &#x27;H&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 30, 29, 47, &#x27;H&#x27;), (&#x27;Group&#x27;, 32, 31, 48, &#x27;H&#x27;);</span><br><span class="line">-- 小组 I</span><br><span class="line">INSERT INTO worldcup_2026_fixtures (stage, team1_id, team2_id, match_order, group_char) VALUES</span><br><span class="line">(&#x27;Group&#x27;, 33, 34, 49, &#x27;I&#x27;), (&#x27;Group&#x27;, 35, 36, 50, &#x27;I&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 36, 34, 51, &#x27;I&#x27;), (&#x27;Group&#x27;, 33, 35, 52, &#x27;I&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 34, 33, 53, &#x27;I&#x27;), (&#x27;Group&#x27;, 36, 35, 54, &#x27;I&#x27;);</span><br><span class="line">-- 小组 J</span><br><span class="line">INSERT INTO worldcup_2026_fixtures (stage, team1_id, team2_id, match_order, group_char) VALUES</span><br><span class="line">(&#x27;Group&#x27;, 37, 38, 55, &#x27;J&#x27;), (&#x27;Group&#x27;, 39, 40, 56, &#x27;J&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 40, 38, 57, &#x27;J&#x27;), (&#x27;Group&#x27;, 37, 39, 58, &#x27;J&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 38, 37, 59, &#x27;J&#x27;), (&#x27;Group&#x27;, 40, 39, 60, &#x27;J&#x27;);</span><br><span class="line">-- 小组 K</span><br><span class="line">INSERT INTO worldcup_2026_fixtures (stage, team1_id, team2_id, match_order, group_char) VALUES</span><br><span class="line">(&#x27;Group&#x27;, 41, 42, 61, &#x27;K&#x27;), (&#x27;Group&#x27;, 43, 44, 62, &#x27;K&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 44, 42, 63, &#x27;K&#x27;), (&#x27;Group&#x27;, 41, 43, 64, &#x27;K&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 42, 41, 65, &#x27;K&#x27;), (&#x27;Group&#x27;, 44, 43, 66, &#x27;K&#x27;);</span><br><span class="line">-- 小组 L</span><br><span class="line">INSERT INTO worldcup_2026_fixtures (stage, team1_id, team2_id, match_order, group_char) VALUES</span><br><span class="line">(&#x27;Group&#x27;, 45, 46, 67, &#x27;L&#x27;), (&#x27;Group&#x27;, 47, 48, 68, &#x27;L&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 48, 46, 69, &#x27;L&#x27;), (&#x27;Group&#x27;, 45, 47, 70, &#x27;L&#x27;),</span><br><span class="line">(&#x27;Group&#x27;, 46, 45, 71, &#x27;L&#x27;), (&#x27;Group&#x27;, 48, 47, 72, &#x27;L&#x27;);</span><br></pre></td></tr></table></figure><h2 id="附录-B：完整蒙特卡洛存储过程"><a href="#附录-B：完整蒙特卡洛存储过程" class="headerlink" title="附录 B：完整蒙特卡洛存储过程"></a>附录 B：完整蒙特卡洛存储过程</h2><p>以下 SQL 为正文第四节设计思路对应的完整可执行存储过程。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br></pre></td><td class="code"><pre><span class="line">DELIMITER //</span><br><span class="line"></span><br><span class="line">DROP PROCEDURE IF EXISTS sp_simulate_worldcup //</span><br><span class="line"></span><br><span class="line">CREATE PROCEDURE sp_simulate_worldcup(</span><br><span class="line">    IN num_sims INT,</span><br><span class="line">    IN result_table VARCHAR(64)</span><br><span class="line">)</span><br><span class="line">BEGIN</span><br><span class="line">    DECLARE sim_counter INT DEFAULT 0;</span><br><span class="line">    DECLARE avg_goals_total DECIMAL(10,4);</span><br><span class="line">    DECLARE home_advantage DECIMAL(5,2) DEFAULT 1.25;</span><br><span class="line">    DECLARE host_ids VARCHAR(100) DEFAULT &#x27;1,5,13&#x27;;</span><br><span class="line">    DECLARE done INT DEFAULT 0;</span><br><span class="line"></span><br><span class="line">    DECLARE v_fixture_id INT;</span><br><span class="line">    DECLARE v_team1 INT;</span><br><span class="line">    DECLARE v_team2 INT;</span><br><span class="line">    DECLARE v_att1 DECIMAL(10,4);</span><br><span class="line">    DECLARE v_def1 DECIMAL(10,4);</span><br><span class="line">    DECLARE v_att2 DECIMAL(10,4);</span><br><span class="line">    DECLARE v_def2 DECIMAL(10,4);</span><br><span class="line">    DECLARE v_home_boost DECIMAL(5,2);</span><br><span class="line">    DECLARE v_lambda1 DECIMAL(10,4);</span><br><span class="line">    DECLARE v_lambda2 DECIMAL(10,4);</span><br><span class="line">    DECLARE v_home_goals INT;</span><br><span class="line">    DECLARE v_away_goals INT;</span><br><span class="line">    DECLARE v_champion INT;</span><br><span class="line"></span><br><span class="line">    DECLARE fixture_cursor CURSOR FOR</span><br><span class="line">        SELECT fixture_id, team1_id, team2_id</span><br><span class="line">        FROM worldcup_2026_fixtures</span><br><span class="line">        WHERE stage = &#x27;Group&#x27;</span><br><span class="line">        ORDER BY fixture_id;</span><br><span class="line"></span><br><span class="line">    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;</span><br><span class="line"></span><br><span class="line">    -- 计算联赛平均进球</span><br><span class="line">    SELECT AVG(goals_for / matches_played) INTO avg_goals_total</span><br><span class="line">    FROM team_season_stats</span><br><span class="line">    WHERE season_year = 2025;</span><br><span class="line"></span><br><span class="line">    -- 预计算球队系数（如果表为空才插入）</span><br><span class="line">    IF (SELECT COUNT(*) FROM team_params) = 0 THEN</span><br><span class="line">        INSERT INTO team_params</span><br><span class="line">        SELECT</span><br><span class="line">            t.team_id,</span><br><span class="line">            (t.goals_for / t.matches_played) / avg_goals_total,</span><br><span class="line">            (t.goals_against / t.matches_played) / avg_goals_total,</span><br><span class="line">            te.elo_rating</span><br><span class="line">        FROM team_season_stats t</span><br><span class="line">        JOIN teams te ON t.team_id = te.team_id</span><br><span class="line">        WHERE t.season_year = 2025;</span><br><span class="line">    END IF;</span><br><span class="line"></span><br><span class="line">    TRUNCATE TABLE tmp_champions;</span><br><span class="line"></span><br><span class="line">    WHILE sim_counter &lt; num_sims DO</span><br><span class="line">        SET sim_counter = sim_counter + 1;</span><br><span class="line">        SET done = 0;</span><br><span class="line"></span><br><span class="line">        TRUNCATE TABLE group_stats;</span><br><span class="line">        TRUNCATE TABLE group_ranking;</span><br><span class="line">        TRUNCATE TABLE round32;</span><br><span class="line">        TRUNCATE TABLE knockout_results;</span><br><span class="line"></span><br><span class="line">        -- 初始化小组赛队伍</span><br><span class="line">        INSERT INTO group_stats (team_id, group_char)</span><br><span class="line">        SELECT team_id, group_char</span><br><span class="line">        FROM (</span><br><span class="line">            SELECT team1_id AS team_id, group_char</span><br><span class="line">            FROM worldcup_2026_fixtures WHERE stage = &#x27;Group&#x27;</span><br><span class="line">            UNION</span><br><span class="line">            SELECT team2_id AS team_id, group_char</span><br><span class="line">            FROM worldcup_2026_fixtures WHERE stage = &#x27;Group&#x27;</span><br><span class="line">        ) t</span><br><span class="line">        GROUP BY team_id;</span><br><span class="line"></span><br><span class="line">        -- 游标模拟小组赛</span><br><span class="line">        OPEN fixture_cursor;</span><br><span class="line">        read_loop: LOOP</span><br><span class="line">            FETCH fixture_cursor INTO v_fixture_id, v_team1, v_team2;</span><br><span class="line">            IF done THEN</span><br><span class="line">                LEAVE read_loop;</span><br><span class="line">            END IF;</span><br><span class="line"></span><br><span class="line">            SELECT attack, defence INTO v_att1, v_def1 FROM team_params WHERE team_id = v_team1;</span><br><span class="line">            SELECT attack, defence INTO v_att2, v_def2 FROM team_params WHERE team_id = v_team2;</span><br><span class="line"></span><br><span class="line">            SET v_home_boost = IF(FIND_IN_SET(v_team1, host_ids) &gt; 0, home_advantage, 1.0);</span><br><span class="line">            SET v_lambda1 = avg_goals_total * v_att1 * v_def2 * v_home_boost;</span><br><span class="line">            SET v_lambda2 = avg_goals_total * v_att2 * v_def1;</span><br><span class="line"></span><br><span class="line">            SET v_home_goals = fn_poisson(v_lambda1);</span><br><span class="line">            SET v_away_goals = fn_poisson(v_lambda2);</span><br><span class="line"></span><br><span class="line">            UPDATE group_stats SET</span><br><span class="line">                goals_for = goals_for + v_home_goals,</span><br><span class="line">                goal_diff = goal_diff + (v_home_goals - v_away_goals),</span><br><span class="line">                points = points + CASE</span><br><span class="line">                    WHEN v_home_goals &gt; v_away_goals THEN 3</span><br><span class="line">                    WHEN v_home_goals = v_away_goals THEN 1</span><br><span class="line">                    ELSE 0</span><br><span class="line">                END</span><br><span class="line">            WHERE team_id = v_team1;</span><br><span class="line"></span><br><span class="line">            UPDATE group_stats SET</span><br><span class="line">                goals_for = goals_for + v_away_goals,</span><br><span class="line">                goal_diff = goal_diff + (v_away_goals - v_home_goals),</span><br><span class="line">                points = points + CASE</span><br><span class="line">                    WHEN v_away_goals &gt; v_home_goals THEN 3</span><br><span class="line">                    WHEN v_away_goals = v_home_goals THEN 1</span><br><span class="line">                    ELSE 0</span><br><span class="line">                END</span><br><span class="line">            WHERE team_id = v_team2;</span><br><span class="line"></span><br><span class="line">        END LOOP;</span><br><span class="line">        CLOSE fixture_cursor;</span><br><span class="line"></span><br><span class="line">        -- 小组排名</span><br><span class="line">        INSERT INTO group_ranking (team_id, group_char, points, goal_diff, goals_for, rank_in_group)</span><br><span class="line">        SELECT team_id, group_char, points, goal_diff, goals_for, rnk</span><br><span class="line">        FROM (</span><br><span class="line">            SELECT team_id, group_char, points, goal_diff, goals_for,</span><br><span class="line">                   ROW_NUMBER() OVER (PARTITION BY group_char ORDER BY points DESC, goal_diff DESC, goals_for DESC) AS rnk</span><br><span class="line">            FROM group_stats</span><br><span class="line">        ) ranked;</span><br><span class="line"></span><br><span class="line">        -- 32 强：小组前 2 名</span><br><span class="line">        INSERT INTO round32 (team_id, group_char, group_rank, points, goal_diff, goals_for)</span><br><span class="line">        SELECT team_id, group_char, rank_in_group, points, goal_diff, goals_for</span><br><span class="line">        FROM group_ranking</span><br><span class="line">        WHERE rank_in_group IN (1, 2);</span><br><span class="line"></span><br><span class="line">        -- 成绩最好的 8 个小组第三</span><br><span class="line">        INSERT INTO round32 (team_id, group_char, group_rank, points, goal_diff, goals_for)</span><br><span class="line">        SELECT team_id, group_char, rank_in_group, points, goal_diff, goals_for</span><br><span class="line">        FROM group_ranking</span><br><span class="line">        WHERE rank_in_group = 3</span><br><span class="line">        ORDER BY points DESC, goal_diff DESC, goals_for DESC</span><br><span class="line">        LIMIT 8;</span><br><span class="line"></span><br><span class="line">        -- 32 强赛对阵（按小组字母和排名排序后两两配对）</span><br><span class="line">        INSERT INTO knockout_results (team1_id, team2_id, round_name)</span><br><span class="line">        SELECT team_id, next_team, &#x27;Round of 32&#x27;</span><br><span class="line">        FROM (</span><br><span class="line">            SELECT team_id,</span><br><span class="line">                   LEAD(team_id) OVER (ORDER BY group_char, group_rank) AS next_team,</span><br><span class="line">                   ROW_NUMBER() OVER (ORDER BY group_char, group_rank) AS seq</span><br><span class="line">            FROM round32</span><br><span class="line">        ) tmp</span><br><span class="line">        WHERE seq % 2 = 1</span><br><span class="line">        LIMIT 16;</span><br><span class="line"></span><br><span class="line">        -- 模拟 32 强赛</span><br><span class="line">        UPDATE knockout_results k</span><br><span class="line">        JOIN team_params tp1 ON k.team1_id = tp1.team_id</span><br><span class="line">        JOIN team_params tp2 ON k.team2_id = tp2.team_id</span><br><span class="line">        SET k.winner_id = IF(</span><br><span class="line">            RAND() &lt; 1/(1+POW(10, (tp2.elo_rating - tp1.elo_rating)/400)),</span><br><span class="line">            k.team1_id, k.team2_id</span><br><span class="line">        )</span><br><span class="line">        WHERE k.round_name = &#x27;Round of 32&#x27; AND k.winner_id IS NULL;</span><br><span class="line"></span><br><span class="line">        -- 16 强赛</span><br><span class="line">        INSERT INTO knockout_results (team1_id, team2_id, round_name)</span><br><span class="line">        SELECT MAX(CASE WHEN pos%2=1 THEN winner_id END),</span><br><span class="line">               MAX(CASE WHEN pos%2=0 THEN winner_id END),</span><br><span class="line">               &#x27;Round of 16&#x27;</span><br><span class="line">        FROM (</span><br><span class="line">            SELECT winner_id, ROW_NUMBER() OVER (ORDER BY match_id) AS pos</span><br><span class="line">            FROM knockout_results WHERE round_name = &#x27;Round of 32&#x27;</span><br><span class="line">        ) t</span><br><span class="line">        GROUP BY FLOOR((pos+1)/2);</span><br><span class="line"></span><br><span class="line">        UPDATE knockout_results k</span><br><span class="line">        JOIN team_params tp1 ON k.team1_id = tp1.team_id</span><br><span class="line">        JOIN team_params tp2 ON k.team2_id = tp2.team_id</span><br><span class="line">        SET k.winner_id = IF(</span><br><span class="line">            RAND() &lt; 1/(1+POW(10, (tp2.elo_rating - tp1.elo_rating)/400)),</span><br><span class="line">            k.team1_id, k.team2_id</span><br><span class="line">        )</span><br><span class="line">        WHERE k.round_name = &#x27;Round of 16&#x27; AND k.winner_id IS NULL;</span><br><span class="line"></span><br><span class="line">        -- 8 强赛</span><br><span class="line">        INSERT INTO knockout_results (team1_id, team2_id, round_name)</span><br><span class="line">        SELECT MAX(CASE WHEN pos%2=1 THEN winner_id END),</span><br><span class="line">               MAX(CASE WHEN pos%2=0 THEN winner_id END),</span><br><span class="line">               &#x27;Quarter-Final&#x27;</span><br><span class="line">        FROM (</span><br><span class="line">            SELECT winner_id, ROW_NUMBER() OVER (ORDER BY match_id) AS pos</span><br><span class="line">            FROM knockout_results WHERE round_name = &#x27;Round of 16&#x27;</span><br><span class="line">        ) t</span><br><span class="line">        GROUP BY FLOOR((pos+1)/2);</span><br><span class="line"></span><br><span class="line">        UPDATE knockout_results k</span><br><span class="line">        JOIN team_params tp1 ON k.team1_id = tp1.team_id</span><br><span class="line">        JOIN team_params tp2 ON k.team2_id = tp2.team_id</span><br><span class="line">        SET k.winner_id = IF(</span><br><span class="line">            RAND() &lt; 1/(1+POW(10, (tp2.elo_rating - tp1.elo_rating)/400)),</span><br><span class="line">            k.team1_id, k.team2_id</span><br><span class="line">        )</span><br><span class="line">        WHERE k.round_name = &#x27;Quarter-Final&#x27; AND k.winner_id IS NULL;</span><br><span class="line"></span><br><span class="line">        -- 半决赛</span><br><span class="line">        INSERT INTO knockout_results (team1_id, team2_id, round_name)</span><br><span class="line">        SELECT MAX(CASE WHEN pos%2=1 THEN winner_id END),</span><br><span class="line">               MAX(CASE WHEN pos%2=0 THEN winner_id END),</span><br><span class="line">               &#x27;Semi-Final&#x27;</span><br><span class="line">        FROM (</span><br><span class="line">            SELECT winner_id, ROW_NUMBER() OVER (ORDER BY match_id) AS pos</span><br><span class="line">            FROM knockout_results WHERE round_name = &#x27;Quarter-Final&#x27;</span><br><span class="line">        ) t</span><br><span class="line">        GROUP BY FLOOR((pos+1)/2);</span><br><span class="line"></span><br><span class="line">        UPDATE knockout_results k</span><br><span class="line">        JOIN team_params tp1 ON k.team1_id = tp1.team_id</span><br><span class="line">        JOIN team_params tp2 ON k.team2_id = tp2.team_id</span><br><span class="line">        SET k.winner_id = IF(</span><br><span class="line">            RAND() &lt; 1/(1+POW(10, (tp2.elo_rating - tp1.elo_rating)/400)),</span><br><span class="line">            k.team1_id, k.team2_id</span><br><span class="line">        )</span><br><span class="line">        WHERE k.round_name = &#x27;Semi-Final&#x27; AND k.winner_id IS NULL;</span><br><span class="line"></span><br><span class="line">        -- 决赛</span><br><span class="line">        INSERT INTO knockout_results (team1_id, team2_id, round_name)</span><br><span class="line">        SELECT MIN(winner_id), MAX(winner_id), &#x27;Final&#x27;</span><br><span class="line">        FROM (</span><br><span class="line">            SELECT winner_id, ROW_NUMBER() OVER (ORDER BY match_id) AS pos</span><br><span class="line">            FROM knockout_results WHERE round_name = &#x27;Semi-Final&#x27;</span><br><span class="line">        ) t;</span><br><span class="line"></span><br><span class="line">        UPDATE knockout_results k</span><br><span class="line">        JOIN team_params tp1 ON k.team1_id = tp1.team_id</span><br><span class="line">        JOIN team_params tp2 ON k.team2_id = tp2.team_id</span><br><span class="line">        SET k.winner_id = IF(</span><br><span class="line">            RAND() &lt; 1/(1+POW(10, (tp2.elo_rating - tp1.elo_rating)/400)),</span><br><span class="line">            k.team1_id, k.team2_id</span><br><span class="line">        )</span><br><span class="line">        WHERE k.round_name = &#x27;Final&#x27; AND k.winner_id IS NULL;</span><br><span class="line"></span><br><span class="line">        SELECT winner_id INTO v_champion FROM knockout_results WHERE round_name = &#x27;Final&#x27; LIMIT 1;</span><br><span class="line">        INSERT INTO tmp_champions VALUES (sim_counter, v_champion);</span><br><span class="line"></span><br><span class="line">    END WHILE;</span><br><span class="line"></span><br><span class="line">    -- 输出结果表</span><br><span class="line">    SET @sql = CONCAT(&#x27;DROP TABLE IF EXISTS &#x27;, result_table);</span><br><span class="line">    PREPARE stmt FROM @sql;</span><br><span class="line">    EXECUTE stmt;</span><br><span class="line">    DEALLOCATE PREPARE stmt;</span><br><span class="line"></span><br><span class="line">    SET @sql = CONCAT(&#x27;CREATE TABLE &#x27;, result_table, &#x27; (team_id INT PRIMARY KEY, team_name VARCHAR(100), champion_count INT, champion_prob DECIMAL(10,4), simulations INT)&#x27;);</span><br><span class="line">    PREPARE stmt FROM @sql;</span><br><span class="line">    EXECUTE stmt;</span><br><span class="line">    DEALLOCATE PREPARE stmt;</span><br><span class="line"></span><br><span class="line">    SET @sql = CONCAT(&#x27;INSERT INTO &#x27;, result_table, &#x27;</span><br><span class="line">        SELECT team_id, team_name, champion_count, prob, &#x27;, num_sims, &#x27; FROM (</span><br><span class="line">            SELECT</span><br><span class="line">                t.team_id,</span><br><span class="line">                t.full_name AS team_name,</span><br><span class="line">                COUNT(*) AS champion_count,</span><br><span class="line">                ROUND(COUNT(*)/&#x27;, num_sims, &#x27;,4) AS prob</span><br><span class="line">            FROM tmp_champions c</span><br><span class="line">            JOIN teams t ON c.champion_id = t.team_id</span><br><span class="line">            GROUP BY t.team_id, t.full_name</span><br><span class="line">        ) tmp ORDER BY prob DESC&#x27;);</span><br><span class="line">    PREPARE stmt FROM @sql;</span><br><span class="line">    EXECUTE stmt;</span><br><span class="line">    DEALLOCATE PREPARE stmt;</span><br><span class="line"></span><br><span class="line">END //</span><br><span class="line"></span><br><span class="line">DELIMITER ;</span><br></pre></td></tr></table></figure><h2 id="往期内容推荐"><a href="#往期内容推荐" class="headerlink" title="往期内容推荐"></a>往期内容推荐</h2><p>了解更多</p><p>添加社区小助手，加入微信交流群~</p><p>seekdb · 目录</p><p>作者提示: 个人观点，仅供参考</p><p>阅读原文</p>]]>
    </content>
    <id>https://ilongda.com/2026/2026-06-22-seekdb-world-cup-prediction/</id>
    <link href="https://ilongda.com/2026/2026-06-22-seekdb-world-cup-prediction/"/>
    <published>2026-06-22T14:44:09.000Z</published>
    <summary>用 OceanBase seekdb 建模 2026 世界杯：Elo 与泊松分布生成赛果，蒙特卡洛模拟夺冠概率，完整展示 AI Native 数据分析实践。</summary>
    <title>用 seekdb 预测 2026 世界杯冠军：从数据建模到概率模拟</title>
    <updated>2026-06-22T14:44:09.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="技术详解" scheme="https://ilongda.com/categories/%E6%8A%80%E6%9C%AF%E8%AF%A6%E8%A7%A3/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="数据库运维" scheme="https://ilongda.com/tags/%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%90%E7%BB%B4/"/>
    <category term="物理备份" scheme="https://ilongda.com/tags/%E7%89%A9%E7%90%86%E5%A4%87%E4%BB%BD/"/>
    <category term="备份恢复" scheme="https://ilongda.com/tags/%E5%A4%87%E4%BB%BD%E6%81%A2%E5%A4%8D/"/>
    <category term="备份清理" scheme="https://ilongda.com/tags/%E5%A4%87%E4%BB%BD%E6%B8%85%E7%90%86/"/>
    <category term="OBServer" scheme="https://ilongda.com/tags/OBServer/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"OceanBase 备份空间清不掉？物理备份自动清理原理详解","description":"详解 OceanBase 物理备份保留策略、备份集依赖与自动清理：为何空间未按直觉释放，以及如何排查日志归档与可还原点问题。","image":"https://ilongda.com/img/2026-06-15-oceanbase-backup-cleanup/01.png","wordCount":6834,"datePublished":"2026-06-14T23:52:11.000Z","dateModified":"2026-06-14T23:52:11.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-06-15-oceanbase-backup-cleanup/"},"url":"https://ilongda.com/2026/2026-06-15-oceanbase-backup-cleanup/","inLanguage":"zh-CN","keywords":["OceanBase","数据库运维","物理备份","备份恢复","备份清理","OBServer"],"articleSection":["技术详解"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"技术详解","item":"https://ilongda.com/categories/技术详解/"},{"@type":"ListItem","position":3,"name":"OceanBase 备份空间清不掉？物理备份自动清理原理详解","item":"https://ilongda.com/2026/2026-06-15-oceanbase-backup-cleanup/"}]}</script><blockquote><p>来源：微信公众号「数据库技术闲谈」<br>原文链接：<a href="https://mp.weixin.qq.com/s/clUMLLVIUWQSCYfJjhj6xQ">OceanBase 奇案：是谁清理了我备份的数据？</a></p></blockquote><h2 id="楔子"><a href="#楔子" class="headerlink" title="楔子"></a>楔子</h2><p>本文由庆涛大佬，带大家“逐帧”分析 OceanBase 备份的自动清理原理。</p><p>一句话先说清问题：OceanBase 明明开了备份自动清理，为什么空间还是降不下来？答案往往不在“保留天数”本身，而在备份集依赖、日志归档链路，以及可还原时间点（RPO）怎么定义。</p><p>对于 OceanBase 运维专家来说，这套原理并不难；但对习惯 Oracle &#x2F; MySQL 备份思路的传统 DBA，看完可能会觉得“跟原来不太一样，还挺有意思”。</p><p>通常来说，使用 OceanBase 有主备库和备份恢复两道安全机制。备份在日常运维里占比不高，真要靠它恢复时才会被想起来。今天不聊怎么恢复，而聊更少被提起、却很贵的话题：备份空间为什么按直觉“过期了”却清不掉。</p><span id="more"></span><p>大部分客户都会直接给 OceanBase 分配几 TB 的备份空间，而且只在少数场景才会盯使用率：一是 PoC 考察自动清理，二是云上备份账单突然变高的时候。</p><p>OceanBase 的备份有自动清理功能，很多人会把它理解成“过了保留期就删文件”。实际清理行为没这么简单。当客户对备份空间锱铢必较时，就会发现：有些备份看起来不需要了，却还在。</p><p>本文接下来会逐一说明 OceanBase 物理备份和空间清理的原理与现象。</p><blockquote><p>说明：本文中的备份，特指物理备份。</p><p>社区运营小编曾经在 OB 很低的版本中，支持过通过备份 SQL 来进行逻辑备份，然后通过 SQL 回放来进行逻辑恢复。不过从 3.x 版本开始，又把逻辑备份全面优化成了物理备份。本文仅讨论物理备份。</p><p>很低的版本指 OB 1.x ~ 2.x，大多数来自 OB 社区的读者应该都没听说过这些版本，所以这段历史可以直接忽略，不必细究。</p></blockquote><p>OceanBase 的数据，包括业务数据和数据变化的日志（WAL 日志或 REDO 日志），OceanBase 的备份自然包括数据备份和日志备份。虽然终端用户只关心数据，但是数据库的设计里，WAL 日志就是数据安全，多副本复制和高可用的必不可少的成本。在 OLAP 业务里，这个日志的成本可能还会非常的突出。</p><p>OceanBase 的备份配置可以通过 SQL 配置，也可以在 OCP 里配置（集群备份或者租户备份，后者覆盖前者），或者在第三方备份产品里配置。注意：这三个途径是彼此冲突的，特别是后面两个途径。</p><h2 id="OceanBase-备份理论知识"><a href="#OceanBase-备份理论知识" class="headerlink" title="OceanBase 备份理论知识"></a>OceanBase 备份理论知识</h2><p>OceanBase 的备份策略配置相比 ORACLE 要相对复杂一些，因为需要先了解相关的理论。</p><p>OceanBase 是分布式架构，每个节点都有可能需要备份到相同的路径，所以备份介质通常是 NFS 路径挂载到本地文件系统，实现多个节点共享访问。共享访问是要点，这个 NFS 在客户那边一般是通过 NAS 存储提供，少数通过独立的服务器做 NFS Server 提供。还有一部分是第三方备份产品提供。NFS 备份介质一般性能都不错，风险是 NFS 路径必须保持高可用。如果 NFS 路径不可用会导致备份异常，所有 OceanBase 主机上的备份的文件系统访问也会出现 HANG。这个在传统数据库的备份里一样存在。</p><p>所以，OceanBase 的备份更推荐是对象存储，通过 OSS 或 S3 协议访问，OceanBase 节点跟备份介质没有直接的物理联系，而且对象存储的备份 IO 性能通常相对差一些。对象存储的备份问题也不少，特别是市面上有很多种国产对象存储，它们实现的协议并不完全一致。这个后面单独写一篇文章，来给大家阐述。</p><p>备份介质可以是 SATA SSD 或者 HDD，或者二者混合存储，在性能和成本之间取一个平衡。通常来说备份在凌晨低峰期发起，持续时间在 5h 以内完成都是安全的，更长的时间可能导致白天业务高峰期时备份还在跑。</p><p>OceanBase 的架构分集群和租户两层，所以备份策略的配置入口支持集群和租户两个。但是实际备份的实体是租户，不是集群。集群里配置的是所有租户的备份策略，也可以指定特定租户的备份策略。租户里配置的是本租户的备份策略。</p><p>OceanBase 的备份分数据备份和日志备份，这两个备份策略还不能相同，需要分别配置。并且必须配置日志备份并启动日志备份，数据备份的配置才能发挥作用。日志备份启动后就是 OceanBase 自动调度做的，平均 2 分钟一次，是近实时备份。OceanBase 把这个也叫日志归档，实时是它的优点。数据备份不会自动调度，需要手动触发，通常通过 OCP 调度。</p><p>在 4.2.5 以及以后版本，OceanBase 的数据备份可以发起多次，但在一个周期（24h）内发起的多次数据备份其内容很可能是完全一样的，都是租户最近一次合并产生的数据快照。所以有时候客户会说一会业务要做一个重大发布，先把数据库“物理备份”一下。这个想法放在传统 ORACLE 数据库里有意义，在 OceanBase 里很可能毫无意义。除非记得在再次备份之前先对租户发起一个“合并”操作。先合并成功，再做数据备份是有意义的。所以，合并和备份的调度时间要做好规划。尽力保证数据全量备份只会在合并成功后才进行。</p><p>数据备份又细分为全量备份和增量备份。增量备份记录的是距离最近的全量备份或增量备份以后数据变化的部分。这里不像 ORACLE RMAN 还有累积增量备份概念。日志备份记录的是 WAL 日志，也就是数据变化的过程日志。日志备份有增量的效果，实际沟通中可能会跟增量备份混淆，所以表述备份一定要准确。关于增量，举个例子：一张表插入 1000 万数据，然后没多久就删除了这 1000 万数据，假设随后凌晨发生的是增量备份，那么增量备份里跟这个表有关的数据块大小没有什么变化。但是日志备份里会有这 1000 万数据的插入日志和删除日志。 默认情况下，不推荐用数据备份的增量备份。因为可能引来备份空间膨胀问题。后面会阐述。</p><p>OceanBase 的日志备份以流的形式备份，默认一段日志被备份后就不会再次被备份，所以日志备份文件要保证时间线上的连贯。如果中间中断了，那么这个日志备份就不能用于还原到这个任意时间点了。因为“链条断了”。备份文件的丢失，或者日志备份启动后又停止了，都会造成日志备份流的断流。日志备份就是备份租户的日志流（Log Stream）。租户的日志流没有启停的说法，也没有断流的说法，只是备份有这个。这是 OceanBase 跟 ORACLE 和 MYSQL 一个显著的区别。在 ORACLE 里，备份归档文件如果丢了，到其他地方去找一个回来就可以弥补，但是在 OceanBase 里不一定能行。官方没有这种功能介绍，我也没有做过这种测试）。日志备份每次启动称为一个 Round，数字会加 1 。日志流的备份还有个 piece 的概念，姑且翻译为分片 。日志备份参数里会指定日志流的备份多久切换一个分片，取值范围是 [1d,7d]。粒度就是天，不支持更小，最小 1 天。这个非常重要，强烈建议设置为 1 天。后面也会阐述。</p><p><img src="/img/2026-06-15-oceanbase-backup-cleanup/01.png" alt="OceanBase 数据备份与日志备份架构" decoding="async"></p><p><em>图：OceanBase 备份架构全景（数据备份 + 日志备份 + Round + Piece）</em></p><p>备份的保留策略，通常谈的是备份保留天数，这个说起来比较好理解。但是在 OceanBase 里这样沟通备份策略是错误的。 备份应该保留多少天，不是说保留多少天就是多少天，而是根据备份的目标定的。备份的目的是用于还原，所以真正的运维需求是保留的备份能用于还原的最早还原时间点。可以理解为这个点是 RPO 的最大值。通常我们说 OceanBase 高可用能力做到 RPO&#x3D;0，另外一种需求就是还原数据库到某个历史时间点，那就是 RPO&gt;0，备份的保留就是让这个 RPO 尽可能大，满足客户的还原需求。所以，跟客户沟通的不应该是备份的保留天数是多少，而是客户期望的 RPO 最大是多大。</p><p>比如说 OCP 产品里默认的备份策略说“保留天数”是 7 天。这个是不严谨的，极大的误导了客户。</p><p><img src="/img/2026-06-15-oceanbase-backup-cleanup/02.png" alt="OCP 备份保留策略配置界面" loading="lazy" decoding="async"></p><p><em>图：OCP 备份策略</em></p><p>实际上 OCP 说的是备份保留能满足还原 RPO 等于 7天 。那么实际保留的备份天数一定会大于 7 天，最糟糕的情形是会保留 14 天的备份。</p><p>为了弥补产品 OCP 上这个“保留天数”带来的误解，OCP 产品文档详细的描述了这个 OceanBase 备份保留参数 <code>recovery_window</code> 的计算逻辑 （相当于文档给产品打了个补丁）。（从 OceanBase 参数的命名也能看出内核研发想表达的也是跟还原目标有关的意思。）</p><p>文档地址：<a href="https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001499877">https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001499877</a> 这里我直接贴文档的解释：</p><p><img src="/img/2026-06-15-oceanbase-backup-cleanup/03.jpg" alt="备份集依赖与可还原时间点关系" loading="lazy" decoding="async"></p><p><em>图：OceanBase 的 recovery_window 参数</em></p><h2 id="OceanBase-备份目录分析"><a href="#OceanBase-备份目录分析" class="headerlink" title="OceanBase 备份目录分析"></a>OceanBase 备份目录分析</h2><p>首先是数据备份的配置。下面主要演示 SQL 命令行配置方法， OCP 和 第三方备份产品的备份都是发 SQL 完成。</p><p>租户备份路径查看：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">select tenant_id, path,dest_id,dest_type,CHECK_FILE_NAME ,LAST_CHECK_TIMESTAMP from oceanbase.DBA_OB_BACKUP_STORAGE_INFO \G</span><br><span class="line">*************************** 1. row ***************************</span><br><span class="line">           tenant_id: 1002</span><br><span class="line">                path: file:///nfs-server/ob***/obbackup01/***ob/1767617455/tenant_incarnation_1/1002/clog</span><br><span class="line">             dest_id: 1001</span><br><span class="line">           dest_type: archive_log</span><br><span class="line">     CHECK_FILE_NAME: 1002_connect_file_20260107T112233.obbak</span><br><span class="line">LAST_CHECK_TIMESTAMP: 2026-01-07 11:23:06.461397</span><br><span class="line">*************************** 2. row ***************************</span><br><span class="line">           tenant_id: 1002</span><br><span class="line">                path: file:///nfs-server/ob***/obbackup01/***ob/1767617455/tenant_incarnation_1/1002/data</span><br><span class="line">             dest_id: 1002</span><br><span class="line">           dest_type: backup_data</span><br><span class="line">     CHECK_FILE_NAME: 1002_connect_file_20260107T112233.obbak</span><br><span class="line">LAST_CHECK_TIMESTAMP: 2026-06-10 04:00:33.454802</span><br></pre></td></tr></table></figure><p>从这里能看到数据备份和日志备份的路径默认是分开的。这个 <code>dest_id</code> 值（1001 和 1002）后面有用。这个路径很长，命名有一定规范，这些是 OCP 的行为，不是 OceanBase 的行为。所以不是一定要写成这样，但是这样确实规范很多，特别是有很多 OceanBase 集群和租户要备份的时候。</p><p>查看数据备份路径特点：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">--- /nfs-server/ob***/obbackup01/***ob/1767617455/tenant_incarnation_1/1002/data ------------------</span><br><span class="line">                                               2026-06-10 04:26:03 +0800 /..</span><br><span class="line">238.7 GiB [########################]    285  2026-06-10 04:26:03 +0800 /backup_set_158_full</span><br><span class="line">236.0 GiB [####################### ]    282  2026-06-09 04:30:35 +0800 /backup_set_157_full</span><br><span class="line">  2.0 KiB [                        ]      4  2026-06-10 04:26:03 +0800 /backup_sets</span><br><span class="line">512.0   B [                        ]         2026-01-07 11:22:33 +0800  format.obbak</span><br><span class="line">512.0   B [                        ]      1  2026-01-07 11:22:33 +0800 /check_file</span><br></pre></td></tr></table></figure><p>这个备份目录特点：</p><ul><li>下面有个文件 <code>format.obbak</code> 和 <code>check_file</code> 目录，表示这是一个备份目录。不要去删这两个文件（目录）。</li><li>以 <code>backup_set_数字_full</code> 命名的大文件夹就是备份文件夹，每次全量备份一个文件夹（增量备份也是一个文件夹，关键字 <code>incr</code> 替换 <code>full</code>）。</li></ul><p>现在看到的是空间优化后的结果，之前这里最多的时候有 14 个文件夹。这种场景往往是备份策略设置每周一个全备，其他全是增量备份。</p><p>上面是数据备份目录，再看看日志备份目录，稍微复杂一些。</p><p><img src="/img/2026-06-15-oceanbase-backup-cleanup/04.png" alt="OceanBase 备份目录层级结构示意" loading="lazy" decoding="async"></p><p><em>图：OceanBase NFS 备份目录结构（data + clog + piece + logstream）</em></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">--- /nfs-server/ob***/obbackup01/***ob/1767617455/tenant_incarnation_1/1002/clog ------------------------------------------------</span><br><span class="line">                                               2026-06-10 17:22:11 +0800 /..</span><br><span class="line">  3.1 TiB [########################] 50,660  2026-06-09 11:26:16 +0800 /piece_d1001r1p153</span><br><span class="line">  2.8 TiB [#####################   ] 45,730  2026-06-10 11:25:48 +0800 /piece_d1001r1p154</span><br><span class="line">558.1 GiB [####                    ]  8,949  2026-06-10 17:22:11 +0800 /piece_d1001r1p155</span><br><span class="line">  2.5 KiB [                        ]      5  2026-06-10 11:25:48 +0800 /pieces</span><br><span class="line">512.0   B [                        ]         2026-01-07 11:22:33 +0800  format.obbak</span><br><span class="line">512.0   B [                        ]      1  2026-01-07 11:22:33 +0800 /check_file</span><br><span class="line">512.0   B [                        ]      1  2026-01-07 11:23:16 +0800 /rounds</span><br></pre></td></tr></table></figure><p>这个备份目录特点：</p><ul><li>下面有个文件 <code>format.obbak</code> 和 <code>check_file</code> 目录，表示这是一个备份目录。不要去删这两个文件（目录）。</li><li>以 <code>piece_d数字r数字p数字</code> 命名的文件夹就是日志备份，每个文件夹表示一个日志分片(piece）的备份，p 后面的数字就表示当前这个日志分片编号。d 后面的数字表示这是日志备份，r 后面的数字表示启动日志备份的次数。通常是 1 ，如果你反复停止和启动日志备份，这个数字会累加。</li></ul><p>这里变化的通常是分片数字。我这里的环境是每天切换一个日志备份分片。至于切换的时间点（时分秒）并不是想象的整点，或者根本无法设置切换的时间点。实际切换时间点就是由启动成功日志备份的时间决定的。所以，1000 个 OceanBase 客户，就有 1000 个 OceanBase 日志备份分片切换时间点（时分秒）。我很难认为这是一个很好的设计。</p><p>如果只是分析日志备份空间清理问题，目录看到这一层就够了。不过到这里我们就多看一点。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">--- /nfs-server/ob***/obbackup01/***ob/1767617455/tenant_incarnation_1/1002/clog/piece_d1001r1p154 -----------------------------------------------------------------------</span><br><span class="line">                                               2026-06-10 11:25:48 +0800 /..</span><br><span class="line">972.5 GiB [########################] 15,563  2026-06-10 11:25:48 +0800 /logstream_1003</span><br><span class="line">956.3 GiB [####################### ] 15,305  2026-06-10 11:25:45 +0800 /logstream_1002</span><br><span class="line">922.2 GiB [######################  ] 14,758  2026-06-10 11:25:42 +0800 /logstream_1001</span><br><span class="line">  4.8 GiB [                        ]     93  2026-06-10 11:25:39 +0800 /logstream_15</span><br><span class="line"> 80.5 KiB [                        ]         2026-06-10 11:25:48 +0800  file_info.obarc</span><br><span class="line">  1.0 KiB [                        ]         2026-06-09 11:26:17 +0800  tenant_archive_piece_infos.obarc</span><br><span class="line">512.0   B [                        ]         2026-06-10 11:25:48 +0800  single_piece_info.obarc</span><br><span class="line">512.0   B [                        ]      2  2026-06-10 11:24:48 +0800 /checkpoint</span><br><span class="line">512.0   B [                        ]         2026-06-10 11:25:48 +0800  piece_d1001r1p154_20260609T112316_20260610T112316.obarc</span><br></pre></td></tr></table></figure><p>这里看的是一个具体的日志备份分片目录细节，<code>logstream_数字</code> 文件夹表示的就是日志流的备份，看来日志备份是以日志流为单位去组织存储的。租户的日志流可能有 1~4 个，这个以前介绍过。日志的备份是根据 OceanBase 文档描述是优先选择日志流的备副本所在节点（数据备份也是如此）。</p><h2 id="备份空间清理分析"><a href="#备份空间清理分析" class="headerlink" title="备份空间清理分析"></a>备份空间清理分析</h2><p>首先查看当前的备份参数 <code>recovery_window</code> 设置（或者叫备份还原的 RPO 目标值。我尽量不用那个词不达意的保留天数）。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">SELECT policy_name, RECOVERY_WINDOW  FROM oceanbase.DBA_OB_BACKUP_DELETE_POLICY \G</span><br><span class="line">*************************** 1. row ***************************</span><br><span class="line">    policy_name: default</span><br><span class="line">RECOVERY_WINDOW: 1d</span><br></pre></td></tr></table></figure><p>最早是 7d，后来空间太大了，改为 3d ，还是很大，最后改为 1d ，不能再小了。</p><p>然后查看备份清理任务。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br></pre></td><td class="code"><pre><span class="line">select job_id, type, PARAMETER ,START_TIMESTAMP ,END_TIMESTAMP ,STATUS , concat(SUCCESS_TASK_COUNT ,&#x27; / &#x27;, task_count ) task_info from oceanbase.DBA_OB_BACKUP_DELETE_JOB_HISTORY WHERE 1=1 order by job_id desc limit 15 \G</span><br><span class="line">*************************** 1. row ***************************</span><br><span class="line">         job_id: 3859</span><br><span class="line">           type: DELETE OBSOLETE BACKUP</span><br><span class="line">      PARAMETER: 2026-06-09 17:55:40.561998</span><br><span class="line">START_TIMESTAMP: 2026-06-10 17:55:40.562762</span><br><span class="line">  END_TIMESTAMP: 2026-06-10 17:55:40.584452</span><br><span class="line">         STATUS: COMPLETED</span><br><span class="line">      task_info: 0 / 0</span><br><span class="line">*************************** 2. row ***************************</span><br><span class="line">         job_id: 3858</span><br><span class="line">           type: DELETE OBSOLETE BACKUP</span><br><span class="line">      PARAMETER: 2026-06-09 16:55:40.406901</span><br><span class="line">START_TIMESTAMP: 2026-06-10 16:55:40.407672</span><br><span class="line">  END_TIMESTAMP: 2026-06-10 16:55:40.424844</span><br><span class="line">         STATUS: COMPLETED</span><br><span class="line">      task_info: 0 / 0</span><br><span class="line">*************************** 3. row ***************************</span><br><span class="line">         job_id: 3857</span><br><span class="line">           type: DELETE OBSOLETE BACKUP</span><br><span class="line">      PARAMETER: 2026-06-09 15:55:40.252236</span><br><span class="line">START_TIMESTAMP: 2026-06-10 15:55:40.253079</span><br><span class="line">  END_TIMESTAMP: 2026-06-10 15:55:40.271519</span><br><span class="line">         STATUS: COMPLETED</span><br><span class="line">      task_info: 0 / 0</span><br><span class="line">*************************** 4. row ***************************</span><br><span class="line">         job_id: 3856</span><br><span class="line">           type: DELETE OBSOLETE BACKUP</span><br><span class="line">      PARAMETER: 2026-06-09 14:55:40.095898</span><br><span class="line">START_TIMESTAMP: 2026-06-10 14:55:40.096637</span><br><span class="line">  END_TIMESTAMP: 2026-06-10 14:55:40.118587</span><br><span class="line">         STATUS: COMPLETED</span><br><span class="line">      task_info: 0 / 0</span><br><span class="line">*************************** 5. row ***************************</span><br><span class="line">         job_id: 3855</span><br><span class="line">           type: DELETE OBSOLETE BACKUP</span><br><span class="line">      PARAMETER: 2026-06-09 13:55:39.943337</span><br><span class="line">START_TIMESTAMP: 2026-06-10 13:55:39.944174</span><br><span class="line">  END_TIMESTAMP: 2026-06-10 13:55:39.965111</span><br><span class="line">         STATUS: COMPLETED</span><br><span class="line">      task_info: 0 / 0</span><br><span class="line">*************************** 6. row ***************************</span><br><span class="line">         job_id: 3854</span><br><span class="line">           type: DELETE OBSOLETE BACKUP</span><br><span class="line">      PARAMETER: 2026-06-09 12:55:39.787493</span><br><span class="line">START_TIMESTAMP: 2026-06-10 12:55:39.788274</span><br><span class="line">  END_TIMESTAMP: 2026-06-10 12:55:39.805527</span><br><span class="line">         STATUS: COMPLETED</span><br><span class="line">      task_info: 0 / 0</span><br><span class="line">*************************** 7. row ***************************</span><br><span class="line">         job_id: 3853</span><br><span class="line">           type: DELETE OBSOLETE BACKUP</span><br><span class="line">      PARAMETER: 2026-06-09 11:55:39.631708</span><br><span class="line">START_TIMESTAMP: 2026-06-10 11:55:39.632641</span><br><span class="line">  END_TIMESTAMP: 2026-06-10 11:55:39.652143</span><br><span class="line">         STATUS: COMPLETED</span><br><span class="line">      task_info: 0 / 0</span><br><span class="line">*************************** 8. row ***************************</span><br><span class="line">         job_id: 3852</span><br><span class="line">           type: DELETE OBSOLETE BACKUP</span><br><span class="line">      PARAMETER: 2026-06-09 10:55:39.441597</span><br><span class="line">START_TIMESTAMP: 2026-06-10 10:55:39.442838</span><br><span class="line">  END_TIMESTAMP: 2026-06-10 10:55:39.491902</span><br><span class="line">         STATUS: COMPLETED</span><br><span class="line">      task_info: 0 / 0</span><br><span class="line">*************************** 9. row ***************************</span><br><span class="line">         job_id: 3851</span><br><span class="line">           type: DELETE OBSOLETE BACKUP</span><br><span class="line">      PARAMETER: 2026-06-09 09:55:39.281553</span><br><span class="line">START_TIMESTAMP: 2026-06-10 09:55:39.282451</span><br><span class="line">  END_TIMESTAMP: 2026-06-10 09:55:39.304357</span><br><span class="line">         STATUS: COMPLETED</span><br><span class="line">      task_info: 0 / 0</span><br><span class="line">*************************** 10. row ***************************</span><br><span class="line">         job_id: 3850</span><br><span class="line">           type: DELETE OBSOLETE BACKUP</span><br><span class="line">      PARAMETER: 2026-06-09 08:55:39.127329</span><br><span class="line">START_TIMESTAMP: 2026-06-10 08:55:39.128209</span><br><span class="line">  END_TIMESTAMP: 2026-06-10 08:55:39.151443</span><br><span class="line">         STATUS: COMPLETED</span><br><span class="line">      task_info: 0 / 0</span><br><span class="line">*************************** 11. row ***************************</span><br><span class="line">         job_id: 3849</span><br><span class="line">           type: DELETE OBSOLETE BACKUP</span><br><span class="line">      PARAMETER: 2026-06-09 07:55:38.970745</span><br><span class="line">START_TIMESTAMP: 2026-06-10 07:55:38.971699</span><br><span class="line">  END_TIMESTAMP: 2026-06-10 07:55:38.992953</span><br><span class="line">         STATUS: COMPLETED</span><br><span class="line">      task_info: 0 / 0</span><br><span class="line">*************************** 12. row ***************************</span><br><span class="line">         job_id: 3848</span><br><span class="line">           type: DELETE OBSOLETE BACKUP</span><br><span class="line">      PARAMETER: 2026-06-09 06:55:38.812554</span><br><span class="line">START_TIMESTAMP: 2026-06-10 06:55:38.813549</span><br><span class="line">  END_TIMESTAMP: 2026-06-10 06:55:38.832302</span><br><span class="line">         STATUS: COMPLETED</span><br><span class="line">      task_info: 0 / 0</span><br><span class="line">*************************** 13. row ***************************</span><br><span class="line">         job_id: 3847</span><br><span class="line">           type: DELETE OBSOLETE BACKUP</span><br><span class="line">      PARAMETER: 2026-06-09 05:55:38.645012</span><br><span class="line">START_TIMESTAMP: 2026-06-10 05:55:38.645994</span><br><span class="line">  END_TIMESTAMP: 2026-06-10 05:55:38.674352</span><br><span class="line">         STATUS: COMPLETED</span><br><span class="line">      task_info: 0 / 0</span><br><span class="line">*************************** 14. row ***************************</span><br><span class="line">         job_id: 3846</span><br><span class="line">           type: DELETE OBSOLETE BACKUP</span><br><span class="line">      PARAMETER: 2026-06-09 04:55:32.715925</span><br><span class="line">START_TIMESTAMP: 2026-06-10 04:55:32.716860</span><br><span class="line">  END_TIMESTAMP: 2026-06-10 04:56:08.496986</span><br><span class="line">         STATUS: COMPLETED</span><br><span class="line">      task_info: 1 / 1</span><br><span class="line">*************************** 15. row ***************************</span><br><span class="line">         job_id: 3844</span><br><span class="line">           type: DELETE OBSOLETE BACKUP</span><br><span class="line">      PARAMETER: 2026-06-09 03:55:32.551669</span><br><span class="line">START_TIMESTAMP: 2026-06-10 03:55:32.552715</span><br><span class="line">  END_TIMESTAMP: 2026-06-10 03:55:32.577311</span><br><span class="line">         STATUS: COMPLETED</span><br><span class="line">      task_info: 0 / 0</span><br></pre></td></tr></table></figure><p>从这里可以看到每个小时，OceanBase 自动启动备份清理任务（不是 OCP 启动），这个时间点（时分秒）也很有规律，都在每个小时的 55 分左右，为什么会这样我还没有找到。</p><p>其次，虽然每小时都在跑清理任务，但是并不是每次任务都真的清理了数据。大部分的 <code>task_count</code> 都是 0 。最近的是 4 点 55 分左右清理的。因为全量备份启动时间是 4 点，大概 4 点 30 分左右全量备份结束了。因此按照前面的理论计算，为了实现 RPO 为 1 天，更早的数据备份以及部分日志备份应该被清理掉。所以 4 点 55 分的清理可以理解。</p><p>但是此后的每次清理却没有实际清理备份，这个就很奇怪了。 理论上说，随着时间的推进，总会有日志备份不再被需要而被清理。除非是在前面被一次性清理掉了。一次性清理掉也是符合预期的，因为仅凭最早的日志备份是不能用于还原的，所以在新的数据备份产生的时候，就意味着最早的数据备份以及随后的日志备份都处于不被需要的状态（obsolete）。</p><p>不过我们不用猜测，可以实际看看清理了什么。</p><p><img src="/img/2026-06-15-oceanbase-backup-cleanup/05.png" alt="备份空间未按预期释放的排查思路" loading="lazy" decoding="async"></p><p><em>图：OceanBase 备份清理机制（每小时触发 + piece 粒度淘汰）</em></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br></pre></td><td class="code"><pre><span class="line">select task_id, job_id, TASK_TYPE , ROUND_ID ,DEST_ID ,START_TIMESTAMP ,END_TIMESTAMP , status, FINISH_LS_COUNT ,RESULT , PATH from oceanbase.DBA_OB_BACKUP_DELETE_TASK_HISTORY where 1=1 order by job_id desc ,TASK_ID  desc limit 10 \G</span><br><span class="line">*************************** 1. row ***************************</span><br><span class="line">        task_id: 466</span><br><span class="line">         job_id: 3846</span><br><span class="line">      TASK_TYPE: BACKUP SET</span><br><span class="line">       ROUND_ID: 0</span><br><span class="line">        DEST_ID: 1002</span><br><span class="line">START_TIMESTAMP: 2026-06-10 04:55:32.744342</span><br><span class="line">  END_TIMESTAMP: 2026-06-10 04:56:08.480831</span><br><span class="line">         status: COMPLETED</span><br><span class="line">FINISH_LS_COUNT: 4</span><br><span class="line">         RESULT: 0</span><br><span class="line">           PATH: file:///nfs-server/ob***/obbackup01/***ob/1767617455/tenant_incarnation_1/1002/data</span><br><span class="line">*************************** 2. row ***************************</span><br><span class="line">        task_id: 464</span><br><span class="line">         job_id: 3836</span><br><span class="line">      TASK_TYPE: BACKUP PIECE</span><br><span class="line">       ROUND_ID: 1</span><br><span class="line">        DEST_ID: 1001</span><br><span class="line">START_TIMESTAMP: 2026-06-09 19:55:19.774380</span><br><span class="line">  END_TIMESTAMP: 2026-06-09 20:10:01.147932</span><br><span class="line">         status: COMPLETED</span><br><span class="line">FINISH_LS_COUNT: 4</span><br><span class="line">         RESULT: 0</span><br><span class="line">           PATH: file:///nfs-server/ob***/obbackup01/***ob/1767617455/tenant_incarnation_1/1002/clog</span><br><span class="line">*************************** 3. row ***************************</span><br><span class="line">        task_id: 463</span><br><span class="line">         job_id: 3836</span><br><span class="line">      TASK_TYPE: BACKUP SET</span><br><span class="line">       ROUND_ID: 0</span><br><span class="line">        DEST_ID: 1002</span><br><span class="line">START_TIMESTAMP: 2026-06-09 19:55:19.756638</span><br><span class="line">  END_TIMESTAMP: 2026-06-09 19:55:55.752544</span><br><span class="line">         status: COMPLETED</span><br><span class="line">FINISH_LS_COUNT: 4</span><br><span class="line">         RESULT: 0</span><br><span class="line">           PATH: file:///nfs-server/ob***/obbackup01/***ob/1767617455/tenant_incarnation_1/1002/data</span><br><span class="line">*************************** 4. row ***************************</span><br><span class="line">        task_id: 462</span><br><span class="line">         job_id: 3821</span><br><span class="line">      TASK_TYPE: BACKUP PIECE</span><br><span class="line">       ROUND_ID: 1</span><br><span class="line">        DEST_ID: 1001</span><br><span class="line">START_TIMESTAMP: 2026-06-09 04:55:07.895869</span><br><span class="line">  END_TIMESTAMP: 2026-06-09 05:01:47.202273</span><br><span class="line">         status: COMPLETED</span><br><span class="line">FINISH_LS_COUNT: 4</span><br><span class="line">         RESULT: 0</span><br><span class="line">           PATH: file:///nfs-server/ob***/obbackup01/***ob/1767617455/tenant_incarnation_1/1002/clog</span><br><span class="line">*************************** 5. row ***************************</span><br><span class="line">        task_id: 461</span><br><span class="line">         job_id: 3821</span><br><span class="line">      TASK_TYPE: BACKUP SET</span><br><span class="line">       ROUND_ID: 0</span><br><span class="line">        DEST_ID: 1002</span><br><span class="line">START_TIMESTAMP: 2026-06-09 04:55:07.881379</span><br><span class="line">  END_TIMESTAMP: 2026-06-09 04:55:43.285124</span><br><span class="line">         status: COMPLETED</span><br><span class="line">FINISH_LS_COUNT: 4</span><br><span class="line">         RESULT: 0</span><br><span class="line">           PATH: file:///nfs-server/ob***/obbackup01/***ob/1767617455/tenant_incarnation_1/1002/data</span><br><span class="line">*************************** 6. row ***************************</span><br><span class="line">        task_id: 458</span><br><span class="line">         job_id: 3805</span><br><span class="line">      TASK_TYPE: BACKUP PIECE</span><br><span class="line">       ROUND_ID: 1</span><br><span class="line">        DEST_ID: 1001</span><br><span class="line">START_TIMESTAMP: 2026-06-08 14:54:51.926005</span><br><span class="line">  END_TIMESTAMP: 2026-06-08 15:12:35.393356</span><br><span class="line">         status: COMPLETED</span><br><span class="line">FINISH_LS_COUNT: 4</span><br><span class="line">         RESULT: 0</span><br><span class="line">           PATH: file:///nfs-server/ob***/obbackup01/***ob/1767617455/tenant_incarnation_1/1002/clog</span><br><span class="line">*************************** 7. row ***************************</span><br><span class="line">        task_id: 457</span><br><span class="line">         job_id: 3805</span><br><span class="line">      TASK_TYPE: BACKUP SET</span><br><span class="line">       ROUND_ID: 0</span><br><span class="line">        DEST_ID: 1002</span><br><span class="line">START_TIMESTAMP: 2026-06-08 14:54:51.910983</span><br><span class="line">  END_TIMESTAMP: 2026-06-08 14:55:28.670751</span><br><span class="line">         status: COMPLETED</span><br><span class="line">FINISH_LS_COUNT: 4</span><br><span class="line">         RESULT: 0</span><br><span class="line">           PATH: file:///nfs-server/ob***/obbackup01/***ob/1767617455/tenant_incarnation_1/1002/data</span><br><span class="line">*************************** 8. row ***************************</span><br><span class="line">        task_id: 456</span><br><span class="line">         job_id: 3795</span><br><span class="line">      TASK_TYPE: BACKUP PIECE</span><br><span class="line">       ROUND_ID: 1</span><br><span class="line">        DEST_ID: 1001</span><br><span class="line">START_TIMESTAMP: 2026-06-08 04:54:27.779813</span><br><span class="line">  END_TIMESTAMP: 2026-06-08 05:06:19.944003</span><br><span class="line">         status: COMPLETED</span><br><span class="line">FINISH_LS_COUNT: 4</span><br><span class="line">         RESULT: 0</span><br><span class="line">           PATH: file:///nfs-server/ob***/obbackup01/***ob/1767617455/tenant_incarnation_1/1002/clog</span><br><span class="line">*************************** 9. row ***************************</span><br><span class="line">        task_id: 455</span><br><span class="line">         job_id: 3795</span><br><span class="line">      TASK_TYPE: BACKUP SET</span><br><span class="line">       ROUND_ID: 0</span><br><span class="line">        DEST_ID: 1002</span><br><span class="line">START_TIMESTAMP: 2026-06-08 04:54:27.766664</span><br><span class="line">  END_TIMESTAMP: 2026-06-08 04:55:04.158958</span><br><span class="line">         status: COMPLETED</span><br><span class="line">FINISH_LS_COUNT: 4</span><br><span class="line">         RESULT: 0</span><br><span class="line">           PATH: file:///nfs-server/ob***/obbackup01/***ob/1767617455/tenant_incarnation_1/1002/data</span><br><span class="line">*************************** 10. row ***************************</span><br><span class="line">        task_id: 453</span><br><span class="line">         job_id: 3770</span><br><span class="line">      TASK_TYPE: BACKUP PIECE</span><br><span class="line">       ROUND_ID: 1</span><br><span class="line">        DEST_ID: 1001</span><br><span class="line">START_TIMESTAMP: 2026-06-07 04:54:10.030664</span><br><span class="line">  END_TIMESTAMP: 2026-06-07 05:01:53.615006</span><br><span class="line">         status: COMPLETED</span><br><span class="line">FINISH_LS_COUNT: 4</span><br><span class="line">         RESULT: 0</span><br><span class="line">           PATH: file:///nfs-server/ob***/obbackup01/***ob/1767617455/tenant_incarnation_1/1002/clog</span><br></pre></td></tr></table></figure><p>从这段记录看，每天也就清理一次数据备份和日志备份。</p><p>再看看数据备份文件的状态。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line">select BACKUP_SET_ID , BACKUP_TYPE ,START_TIMESTAMP ,END_TIMESTAMP ,START_REPLAY_SCN_DISPLAY , STATUS ,FILE_STATUS ,FILE_COUNT ,ELAPSED_SECONDES from oceanbase.DBA_OB_BACKUP_SET_FILES order by BACKUP_SET_ID desc limit 5 \G</span><br><span class="line">*************************** 1. row ***************************</span><br><span class="line">           BACKUP_SET_ID: 158</span><br><span class="line">             BACKUP_TYPE: FULL</span><br><span class="line">         START_TIMESTAMP: 2026-06-10 04:00:05.622073</span><br><span class="line">           END_TIMESTAMP: 2026-06-10 04:26:03.158353</span><br><span class="line">START_REPLAY_SCN_DISPLAY: 2026-06-10 02:17:38.960160</span><br><span class="line">                  STATUS: SUCCESS</span><br><span class="line">             FILE_STATUS: AVAILABLE</span><br><span class="line">              FILE_COUNT: 0</span><br><span class="line">        ELAPSED_SECONDES: 1558</span><br><span class="line">*************************** 2. row ***************************</span><br><span class="line">           BACKUP_SET_ID: 157</span><br><span class="line">             BACKUP_TYPE: FULL</span><br><span class="line">         START_TIMESTAMP: 2026-06-09 04:00:04.345129</span><br><span class="line">           END_TIMESTAMP: 2026-06-09 04:30:35.335842</span><br><span class="line">START_REPLAY_SCN_DISPLAY: 2026-06-09 01:49:54.467299</span><br><span class="line">                  STATUS: SUCCESS</span><br><span class="line">             FILE_STATUS: AVAILABLE</span><br><span class="line">              FILE_COUNT: 0</span><br><span class="line">        ELAPSED_SECONDES: 1831</span><br><span class="line">*************************** 3. row ***************************</span><br><span class="line">           BACKUP_SET_ID: 156</span><br><span class="line">             BACKUP_TYPE: FULL</span><br><span class="line">         START_TIMESTAMP: 2026-06-08 18:36:23.016296</span><br><span class="line">           END_TIMESTAMP: 2026-06-08 19:06:47.962207</span><br><span class="line">START_REPLAY_SCN_DISPLAY: 2026-06-08 18:15:20.863016</span><br><span class="line">                  STATUS: SUCCESS</span><br><span class="line">             FILE_STATUS: DELETED</span><br><span class="line">              FILE_COUNT: 0</span><br><span class="line">        ELAPSED_SECONDES: 1825</span><br><span class="line">*************************** 4. row ***************************</span><br><span class="line">           BACKUP_SET_ID: 155</span><br><span class="line">             BACKUP_TYPE: FULL</span><br><span class="line">         START_TIMESTAMP: 2026-06-08 04:00:05.374333</span><br><span class="line">           END_TIMESTAMP: 2026-06-08 04:25:44.933878</span><br><span class="line">START_REPLAY_SCN_DISPLAY: 2026-06-08 02:37:20.290484</span><br><span class="line">                  STATUS: SUCCESS</span><br><span class="line">             FILE_STATUS: DELETED</span><br><span class="line">              FILE_COUNT: 0</span><br><span class="line">        ELAPSED_SECONDES: 1540</span><br><span class="line">*************************** 5. row ***************************</span><br><span class="line">           BACKUP_SET_ID: 154</span><br><span class="line">             BACKUP_TYPE: FULL</span><br><span class="line">         START_TIMESTAMP: 2026-06-07 04:00:04.985212</span><br><span class="line">           END_TIMESTAMP: 2026-06-07 04:30:41.643439</span><br><span class="line">START_REPLAY_SCN_DISPLAY: 2026-06-07 02:14:55.974754</span><br><span class="line">                  STATUS: SUCCESS</span><br><span class="line">             FILE_STATUS: DELETED</span><br><span class="line">              FILE_COUNT: 0</span><br><span class="line">        ELAPSED_SECONDES: 1837</span><br></pre></td></tr></table></figure><p>从这里看，9 号以前的数据备份都被清理了，9 号和 10 号的数据备份都在。所以简单说保留了 2 天的备份。</p><p>看看日志备份文件状态。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line">select DEST_ID ,PIECE_ID  , status, START_SCN_DISPLAY , END_SCN_DISPLAY  , OUTPUT_BYTES_DISPLAY ,FILE_STATUS from oceanbase.DBA_OB_ARCHIVELOG_PIECE_FILES order by DEST_ID ,ROUND_ID ,PIECE_ID desc limit 5 \G</span><br><span class="line">*************************** 1. row ***************************</span><br><span class="line">             DEST_ID: 1001</span><br><span class="line">            PIECE_ID: 155</span><br><span class="line">              status: ACTIVE</span><br><span class="line">   START_SCN_DISPLAY: 2026-06-10 11:23:16.490548</span><br><span class="line">     END_SCN_DISPLAY: 2026-06-11 11:23:16.490548</span><br><span class="line">OUTPUT_BYTES_DISPLAY: 653.36GB</span><br><span class="line">         FILE_STATUS: AVAILABLE</span><br><span class="line">*************************** 2. row ***************************</span><br><span class="line">             DEST_ID: 1001</span><br><span class="line">            PIECE_ID: 154</span><br><span class="line">              status: FROZEN</span><br><span class="line">   START_SCN_DISPLAY: 2026-06-09 11:23:16.490548</span><br><span class="line">     END_SCN_DISPLAY: 2026-06-10 11:23:16.490548</span><br><span class="line">OUTPUT_BYTES_DISPLAY: 2.79TB</span><br><span class="line">         FILE_STATUS: AVAILABLE</span><br><span class="line">*************************** 3. row ***************************</span><br><span class="line">             DEST_ID: 1001</span><br><span class="line">            PIECE_ID: 153</span><br><span class="line">              status: FROZEN</span><br><span class="line">   START_SCN_DISPLAY: 2026-06-08 11:23:16.490548</span><br><span class="line">     END_SCN_DISPLAY: 2026-06-09 11:23:16.490548</span><br><span class="line">OUTPUT_BYTES_DISPLAY: 3.09TB</span><br><span class="line">         FILE_STATUS: AVAILABLE</span><br><span class="line">*************************** 4. row ***************************</span><br><span class="line">             DEST_ID: 1001</span><br><span class="line">            PIECE_ID: 152</span><br><span class="line">              status: FROZEN</span><br><span class="line">   START_SCN_DISPLAY: 2026-06-07 11:23:16.490548</span><br><span class="line">     END_SCN_DISPLAY: 2026-06-08 11:23:16.490548</span><br><span class="line">OUTPUT_BYTES_DISPLAY: 5.70TB</span><br><span class="line">         FILE_STATUS: DELETED</span><br><span class="line">*************************** 5. row ***************************</span><br><span class="line">             DEST_ID: 1001</span><br><span class="line">            PIECE_ID: 151</span><br><span class="line">              status: FROZEN</span><br><span class="line">   START_SCN_DISPLAY: 2026-06-06 11:23:16.490548</span><br><span class="line">     END_SCN_DISPLAY: 2026-06-07 11:23:16.490548</span><br><span class="line">OUTPUT_BYTES_DISPLAY: 3.01TB</span><br><span class="line">         FILE_STATUS: DELETED</span><br></pre></td></tr></table></figure><p>从这段记录看，日志备份分片保留了 8 号、9 号、10 号的日志备份（分片切换时间点不是整点，而是 11 点 23 分）。8 号之前的日志备份被删除了。所以可以简单的说，保留了 3 天的日志备份。这里疑点最大的就是最早的日志备份分片 8 号为什么还在。这是因为 8 号 4 点以后的日志备份还是被需要的，这导致整个日志备份分片都是需要的。也就是 OceanBase 清理日志备份分片的里粒度是分片（piece），而不是单个的日志备份文件。单个日志备份文件长下面这样：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">--- /nfs-server/ob***/obbackup01/***ob/1767617455/tenant_incarnation_1/1002/clog/piece_d1001r1p153/logstream_1001/log ----------------------------------------------------</span><br><span class="line">                                               2026-06-09 11:24:05 +0800 /..</span><br><span class="line"> 32.2 MiB [############            ]         2026-06-08 11:23:20 +0800  779627.obarc</span><br><span class="line"> 64.0 MiB [########################]         2026-06-08 11:23:21 +0800  779628.obarc</span><br><span class="line"> 64.0 MiB [########################]         2026-06-08 11:23:21 +0800  779629.obarc</span><br><span class="line"> 64.0 MiB [########################]         2026-06-08 11:23:21 +0800  779630.obarc</span><br><span class="line"> 64.0 MiB [########################]         2026-06-08 11:23:21 +0800  779631.obarc</span><br><span class="line"> 64.0 MiB [########################]         2026-06-08 11:23:22 +0800  779632.obarc</span><br><span class="line"> 64.0 MiB [########################]         2026-06-08 11:23:23 +0800  779633.obarc</span><br><span class="line"> 64.0 MiB [########################]         2026-06-08 11:23:23 +0800  779634.obarc</span><br><span class="line"> 64.0 MiB [########################]         2026-06-08 11:23:25 +0800  779635.obarc</span><br></pre></td></tr></table></figure><p>总结起来就是这个业务 OceanBase 租户，为了实现备份还原 RPO 为 1 天的目标，保留了 2 天的数据备份和 3 天的日志备份。</p><h2 id="日志备份空间大的原因"><a href="#日志备份空间大的原因" class="headerlink" title="日志备份空间大的原因"></a>日志备份空间大的原因</h2><p>大部分客户不会关注到这个备份空间清理的问题，除非这个空间成为“成本”。仔细分析上面数据会发现数据备份每天大小大概 240G 左右，但是日志备份每天大小变化范围在 2.8T ~ 5.7T 。</p><p>其原因是这个 OceanBase 集群场景是数据仓库场景，有大量的 ETL ，其中大量用到临时表。 OceanBase 终于在 4.2.5 （也可能是其他版本）实现跟 ORACLE 特性一样的临时表，支持 <code>on commit delete rows</code> 和 <code>on commit preserve rows</code> 。但是这些临时表还是跟 ORACLE 的临时表有个显著的差异就是 OceanBase 的临时表会写 WAL 日志。目前咨询了 4.4.2 版本，还是这样。</p><p><img src="/img/2026-06-15-oceanbase-backup-cleanup/06.png" alt="日志备份占用空间偏大的常见原因" loading="lazy" decoding="async"></p><p><em>图：ETL 临时表 → WAL 日志 → 备份空间膨胀 &amp; 实际保留对比</em></p><h2 id="结论"><a href="#结论" class="headerlink" title="结论"></a>结论</h2><p>OCP 里的备份“保留天数”设置功能对应的是设置租户备份的 <code>recovery_window</code> 参数，这个是跟还原的能力（RPO）有关的描述，间接影响备份的保留天数。从实际效果看，如果 OCP 里设置“保留天数”是 1 天，实际上会保留 2 天的数据备份，以及 3 天的日志备份。其实运维承诺的就应该是备份的还原的能力而不是保留天数。这个也适合传统数据库。</p><p>如果还想进一步缩小这个备份空间的大小，那就要精细化控制合并和备份的调度时间，以及在备份被调度之前，提前 10 分钟去启动日志备份（可能要晚上加个班）。不过看到 OCP 的备份里有个选项说是可以在数据备份的时候才启动日志备份，数据备份结束再关闭日志备份。这个功能没有在客户环境测试过。如果有人用过，欢迎留言分享。</p><p><img src="/img/2026-06-15-oceanbase-backup-cleanup/07.png" alt="OceanBase 备份清理机制结论总结" loading="lazy" decoding="async"></p><h2 id="更多阅读"><a href="#更多阅读" class="headerlink" title="更多阅读"></a>更多阅读</h2><ul><li><a href="https://mp.weixin.qq.com/s?__biz=MzU3OTc2MDQxNg==&mid=2247487142&idx=1&sn=9cad48330b897400c9902053dd508bd1&scene=21#wechat_redirect">OceanBase V4 日志流设计分析</a></li><li><a href="https://mp.weixin.qq.com/s?__biz=MzU3OTc2MDQxNg==&mid=2247485683&idx=1&sn=63b3e309b8f31c55f662c04667d13ca3&scene=21#wechat_redirect">OceanBase 社区版 4.1 备份恢复实践</a></li><li><a href="https://mp.weixin.qq.com/s?__biz=MzU3OTc2MDQxNg==&mid=2247485674&idx=1&sn=42f4e266483acd63b4daf495f0391dd8&scene=21#wechat_redirect">OceanBase 企业版 3.2 备份恢复实践</a></li><li><a href="https://mp.weixin.qq.com/s?__biz=MzU3OTc2MDQxNg==&mid=2247488089&idx=1&sn=22a480ae6e1bc57727542a1c45c77076&scene=21#wechat_redirect">OceanBase 奇案分享：是谁拉起了 OceanBase 进程？</a></li></ul>]]>
    </content>
    <id>https://ilongda.com/2026/2026-06-15-oceanbase-backup-cleanup/</id>
    <link href="https://ilongda.com/2026/2026-06-15-oceanbase-backup-cleanup/"/>
    <published>2026-06-14T23:52:11.000Z</published>
    <summary>详解 OceanBase 物理备份保留策略、备份集依赖与自动清理：为何空间未按直觉释放，以及如何排查日志归档与可还原点问题。</summary>
    <title>OceanBase 备份空间清不掉？物理备份自动清理原理详解</title>
    <updated>2026-06-14T23:52:11.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="技术详解" scheme="https://ilongda.com/categories/%E6%8A%80%E6%9C%AF%E8%AF%A6%E8%A7%A3/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="AI Agent" scheme="https://ilongda.com/tags/AI-Agent/"/>
    <category term="向量检索" scheme="https://ilongda.com/tags/%E5%90%91%E9%87%8F%E6%A3%80%E7%B4%A2/"/>
    <category term="PowerMem" scheme="https://ilongda.com/tags/PowerMem/"/>
    <category term="遗忘机制" scheme="https://ilongda.com/tags/%E9%81%97%E5%BF%98%E6%9C%BA%E5%88%B6/"/>
    <category term="智能记忆" scheme="https://ilongda.com/tags/%E6%99%BA%E8%83%BD%E8%AE%B0%E5%BF%86/"/>
    <category term="工程实践" scheme="https://ilongda.com/tags/%E5%B7%A5%E7%A8%8B%E5%AE%9E%E8%B7%B5/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"PowerMem 记忆生命周期：一条信息从写入到淘汰怎么走完","description":"用一条消息跟踪 PowerMem：重要性评估、分层存储、衰减复习到淘汰，看清 AI Agent 长期记忆工程如何实现智能遗忘。","image":"https://ilongda.com/img/2026-06-12-powermem-memory-lifecycle/01.png","wordCount":7357,"datePublished":"2026-06-11T23:44:48.000Z","dateModified":"2026-06-11T23:44:48.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-06-12-powermem-memory-lifecycle/"},"url":"https://ilongda.com/2026/2026-06-12-powermem-memory-lifecycle/","inLanguage":"zh-CN","keywords":["OceanBase","AI Agent","向量检索","PowerMem","遗忘机制","智能记忆","工程实践"],"articleSection":["技术详解"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"技术详解","item":"https://ilongda.com/categories/技术详解/"},{"@type":"ListItem","position":3,"name":"PowerMem 记忆生命周期：一条信息从写入到淘汰怎么走完","item":"https://ilongda.com/2026/2026-06-12-powermem-memory-lifecycle/"}]}</script><blockquote><p>时间让记忆蒙尘，访问是唯一的擦拭。尘太厚、无人问，便是遗忘。</p></blockquote><blockquote><p>💡 想亲手试试 Agent 记忆层？欢迎到 <a href="https://github.com/oceanbase/powermem">PowerMem</a> 逛逛——开箱就能给 Agent 加上会整理、会遗忘的长期记忆。</p></blockquote><p>前一篇 <a href="https://www.cnblogs.com/knqiufan/p/20130795">记忆系统的遗忘设计，从神经元到代码工程</a> 从认知科学讲了遗忘：突触可塑性、艾宾浩斯曲线、间隔重复。那是“为什么要忘”。</p><p>这篇换视角：以一条消息为线索，跟着它在 PowerMem（OceanBase 开源的 AI 记忆引擎）里走完从写入到淘汰的全程，看遗忘机制在工程里怎么落地。</p><p>一句话概括：消息一旦写入就开始衰减；真正决定它去留的，是之后有没有被再次访问。</p><span id="more"></span><h2 id="一、重要性评估：这条信息值得记住吗？"><a href="#一、重要性评估：这条信息值得记住吗？" class="headerlink" title="一、重要性评估：这条信息值得记住吗？"></a>一、重要性评估：这条信息值得记住吗？</h2><p>先说一个场景。假设发了这么一条消息：</p><blockquote><p>下周五下午三点和产品团队在 3 号会议室评审 Q2 需求文档。</p></blockquote><p>当这条消息进入记忆系统后，第一个问题不是问「怎么记住」，而是要先判断「值不值得记住」。如果所有信息都以相同的权重被存储和检索，随着数据量增长，系统会面临两个问题：检索信噪比持续下降，存储成本不可控。</p><p>香农信息论也解释了这件事：高概率事件的信息量趋近于零，不值得长期存储；低概率但关键事件的信息量极大，必须持久化保留。</p><p><strong>重要性评估就是干这件事的，它是信息过滤器。</strong> 它会为每条信息打一个分数，这个分数决定后续的衰减速度、复习频率和淘汰优先级。</p><p>那么重要性如何评估？</p><h3 id="1-1-六维度评估模型"><a href="#1-1-六维度评估模型" class="headerlink" title="1.1 六维度评估模型"></a>1.1 六维度评估模型</h3><p>在 PowerMem 中评估一条信息的重要性比想象中复杂。它使用了一个<strong>六维评估模型</strong>，即从六个维度进行综合评估、加权汇总：</p><p>| 维度                         | 权重 | 评估什么                       |</p><p>| —————————- | —- | —————————— |</p><p>| relevance（关联度）          | 0.30 | 信息与用户当前上下文的关联程度 |</p><p>| novelty（新颖度）            | 0.20 | 信息的新鲜程度，是否为首次出现 |</p><p>| emotional_impact（情感强度） | 0.15 | 信息是否包含强烈的情感色彩     |</p><p>| actionable（可操作性）       | 0.15 | 信息是否需要用户采取行动       |</p><p>| factual（事实性）            | 0.10 | 信息的客观事实程度             |</p><p>| personal（个人相关性）       | 0.10 | 信息与用户个人的关联程度       |</p><p>拿前面举例的会议消息来说。它与「Q2 的工作」高度相关（relevance ≈ 0.8），包含明确的时间地点（factual ≈ 0.8），用户必须参加不能错过（actionable ≈ 0.9），但情感上中性（emotional_impact ≈ 0.2），那么从使用六维评估模型加权计算出的<strong>重要性分数</strong>大致如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">0.3×0.8 + 0.2×0.5 + 0.15×0.2 + 0.15×0.9 + 0.1×0.8 + 0.1×0.6 ≈ 0.72</span><br></pre></td></tr></table></figure><p>即最终得出的重要性评估分数为 0.72。</p><p>六维评估模型是重要性评估的重要理论基础。</p><h3 id="1-2-双路径评估：LLM-与规则引擎"><a href="#1-2-双路径评估：LLM-与规则引擎" class="headerlink" title="1.2 双路径评估：LLM 与规则引擎"></a>1.2 双路径评估：LLM 与规则引擎</h3><p>PowerMem 设计了两条重要性评估执行路径，确保系统在任何情况下都能给出评分。第一条路径就是基于六维评估模型得出的评分，第二路径则是在第一条路径不可用时进行优雅降级的规则引擎计算方案。</p><p><strong>路径一：LLM 深度评估（优先）</strong></p><p>当 LLM 可用时会直接走这一条评估路径。系统要求 LLM 根据六维度评估模型从六个维度分别分析，返回结构化 JSON。得到的结果示例如下：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">&quot;importance_score&quot;</span><span class="punctuation">:</span> <span class="number">0.72</span><span class="punctuation">,</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">&quot;reasoning&quot;</span><span class="punctuation">:</span> <span class="string">&quot;会议安排对用户具有明确的时间约束和行动要求&quot;</span><span class="punctuation">,</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">&quot;criteria_scores&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line"></span><br><span class="line">        <span class="attr">&quot;relevance&quot;</span><span class="punctuation">:</span> <span class="number">0.8</span><span class="punctuation">,</span></span><br><span class="line"></span><br><span class="line">        <span class="attr">&quot;novelty&quot;</span><span class="punctuation">:</span> <span class="number">0.5</span><span class="punctuation">,</span></span><br><span class="line"></span><br><span class="line">        <span class="attr">&quot;emotional_impact&quot;</span><span class="punctuation">:</span> <span class="number">0.2</span><span class="punctuation">,</span></span><br><span class="line"></span><br><span class="line">        <span class="attr">&quot;actionable&quot;</span><span class="punctuation">:</span> <span class="number">0.9</span><span class="punctuation">,</span></span><br><span class="line"></span><br><span class="line">        <span class="attr">&quot;factual&quot;</span><span class="punctuation">:</span> <span class="number">0.8</span><span class="punctuation">,</span></span><br><span class="line"></span><br><span class="line">        <span class="attr">&quot;personal&quot;</span><span class="punctuation">:</span> <span class="number">0.6</span></span><br><span class="line"></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line"></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>PowerMem 从这个 LLM 回复的结构化 JSON 中提取 <code>importance_score</code> 字段作为重要性评分。</p><p>但实际上因为 LLM 的回答会有一定的不可预知性，所以为了确保即使 LLM 返回格式不规范系统也不会崩溃，可以拿到对应的评分数据，PowerMem 使用了一种<strong>三级回退</strong>的方式来进行解析：首先尝试解析 JSON 拿到最准确的数据，若解析失败则用正则表达式匹配评分数字，若再失败，即返回保底的默认值 0.5。</p><blockquote><p>值得注意的是，LLM 返回的结构化 JSON 中的六维数据实际上并未直接参与最后的权重的计算，在这里让 LLM 返回六维数据只是为了通过 Chain-of-Thought 的结构化分解来辅助 LLM 推理，让最终答案更可靠稳定。</p></blockquote><p><strong>路径二：规则引擎（兜底）</strong></p><p>当 LLM 不可用时，路径一则失效，规则引擎会接管重要性分数的计算。虽然精度会有所下降，但能保证系统能正常运行。</p><p>规则引擎基于一组可量化的信号来累加分数的：</p><ul><li>内容长度 &gt; 100 字符：+0.1；&gt; 50 字符：+0.05</li><li>命中关键词：每个 +0.1</li><li>包含 <code>?</code> 或 <code>!</code>：各 +0.05</li><li>元数据标记了优先级（high&#x2F;medium）：+0.2&#x2F;+0.1</li><li>最终分数上限为 1.0</li></ul><p>规则引擎评分精度不如 LLM 评分，但确保了系统在 LLM 不可用时仍能正常运行，这种**优雅降级（graceful degradation）**设计是生产级系统的重要特征。即不会因为一个外部服务的故障，就导致整个记忆系统停摆。</p><p><img src="/img/2026-06-12-powermem-memory-lifecycle/01.png" alt="PowerMem 双路径重要性评估流程" decoding="async"></p><hr><h2 id="二、分类与参数初始化"><a href="#二、分类与参数初始化" class="headerlink" title="二、分类与参数初始化"></a>二、分类与参数初始化</h2><h3 id="2-1-三层记忆模型"><a href="#2-1-三层记忆模型" class="headerlink" title="2.1 三层记忆模型"></a>2.1 三层记忆模型</h3><p>重要性分数确定了之后，下一步就要给信息分类，来决定这条信息属于哪一层的记忆。</p><p>不知道大家还是否记得前一篇聊过的大脑的记忆分层机制。即信息先进入容量有限的海马体（短期存储），经过记忆巩固后转移至新皮层（长期存储），只有那些被反复激活的、与已有知识建立了丰富关联的、或伴随强烈情绪体验的信息，才能获得优先转移权。</p><p>PowerMem 把这个过程翻译为三层模型：</p><p>| 层级                       | 生物学类比 | 倍率 | 典型存活时间 |</p><p>| ————————– | ———- | —- | ———— |</p><p>| <strong>working</strong>（工作记忆）    | 前额叶皮层 | ×0.5 | 数小时~1 天  |</p><p>| <strong>short_term</strong>（短期记忆） | 海马体     | ×1.5 | 数天~数周    |</p><p>| <strong>long_term</strong>（长期记忆）  | 新皮层     | ×2.0 | 数周~数月    |</p><p>而分类的逻辑又以重要性分数为依据：<code>≥ 0.8</code> 进入 long_term，<code>≥ 0.6</code> 进入 short_term，其余归入 working。<strong>不同层级的衰减速率不同，层级越高衰减越慢，信息活得越久：</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">if</span> score &gt;= self._algo.long_term_threshold:   <span class="comment"># 0.8</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;long_term&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> score &gt;= self._algo.short_term_threshold:  <span class="comment"># 0.6</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;short_term&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="string">&quot;working&quot;</span></span><br></pre></td></tr></table></figure><p>前面算出来的会议信息重要性评分为 importance &#x3D; 0.72，命中了 <code>≥ 0.6</code> 但不到 <code>0.8</code>。所以落入 <strong>short_term（短期记忆）</strong>。</p><p><img src="/img/2026-06-12-powermem-memory-lifecycle/02.png" alt="PowerMem 工作记忆与长期记忆分层模型" loading="lazy" decoding="async"></p><h3 id="2-2-遗忘参数初始化"><a href="#2-2-遗忘参数初始化" class="headerlink" title="2.2 遗忘参数初始化"></a>2.2 遗忘参数初始化</h3><p>分类分完了，但是分类只回答了「这条信息该待在哪一层」，更具体的问题是：<strong>应该忘多快？为了巩固记忆什么时候要再复习一遍？</strong></p><p>PowerMem 在分类完成后会为每条记忆生成一整套<strong>可随生命周期演进的数值档案</strong>。即系统会为这条记忆建立一份元数据卡片用来记录这条信息记忆的强度、衰减参数、复习计划和管理状态等。</p><p>元数据卡片在结构上分成两块：</p><p>| 字段                         | 职责                                                         |</p><p>| —————————- | ———————————————————— |</p><p>| <code>metadata.intelligence</code>      | <strong>一些数值指标</strong>：重要性、层级、保留率、衰减率、复习时刻表、访问&#x2F;复习计数等 |</p><p>| <code>metadata.memory_management</code> | <strong>记忆生命周期开关</strong>：是否待晋升、待遗忘、待归档、是否仍活跃 |</p><p>依旧以会议信息为例（importance &#x3D; 0.72，short_term），逐一说明核心参数的设计意图和计算方式。</p><h4 id="2-2-1-初始保留率"><a href="#2-2-1-初始保留率" class="headerlink" title="2.2.1 初始保留率"></a>2.2.1 初始保留率</h4><p>初始保留率决定了一条信息在形成瞬间的牢固程度，越重要的信息在写入时就应该被赋予越高的初始保留率，低重要性内容在认知层面本就应更脆弱，更容易在竞争中让出存储与检索带宽。</p><p>在 PowerMem 中的初始保留率就是重要性分数乘以一个默认为 1.0 的全局配置参数：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">initial_retention = self.initial_retention * importance_score</span><br><span class="line"></span><br><span class="line"><span class="comment"># 会议示例：1.0 × 0.72 = 0.72</span></span><br></pre></td></tr></table></figure><p>得到的初始保留率实际上会写入两个字段：</p><ul><li><code>initial_retention</code> 字段，用于记录创建时的快照（当初记得有多牢）</li><li><code>current_retention</code> 字段，用于跟踪当前的有效保留水平</li></ul><p>创建时两者数值相同，之后 <code>current_retention</code> 会随衰减和复习而变化。</p><h4 id="2-2-2-关于遗忘速度"><a href="#2-2-2-关于遗忘速度" class="headerlink" title="2.2.2 关于遗忘速度"></a>2.2.2 关于遗忘速度</h4><p>working &#x2F; short_term &#x2F; long_term 对应到认知学科中的工作记忆、海马体、新皮层，即越接近长期存储层，单位时间内的遗忘应该越慢。所以不同的记忆层级需要有各自不同的衰减系数。</p><p>在 PowerMem 中不同记忆层级的衰减系数为：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">&#123;</span><br><span class="line"></span><br><span class="line">    <span class="string">&quot;working&quot;</span>:    <span class="number">0.5</span>,  <span class="comment"># 强度参数 S 最小，忘得最快</span></span><br><span class="line"></span><br><span class="line">    <span class="string">&quot;short_term&quot;</span>: <span class="number">1.5</span>,</span><br><span class="line"></span><br><span class="line">    <span class="string">&quot;long_term&quot;</span>:  <span class="number">2.0</span>,  <span class="comment"># 强度参数 S 最大，忘得最慢</span></span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>那么针对开头的会议信息，这条信息落在了 short_term，故系数为 1.5，当前这条消息的衰减率为：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">0.1（全局基础衰减率） × 1.5（short_term 衰减系数） = 0.15</span><br></pre></td></tr></table></figure><p>若记忆分类在 working，那么衰减率为：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">0.1（全局基础衰减率） × 0.5（working 衰减系数） = 0.05</span><br></pre></td></tr></table></figure><p>若记忆分类在 long_term，那么衰减率为：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">0.1（全局基础衰减率） × 2（long_term 衰减系数） = 0.2</span><br></pre></td></tr></table></figure><p>可以看到 <strong>不同的记忆分类衰减率不同，参数越大遗忘越慢</strong>。</p><h4 id="2-2-3-如何做复习调度"><a href="#2-2-3-如何做复习调度" class="headerlink" title="2.2.3 如何做复习调度"></a>2.2.3 如何做复习调度</h4><p>在认知学原理中有提到，间隔重复的核心原则是复习先密后疏，要在快要忘记但还能拯救的时间窗内进行复习，不能太早（等于白看一遍），也不能太晚（已经彻底忘了）。</p><p>所以 PowerMem <strong>在记忆创建时就排好复习时间点，而不是等到需要时才临时决定。</strong></p><p>PowerMem 通过两步生成这张复习时刻表：</p><p><strong>第一步：给定基准间隔。</strong></p><p>系统预设五个基准间隔（小时）：<code>[1, 6, 24, 72, 168]</code>，分别对应约 1 小时、6 小时、1 天、3 天、7 天。五个间隔是全局配置，所有记忆共享同一组基准值。</p><p><strong>第二步：按重要性压缩间隔。</strong></p><p>基准间隔对所有记忆一视同仁，但不同重要性不同分类的记忆不该用同一个节奏复习，一条密码信息应该比一句闲聊被更频繁地唤醒。所以 PowerMem 用了一个公式，根据重要性分数对<strong>每个基准间隔</strong>做压缩：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">adjusted_interval = interval * (<span class="number">1</span> - importance_score * adjustment_factor)</span><br></pre></td></tr></table></figure><ul><li><code>interval</code> 是基准间隔的数据（如 1h、6h、24h）</li><li><code>importance_score</code> 是前面算出来的会议信息的重要性参数 0.72</li><li><code>adjustment_factor</code> 是压缩系数（默认 0.3），控制压缩的力度</li><li>乘积 <code>importance_score × adjustment_factor</code> 决定了最多能压缩多少</li><li>最终结果 <code>adjusted_interval</code> 是压缩后的实际间隔，下限 0.5 小时</li></ul><p>这么解释公式还是太抽象，还是用会议信息（importance &#x3D; 0.72）来拆一遍。</p><p>这时压缩乘子（即对应公式中的 <code>(1 - importance_score * adjustment_factor)</code> 部分）是：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">1 - 0.72 × 0.3 = 0.784</span><br></pre></td></tr></table></figure><p>也就是说，每个基准间隔都会变成原来的 78.4%。通过计算得出的五个时间点如下：</p><p>| 次序    | 基准间隔 | 调整后间隔            | 建议复习时刻（示意） |</p><p>| ——- | ——– | ——————— | ——————– |</p><p>| 第 1 次 | 1h       | ≈ 0.78h（约 47 分钟） | T₀ + 47min           |</p><p>| 第 2 次 | 6h       | ≈ 4.7h                | T₀ + 4.7h            |</p><p>| 第 3 次 | 24h      | ≈ 18.8h               | T₀ + 18.8h           |</p><p>| 第 4 次 | 72h      | ≈ 56.4h（约 2.4 天）  | T₀ + 2.4d            |</p><p>| 第 5 次 | 168h     | ≈ 131.7h（约 5.5 天） | T₀ + 5.5d            |</p><p>换个角度再看，如果一条信息没有那么重要，假设 importance &#x3D; 0.3，压缩乘子则变成：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">1 - 0.3 × 0.3 = 0.91</span><br></pre></td></tr></table></figure><p>即每个基准间隔都会变成原来的 91%，这条信息的五个复习时间点会更靠后：</p><p>| 次序    | 基准间隔 | 调整后间隔             | 建议复习时刻（示意） |</p><p>| ——- | ——– | ———————- | ——————– |</p><p>| 第 1 次 | 1h       | ≈ 0.91h（约 55 分钟）  | T₀ + 55min           |</p><p>| 第 2 次 | 6h       | ≈ 5.46h                | T₀ + 5.46h           |</p><p>| 第 3 次 | 24h      | ≈ 21.84h               | T₀ + 21.84h          |</p><p>| 第 4 次 | 72h      | ≈ 65.52h（约 2.7 天）  | T₀ + 2.7d            |</p><p>| 第 5 次 | 168h     | ≈ 152.88h（约 6.4 天） | T₀ + 6.4d            |</p><p>效果很明显。importance &#x3D; 0.72 的会议信息，五轮复习的间隔时间点都被明显提前；importance &#x3D; 0.3 的不那么重要的信息，复习间隔只被轻微压缩。复习次数越往后，复习时间的差距越大。</p><p><strong>重要性越高，系统越早把它拉回复习窗口，记忆被重新巩固的机会也就越多。</strong></p><p>当算完五个时间点后 PowerMem 会把它们存入完整的复习时刻表，同时会初始化几个字段，配合复习时刻表工作：</p><p>| 字段                   | 含义                                                         |</p><p>| ———————- | ———————————————————— |</p><p>| <code>next_review</code>          | 时刻表中的第一个时间点，即<strong>下一次建议复习</strong>的时间。系统通过这个字段知道最近一次复习该在什么时候 |</p><p>| <code>last_reviewed</code>        | 最近一次复习的时间戳。刚创建时等于创建时刻，之后每完成一次复习就更新 |</p><p>| <code>review_count</code>         | 已经完成了几轮复习。创建时为 0，每完成一轮加 1               |</p><p>| <code>reinforcement_factor</code> | 复习成功后保留率的提升幅度（默认 0.3）。决定每次温故能补回多少遗忘 |</p><p>这几个字段和时刻表一起，构成了一套完整的复习追踪机制：</p><ul><li><code>next_review</code> 告诉系统什么时候该复习</li><li><code>review_count</code> 和 <code>last_reviewed</code> 记录已经复习了多少次</li><li><code>reinforcement_factor</code> 决定复习一次能恢复多少</li></ul><p>当到达 <code>next_review</code> 并完成一次复习时，<code>review_count</code> 递增、<code>last_reviewed</code> 更新、<code>current_retention</code> 按 <code>reinforcement_factor</code> 提升，<code>next_review</code> 推进到下一个时间点。</p><p>至此形成<strong>提取再巩固</strong>的工程闭环。</p><h4 id="2-2-4-生命周期状态机"><a href="#2-2-4-生命周期状态机" class="headerlink" title="2.2.4 生命周期状态机"></a>2.2.4 生命周期状态机</h4><p>除了保留率、衰减率、复习时刻这些连续的数值，记忆在系统中还有一些生命周期状态需要管理：</p><ul><li>这条记忆是否该晋升到更高的层级？</li><li>是否该被淘汰？</li><li>是否该从活跃检索池中移除？</li></ul><p>在 PowerMem 中也都有对应的标志位，创建时初始化为全新、活跃、尚未触发任何处置：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">&quot;should_promote&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span>  <span class="comment">// 是否应该晋升到更高的层级</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">&quot;should_forget&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span>   <span class="comment">// 是否应该被淘汰</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">&quot;should_archive&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span>  <span class="comment">// 是否应该从活跃检索池转入归档</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">&quot;is_active&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span>         <span class="comment">// 是否仍处于活跃状态</span></span><br><span class="line"></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li><code>should_promote</code>：这条记忆是否应该晋升到更高的层级（如 working → short_term）。如果一条 working 记忆被反复访问，说明它对用户很有价值，应该晋升到 short_term 甚至 long_term，获得更慢的衰减速度。</li><li><code>should_forget</code>：这条记忆是否应该被淘汰。当衰减因子跌破阈值（0.3）或者一条记忆在 7 天内从未被任何人访问过，系统就会标记它为待遗忘。</li><li><code>should_archive</code>：这条记忆是否应该从活跃检索池转入归档。<strong>归档不同于遗忘，归档的记忆不会被物理删除，只是不再参与日常检索。</strong></li><li><code>is_active</code>：这条记忆是否仍处于活跃状态，参与正常的检索和服务。</li></ul><p>除此之外，PowerMem 还会初始化一个 <code>access_count</code> 计数器，记录这条记忆被访问了多少次，这个计数器和标志位们配合工作（比如 <code>should_promote</code> 的判断条件之一就是被访问超过 3 次）。</p><h4 id="2-2-5-落库：完整的元数据档案"><a href="#2-2-5-落库：完整的元数据档案" class="headerlink" title="2.2.5 落库：完整的元数据档案"></a>2.2.5 落库：完整的元数据档案</h4><p>所有参数都计算完毕后，系统将它们打包成一个结构化的字典返回。在新增记忆时，合并进记忆的 <code>metadata</code> 元数据中，与正文内容一并写入存储后端。</p><p>至此参数建档完成。<strong>计时器从这一刻开始滴答作响。</strong></p><hr><h2 id="三、衰减计算"><a href="#三、衰减计算" class="headerlink" title="三、衰减计算"></a>三、衰减计算</h2><p>时间开始走，记忆系统中的遗忘机制也开始运作，保留率开始随着时间的流逝慢慢往下掉。</p><p>先回顾一下艾宾浩斯遗忘曲线的数学形式：<code>R(t) = e^(-λt)</code>，它时指数衰减的。</p><h3 id="3-1-PowerMem-的衰减公式"><a href="#3-1-PowerMem-的衰减公式" class="headerlink" title="3.1 PowerMem 的衰减公式"></a>3.1 PowerMem 的衰减公式</h3><p>PowerMem 把理论公式翻译为代码：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">rate = self.decay_rate <span class="keyword">if</span> decay_rate <span class="keyword">is</span> <span class="literal">None</span> <span class="keyword">else</span> decay_rate</span><br><span class="line"></span><br><span class="line">decay_factor = math.exp(-hours_elapsed / (<span class="number">24</span> * rate))</span><br></pre></td></tr></table></figure><p>要看懂这条会议信息<strong>衰减的有多快</strong>，关键是要看懂分母 <code>24 × rate</code> 这个数。<code>24 × rate</code>** 是这条记忆的特征衰减时间，单位是小时。**</p><p>把这个数记作 <strong>S</strong>（Strength），即 <code>S = 24 × rate</code>。S 越大，分母越大，指数衰减就越慢，记忆活得就越久。代入公式会变为更清爽的形式：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">decay_factor = e^(-t / S)</span><br></pre></td></tr></table></figure><p>这个公式有一个很漂亮的性质：<strong>当时间 <strong><code>t</code></strong> 走过一个 S，保留率必然衰减到 <strong><code>e^(-1) ≈ 37%</code></strong>。</strong> 也就是说，无论 S 是几个小时，只要时间走完一个 S 剩下的记忆都是原来的 37%。这是指数衰减的固有特征。</p><p>所以只要知道 S 是多少小时，就大致知道这条记忆遗忘的节奏。</p><p>还是拿这条会议信息举例，它落在 short_term，rate &#x3D; 0.15，那么：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">S = 24 × 0.15 = 3.6（小时）</span><br></pre></td></tr></table></figure><p>也就是说，这条会议信息每过 <strong>3.6 小时</strong>，保留率就会衰减到上一刻的 37% 左右。</p><blockquote><p>最后还有一处工程细节，PowerMem 中存在一条回退机制：调用方首先会按记忆类型算出类型专属的衰减率并传入，但如果调用方没有传，就使用全局默认的衰减率进行计算。这种机制保证了即使旧版本的元数据中缺少类型信息，衰减计算也不会出错。</p></blockquote><h3 id="3-2-彩蛋，一个关键的工程取舍"><a href="#3-2-彩蛋，一个关键的工程取舍" class="headerlink" title="3.2 彩蛋，一个关键的工程取舍"></a>3.2 彩蛋，一个关键的工程取舍</h3><p>PowerMem 用的衰减公式和经典艾宾浩斯论文里的公式其实是等价的，只是写法不同。经典论文写的是 <code>R(t) = e^(-λt)</code>，那个 λ 叫做衰减常数，和 PowerMem 的 S 互为倒数：<code>λ = 1 / S</code>。</p><p>之所以提这件事，是因为如果把 PowerMem 的默认参数和经典艾宾浩斯实验的参数放在一起对比，就能发现一个有意思的细节：从经典的艾宾浩斯实验数据反推出 λ ≈ 0.821。但 PowerMem 默认配置对应的 λ ≈ 0.417，大约只有文档推导值的一半：</p><p>| 参数来源             | λ 值   | 1 小时后保留率 | 设计意图                           |</p><p>| ——————– | —— | ————– | ———————————- |</p><p>| 经典艾宾浩斯实验数据 | ~0.821 | ~44%           | 无意义音节（ZOF、WUX），纯记忆实验 |</p><p>| PowerMem 默认配置    | ~0.417 | ~66%           | 语义信息，天然遗忘更慢             |</p><p>这个差异不是 bug，而是一个工程决策。</p><p>理论上艾宾浩斯使用的是无意义音节，人类对这类孤立符号的遗忘速度最快，但 PowerMem 存储的是具有语义关联的实际信息，对语义信息的遗忘自然会比孤立音节更慢，所以 PowerMem 使用了更温和的衰减速率来匹配这一现实。</p><p>通过衰减参数（可在 <code>.env</code> 中配置 <code>INTELLIGENT_MEMORY_DECAY_RATE</code>）也可以精细控制遗忘的激进程度：</p><p>| decay_rate  | S &#x3D; 24 × rate | λ &#x3D; 1&#x2F;S | 1 小时后保留率 | 风格     |</p><p>| ———– | ————- | ——- | ————– | ——– |</p><p>| 0.05        | 1.2           | ~0.833  | ~43%           | 激进遗忘 |</p><p>| 0.1（默认） | 2.4           | ~0.417  | ~66%           | 平衡     |</p><p>| 0.2         | 4.8           | ~0.208  | ~81%           | 温和遗忘 |</p><p>衰减参数越小，遗忘越激进。</p><p><img src="/img/2026-06-12-powermem-memory-lifecycle/03.png" alt="记忆衰减计算中的工程取舍示意" loading="lazy" decoding="async"></p><h3 id="3-3-衰减时间表"><a href="#3-3-衰减时间表" class="headerlink" title="3.3 衰减时间表"></a>3.3 衰减时间表</h3><p>好，现在把上面的一切串起来，就会得到这条会议信息完整的衰减过程：</p><p>| 时间       | 距创建时长 | 衰减因子 | 状态                    |</p><p>| ———- | ———- | ——– | ———————– |</p><p>| 刚创建     | 0h         | 1.000    | 新鲜                    |</p><p>| 1 小时后   | 1h         | ≈ 0.757  | 轻度衰减                |</p><p>| 4.3 小时后 | 4.3h       | ≈ 0.300  | <strong>跌破遗忘阈值（0.3）</strong> |</p><p>| 6 小时后   | 6h         | ≈ 0.189  | 深度衰减                |</p><p>| 24 小时后  | 24h        | ≈ 0.0013 | 几乎归零                |</p><p>可以看到一条 short_term 记忆在约 4.3 小时后衰减因子就会跌破 0.3 的遗忘阈值，但这并不意味着它会被立即删除，遗忘决策的执行时机，取决于记忆何时被访问。</p><hr><h2 id="四、访问触发"><a href="#四、访问触发" class="headerlink" title="四、访问触发"></a>四、访问触发</h2><h3 id="4-1-将遗忘决策延迟到访问时"><a href="#4-1-将遗忘决策延迟到访问时" class="headerlink" title="4.1 将遗忘决策延迟到访问时"></a>4.1 将遗忘决策延迟到访问时</h3><p>衰减一直在后台进行，但遗忘的决策只在实际访问记忆时才被执行。</p><p>这里有个认知学背景：当一个已巩固的记忆被主动提取时它会暂时回到可塑状态，然后需要重新巩固。这个提取到再巩固的循环会加强对应的神经连接。</p><p>在工程层面，这意味着记忆的命运不应该由时间单向决定，而应该在每次被访问时重新评估。</p><p><strong>访问是记忆系统最重要的反馈信号。</strong> 一条信息被频繁访问说明它对用户有价值，应该被保留甚至晋升。一条信息长期无人问津，即使最初很重要也应该被遗忘。这种懒惰求值的设计降低了系统的计算负担，不需要后台定时任务批量扫描所有记忆。</p><h3 id="4-2-四道关卡"><a href="#4-2-四道关卡" class="headerlink" title="4.2 四道关卡"></a>4.2 四道关卡</h3><p>当用户通过 <code>Memory.get()</code> 或 <code>Memory.search()</code> 访问记忆时，会依次执行四道检查。</p><p><strong>第一关：遗忘检查</strong></p><p>两个触发遗忘的条件：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># 衰减因子跌破阈值</span></span><br><span class="line"></span><br><span class="line">rate = self._resolve_decay_rate(memory)</span><br><span class="line"></span><br><span class="line">decay_factor = self.calculate_decay(created_at, decay_rate=rate)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> decay_factor &lt; self.working_threshold:  <span class="comment"># 0.3</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 静默遗忘，从未被使用且已过 7 天</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> access_count == <span class="number">0</span> <span class="keyword">and</span> time_elapsed &gt; timedelta(days=<span class="number">7</span>):</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">True</span></span><br></pre></td></tr></table></figure><p>两个条件满足其一即触发遗忘。第一条，衰减到了阈值以下，该淘汰了。第二条也容易理解，<strong>从未被使用过本身就是最强的遗忘信号。</strong></p><p>满足了遗忘触发条件，调用方负责执行删除。</p><p><strong>第二关：晋升检查</strong></p><p>三个条件，满足其一即晋升：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># 高频访问（被访问 3 次以上）</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> access_count &gt;= <span class="number">3</span>:</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 通过时间检验（存活超过 24 小时）</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> time_elapsed &gt; timedelta(hours=<span class="number">24</span>):</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本质上很重要（重要性分数大于0.6）</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> importance &gt;= self.short_term_threshold:  <span class="comment"># 0.6</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">True</span></span><br></pre></td></tr></table></figure><p>晋升的效果：<code>working → short_term</code> 或 <code>short_term → long_term</code>。衰减速率倍率从高降到低，信息获得更长的寿命。</p><p>在会议信息这个例子中，importance&#x3D;0.72 ≥ 0.6，<strong>第一次访问时就直接满足晋升条件</strong>。如果它此时还是 short_term，将升级为 long_term。一条信息通过晋升机制，实现了从临时便签到长期知识的演变。</p><p>这是人脑记忆巩固过程的工程对应。</p><p><strong>第三关：归档检查</strong></p><p>两个条件：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># 自然老化（超过 30 天）</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> time_elapsed &gt; timedelta(days=<span class="number">30</span>):</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 本质上不重要（重要性分数小于0.3）</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> importance &lt; self.working_threshold:  <span class="comment"># 0.3</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">True</span></span><br></pre></td></tr></table></figure><p>归档不同于遗忘。被归档的记忆不会被物理删除，但从活跃检索池中移除，进入存档状态。用户仍可通过专门的归档检索接口访问。</p><p><strong>第四关：周期重处理</strong></p><p>每当访问次数是 5 的倍数（第 5 次、第 10 次……），或记忆类型发生变更，系统重新计算全部 Ebbinghaus 元数据。这确保记忆的参数始终与其访问模式保持一致。随着访问累积，衰减率和复习调度逐步趋于稳定，这正是间隔重复效应在工程层面的体现。</p><p><img src="/img/2026-06-12-powermem-memory-lifecycle/04.png" alt="记忆淘汰前的四道安全关卡" loading="lazy" decoding="async"></p><hr><h2 id="五、搜索加权"><a href="#五、搜索加权" class="headerlink" title="五、搜索加权"></a>五、搜索加权</h2><h3 id="5-1-干扰理论在搜索中的体现"><a href="#5-1-干扰理论在搜索中的体现" class="headerlink" title="5.1 干扰理论在搜索中的体现"></a>5.1 干扰理论在搜索中的体现</h3><blockquote><p>记忆的困难不在于存不进去，而在于取不出来。随着存储信息增多，记忆之间的交叉干扰呈指数级增长。</p></blockquote><p>当用户搜索「Q2 评审」时，如果系统只按语义相似度排序，可能出现这种情况：一条 3 个月前的会议纪要语义完美匹配，排在最前面。而昨天刚更新的评审时间变更信息排在后面。<strong>语义匹配度最高 ≠ 用户最需要。</strong></p><p>PowerMem 通过为搜索结果引入时间维度来解决这个问题。</p><h3 id="5-2-排序公式"><a href="#5-2-排序公式" class="headerlink" title="5.2 排序公式"></a>5.2 排序公式</h3><p>先上公式：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">final_score = relevance_score × decay_factor</span><br></pre></td></tr></table></figure><ul><li><code>relevance_score</code> 是关键词匹配度</li><li><code>decay_factor</code> 是前面提到的衰减因子</li></ul><p>这个公式做了一次<strong>交叉排序</strong>。高语义匹配但时间久远的记忆，可能被中等匹配度但非常新鲜的记忆超越：</p><p>| 记忆                         | 语义匹配度 | 衰减因子 | final_score | 排名 |</p><p>| —————————- | ———- | ——– | ———– | —- |</p><p>| 1 分钟前的闲聊，中等匹配     | 0.45       | 0.99     | <strong>0.45</strong>    | 1    |</p><p>| 3 小时前的会议记录，高度匹配 | 0.92       | 0.29     | <strong>0.27</strong>    | 2    |</p><p>| 10 天前的会议记录，完美匹配  | 0.98       | ~0.00    | ~0.00       | 末尾 |</p><p>大白话讲，新鲜度在搜索排序中有一票否决权。再怎么匹配，衰减到接近零的老记忆也会被沉到底部。</p><p><img src="/img/2026-06-12-powermem-memory-lifecycle/05.png" alt="PowerMem 检索结果排序加权公式" loading="lazy" decoding="async"></p><p>此外，搜索本身也是记忆访问。<strong>在进行搜索时，会对每条搜索结果依次调用 <strong><code>Memory.get</code></strong>，实现批量生命周期管理。</strong></p><hr><h2 id="六、全局优化"><a href="#六、全局优化" class="headerlink" title="六、全局优化"></a>六、全局优化</h2><h3 id="6-1-为什么需要全局优化"><a href="#6-1-为什么需要全局优化" class="headerlink" title="6.1 为什么需要全局优化"></a>6.1 为什么需要全局优化</h3><p>前面讲的都是针对单条记忆的实时管理。但记忆系统还需要周期性的全局治理。随着信息不断积累，重复、冗余、碎片化等问题都会逐渐显现。</p><p>这类似于大脑在睡眠阶段进行的记忆整理。海马体将记忆重放并转移至新皮层，同时去除重复信息、合并相似记忆、强化重要连接。</p><p>PowerMem 提供三种互补的优化策略。</p><h3 id="6-2-三种优化策略"><a href="#6-2-三种优化策略" class="headerlink" title="6.2 三种优化策略"></a>6.2 三种优化策略</h3><p><strong>（1）精确去重</strong></p><p>基于内容哈希的精确匹配。系统维护一个 <code>hash → [memories]</code> 的映射，保留每组中最早创建的记录，删除其余。一次最多处理 10,000 条记录。</p><p>完全相同的两条信息只留一条。这是最基础的清理。</p><p><strong>（2）语义去重</strong></p><p>基于 embedding 余弦相似度，识别语义高度近似但措辞不同的记忆。使用 O(N×M) 逐对比较，默认阈值 0.95。相似度超过阈值的较新记忆被删除，保留最早的那条。</p><p>比如「Q2 评审改到下周三了」和「Q2 review 推迟到下周三」语义相同但文字不同，语义去重能识别出来。</p><p><strong>（3）记忆压缩</strong></p><p>对多条语义相似但不严格重复的记忆，使用 LLM 将其总结为一条精炼的合成记忆。流程分两步：</p><ol><li><strong>贪心聚类</strong>：将相似度超过阈值（默认 0.85）的记忆归为一组</li><li><strong>LLM 摘要</strong>：使用提示模板让 LLM 生成精炼摘要，用一条合成记忆替换整个聚类</li></ol><p>这三个机制与遗忘衰减协同，构成从**微观（逐条衰减）到宏观（批量压缩）**的完整记忆质量管理体系。</p><p><img src="/img/2026-06-12-powermem-memory-lifecycle/06.png" alt="记忆全局优化的三种精简策略" loading="lazy" decoding="async"></p><hr><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>信息量不小。回顾这条会议信息在 PowerMem 中走过的路：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">&quot;下周五下午三点评审 Q2 需求文档&quot; 进入系统</span><br><span class="line"></span><br><span class="line">  ↓</span><br><span class="line"></span><br><span class="line">重要性评估 → &quot;这条信息有多重要？&quot; → 0.72</span><br><span class="line"></span><br><span class="line">  ↓</span><br><span class="line"></span><br><span class="line">分类 → &quot;分到哪一层？&quot; → 短期记忆</span><br><span class="line"></span><br><span class="line">  ↓</span><br><span class="line"></span><br><span class="line">参数初始化 → &quot;配一个衰减计时器&quot; → 衰减率和复习间隔已排好</span><br><span class="line"></span><br><span class="line">  ↓</span><br><span class="line"></span><br><span class="line">时间流逝 → 衰减进行中，保留率持续下降</span><br><span class="line"></span><br><span class="line">  ↓</span><br><span class="line"></span><br><span class="line">被访问 → &quot;还活着吗？需要升级吗？&quot; → 检查通过，晋升为长期记忆</span><br><span class="line"></span><br><span class="line">  ↓</span><br><span class="line"></span><br><span class="line">被搜索 → &quot;排在第几位？&quot; → 时间新鲜度 × 语义匹配度</span><br><span class="line"></span><br><span class="line">  ↓</span><br><span class="line"></span><br><span class="line">全局优化 → &quot;有重复吗？能压缩吗？&quot; → 去重与合并</span><br></pre></td></tr></table></figure><p>核心思路贯穿始终：<strong>用有限资源保留最有价值的信息，同时保持检索的高信噪比。</strong></p><p>六个节点各司其职：</p><ul><li><strong>重要性评估</strong>解决记住什么</li><li><strong>分类</strong>解决记住多久</li><li><strong>衰减</strong>解决何时淘汰</li><li><strong>访问触发</strong>解决动态调整</li><li><strong>搜索加权</strong>解决怎么找到</li><li><strong>全局优化</strong>解决怎么精简</li></ul><p>我觉得 PowerMem 这套设计最有意思的地方在于，它没有把遗忘当作一个”<strong>要不要删</strong>”的二元问题来处理，从写入的那一刻起衰减就在发生。但衰减不等于删除，它只是一个持续变化的权重，真正决定一条记忆命运的，是它有没有被再次访问，这跟人脑的工作方式很一致。</p><p><strong>遗忘不是记忆系统的事后补救，而是贯穿整个生命周期的核心设计维度。</strong></p><p><img src="/img/2026-06-12-powermem-memory-lifecycle/07.png" alt="PowerMem 记忆完整生命周期总览" loading="lazy" decoding="async"></p><hr><p><strong>参考资料：</strong></p><ol><li>PowerMem GitHub Repository — <a href="https://github.com/oceanbase/powermem">https://github.com/oceanbase/powermem</a></li><li>PowerMem Docs — <a href="https://github.com/oceanbase/powermem/blob/main/docs/guides/0008-ebbinghaus_forgetting_curve.md">Ebbinghaus Forgetting Curve Guide</a></li></ol><hr><p><em>本文基于 PowerMem v1.1.1 源码分析撰写，所有代码引用均来自实际项目。</em></p>]]>
    </content>
    <id>https://ilongda.com/2026/2026-06-12-powermem-memory-lifecycle/</id>
    <link href="https://ilongda.com/2026/2026-06-12-powermem-memory-lifecycle/"/>
    <published>2026-06-11T23:44:48.000Z</published>
    <summary>用一条消息跟踪 PowerMem：重要性评估、分层存储、衰减复习到淘汰，看清 AI Agent 长期记忆工程如何实现智能遗忘。</summary>
    <title>PowerMem 记忆生命周期：一条信息从写入到淘汰怎么走完</title>
    <updated>2026-06-11T23:44:48.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="用户实践" scheme="https://ilongda.com/categories/%E7%94%A8%E6%88%B7%E5%AE%9E%E8%B7%B5/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="AI Agent" scheme="https://ilongda.com/tags/AI-Agent/"/>
    <category term="MCP" scheme="https://ilongda.com/tags/MCP/"/>
    <category term="seekdb" scheme="https://ilongda.com/tags/seekdb/"/>
    <category term="PowerMem" scheme="https://ilongda.com/tags/PowerMem/"/>
    <category term="Python" scheme="https://ilongda.com/tags/Python/"/>
    <category term="操作手册" scheme="https://ilongda.com/tags/%E6%93%8D%E4%BD%9C%E6%89%8B%E5%86%8C/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"PowerMem 操作手册：从 Linux 部署到 Claude Code / OpenClaw 接入","description":"PowerMem 简明操作手册：Linux 安装配置、HTTP 服务、Dashboard、Claude Code 与 OpenClaw 接入，快速搭建可自进化的 Agent 记忆层。","image":"https://ilongda.com/img/2026-06-12-powermem-operation-guide/01.png","wordCount":1847,"datePublished":"2026-06-11T22:18:50.000Z","dateModified":"2026-06-11T22:18:50.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-06-12-powermem-operation-guide/"},"url":"https://ilongda.com/2026/2026-06-12-powermem-operation-guide/","inLanguage":"zh-CN","keywords":["OceanBase","AI Agent","MCP","seekdb","PowerMem","Python","操作手册"],"articleSection":["用户实践"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"用户实践","item":"https://ilongda.com/categories/用户实践/"},{"@type":"ListItem","position":3,"name":"PowerMem 操作手册：从 Linux 部署到 Claude Code / OpenClaw 接入","item":"https://ilongda.com/2026/2026-06-12-powermem-operation-guide/"}]}</script><p><img src="/img/2026-06-12-powermem-operation-guide/01.png" alt="PowerMem Agent 记忆层部署总览" decoding="async"></p><blockquote><p>💡 仓库在这：<a href="https://github.com/oceanbase/powermem">oceanbase&#x2F;powermem</a>。想给 Agent 加上会检索、会整理、会遗忘的记忆，按本文顺序做完就能跑通。</p></blockquote><p>本手册覆盖完整链路：Linux 服务端安装与配置 → 启动 HTTP &#x2F; Dashboard → 本地 Claude Code 连接 → OpenClaw 落库。按章节顺序操作即可，无需先读原理。</p><span id="more"></span><hr><h2 id="一、Linux-服务端：安装、配置、启动"><a href="#一、Linux-服务端：安装、配置、启动" class="headerlink" title="一、Linux 服务端：安装、配置、启动"></a>一、Linux 服务端：安装、配置、启动</h2><p><img src="/img/2026-06-12-powermem-operation-guide/02.png" alt="Linux 服务端安装与启动步骤示意" loading="lazy" decoding="async"></p><h3 id="1-1-环境要求"><a href="#1-1-环境要求" class="headerlink" title="1.1 环境要求"></a>1.1 环境要求</h3><ul><li>Python &gt;&#x3D; 3.11</li><li>pip 或 uv（推荐 uv，更快）</li></ul><h3 id="1-2-安装"><a href="#1-2-安装" class="headerlink" title="1.2 安装"></a>1.2 安装</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 从 PyPI 安装（生产环境推荐）</span></span><br><span class="line">uv pip install <span class="string">&quot;powermem[cli,server,mcp,seekdb]&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 或从源码安装（开发环境）</span></span><br><span class="line">git <span class="built_in">clone</span> https://github.com/oceanbase/powermem.git</span><br><span class="line"><span class="built_in">cd</span> powermem</span><br><span class="line">uv pip install -e <span class="string">&quot;.[cli,server,mcp,seekdb]&quot;</span></span><br></pre></td></tr></table></figure><p>各 extras 说明：</p><table><thead><tr><th>extras</th><th>作用</th></tr></thead><tbody><tr><td><code>cli</code></td><td><code>pmem</code> 命令行工具</td></tr><tr><td><code>server</code></td><td><code>powermem-server</code> HTTP API 服务器</td></tr><tr><td><code>mcp</code></td><td>MCP 协议支持</td></tr><tr><td><code>seekdb</code></td><td>内嵌向量数据库（零配置，无需单独部署数据库）</td></tr></tbody></table><h3 id="1-3-初始化配置"><a href="#1-3-初始化配置" class="headerlink" title="1.3 初始化配置"></a>1.3 初始化配置</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 交互式生成 .env 配置文件</span></span><br><span class="line">pmem config init</span><br></pre></td></tr></table></figure><p><img src="/img/2026-06-12-powermem-operation-guide/03.png" alt="PowerMem 交互式初始化配置界面" loading="lazy" decoding="async"></p><p>也可手动创建 <code>.env</code> 文件。以下是我的配置：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># DATABASE_PROVIDER=oceanbase</span></span><br><span class="line">DATABASE_PROVIDER=sqlite</span><br><span class="line">SQLITE_PATH=/root/data/package/powermem/powermem.db</span><br><span class="line"><span class="comment"># LLM_PROVIDER=anthropic</span></span><br><span class="line">LLM_PROVIDER=openai</span><br><span class="line"><span class="comment"># ANTHROPIC_LLM_BASE_URL=https://token-plan-cn.xiaomimimo.com/anthropic</span></span><br><span class="line"><span class="comment"># LLM_API_KEY=tp-xxx</span></span><br><span class="line"><span class="comment"># LLM_MODEL=mimo-v2.5-pro</span></span><br><span class="line">LLM_API_KEY=xxx</span><br><span class="line">LLM_MODEL=step-3.7-flash</span><br><span class="line">OPENAI_LLM_BASE_URL=https://api.stepfun.com/step_plan/v1</span><br><span class="line">EMBEDDING_PROVIDER=siliconflow</span><br><span class="line">EMBEDDING_API_KEY=sk-xx</span><br><span class="line">EMBEDDING_MODEL=BAAI/bge-m3</span><br><span class="line"><span class="comment"># OCEANBASE_EMBEDDING_MODEL_DIMS=1024</span></span><br><span class="line"><span class="comment"># EMBEDDING_DIMS=1024</span></span><br></pre></td></tr></table></figure><p><strong>注意事项：</strong></p><ul><li><code>SQLITE_PATH</code> 必须是完整的数据库文件路径（如 <code>/root/data/powermem/powermem.db</code>），不能只是文件夹路径</li><li>使用 seekdb 时，<code>EMBEDDING_DIMS</code> 或 <code>OCEANBASE_EMBEDDING_MODEL_DIMS</code> 是必填项，维度要和嵌入模型匹配</li><li>硅基流动的嵌入模型如果不走 seekdb，可以不配 <code>EMBEDDING_DIMS</code></li></ul><h3 id="1-4-启动服务器"><a href="#1-4-启动服务器" class="headerlink" title="1.4 启动服务器"></a>1.4 启动服务器</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">powermem-server --host 0.0.0.0 --port 8848</span><br></pre></td></tr></table></figure><p>参数说明：</p><table><thead><tr><th>参数</th><th>默认值</th><th>说明</th></tr></thead><tbody><tr><td><code>--host</code></td><td><code>0.0.0.0</code></td><td>监听地址</td></tr><tr><td><code>--port</code></td><td><code>8848</code></td><td>监听端口</td></tr><tr><td><code>--workers</code></td><td><code>4</code></td><td>工作进程数（内嵌存储自动降为 1）</td></tr><tr><td><code>--reload</code></td><td>关闭</td><td>开发模式，代码变更自动重载</td></tr><tr><td><code>--log-level</code></td><td><code>INFO</code></td><td>日志级别</td></tr></tbody></table><p>首次启动会比较慢（60-120 秒），因为需要初始化 seekdb 和下载嵌入模型。</p><p>验证启动成功：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">curl http://localhost:8848/api/v1/system/health</span><br><span class="line"><span class="comment"># 返回 &#123;&quot;status&quot;:&quot;ok&quot;&#125; 即成功</span></span><br></pre></td></tr></table></figure><hr><h2 id="二、Dashboard-使用"><a href="#二、Dashboard-使用" class="headerlink" title="二、Dashboard 使用"></a>二、Dashboard 使用</h2><p><img src="/img/2026-06-12-powermem-operation-guide/04.png" alt="PowerMem Dashboard 功能入口总览" loading="lazy" decoding="async"></p><h3 id="2-1-访问-Dashboard"><a href="#2-1-访问-Dashboard" class="headerlink" title="2.1 访问 Dashboard"></a>2.1 访问 Dashboard</h3><p>服务器启动后，浏览器打开：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://&lt;服务器IP&gt;:8848/dashboard/</span><br></pre></td></tr></table></figure><p><img src="/img/2026-06-12-powermem-operation-guide/05.png" alt="浏览器访问 PowerMem Dashboard 首页" loading="lazy" decoding="async"></p><p><img src="/img/2026-06-12-powermem-operation-guide/06.png" alt="Dashboard 记忆列表与检索面板" loading="lazy" decoding="async"></p><h3 id="2-2-Dashboard-功能"><a href="#2-2-Dashboard-功能" class="headerlink" title="2.2 Dashboard 功能"></a>2.2 Dashboard 功能</h3><table><thead><tr><th>页面</th><th>路径</th><th>功能</th></tr></thead><tbody><tr><td>总览</td><td><code>/dashboard/</code></td><td>记忆总量、增长趋势、质量指标、系统健康</td></tr><tr><td>记忆管理</td><td><code>/dashboard/memories</code></td><td>浏览、搜索、查看、删除记忆</td></tr><tr><td>用户画像</td><td><code>/dashboard/user-profile</code></td><td>查看用户级别的聚合画像</td></tr><tr><td>设置</td><td><code>/dashboard/settings</code></td><td>配置 API Key（仅在服务端开启认证时需要）</td></tr></tbody></table><h3 id="2-3-开启认证（可选）"><a href="#2-3-开启认证（可选）" class="headerlink" title="2.3 开启认证（可选）"></a>2.3 开启认证（可选）</h3><p>在 <code>.env</code> 中添加：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">POWERMEM_SERVER_AUTH_ENABLED=<span class="literal">true</span></span><br><span class="line">POWERMEM_SERVER_API_KEYS=your-secret-key</span><br></pre></td></tr></table></figure><p>重启服务器后，所有 API 请求需携带 <code>X-API-Key</code> 头。Dashboard 的 Settings 页面可配置 Key。</p><h3 id="2-4-API-文档"><a href="#2-4-API-文档" class="headerlink" title="2.4 API 文档"></a>2.4 API 文档</h3><p>服务器自带 Swagger 文档：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://&lt;服务器IP&gt;:8848/docs</span><br></pre></td></tr></table></figure><hr><h2 id="三、本地-Claude-Code-连接-PowerMem-服务器"><a href="#三、本地-Claude-Code-连接-PowerMem-服务器" class="headerlink" title="三、本地 Claude Code 连接 PowerMem 服务器"></a>三、本地 Claude Code 连接 PowerMem 服务器</h2><p><img src="/img/2026-06-12-powermem-operation-guide/07.png" alt="Claude Code 连接远程 PowerMem 示意" loading="lazy" decoding="async"></p><p>以下步骤在本地 Windows&#x2F;Mac 操作，服务器在远程 Linux。</p><h3 id="3-1-在-Dashboard-获取-API-Key"><a href="#3-1-在-Dashboard-获取-API-Key" class="headerlink" title="3.1 在 Dashboard 获取 API Key"></a>3.1 在 Dashboard 获取 API Key</h3><p>如果服务端开启了认证，先在 Dashboard Settings 页面拿到 API Key。</p><p><img src="/img/2026-06-12-powermem-operation-guide/08.png" alt="Dashboard 中创建并复制 API Key" loading="lazy" decoding="async"></p><h3 id="3-2-通过-Marketplace-安装插件"><a href="#3-2-通过-Marketplace-安装插件" class="headerlink" title="3.2 通过 Marketplace 安装插件"></a>3.2 通过 Marketplace 安装插件</h3><p>在 Claude Code 中依次执行：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">/plugin marketplace add oceanbase/powermem</span><br><span class="line">/plugin install memory-powermem@powermem</span><br><span class="line">/reload-plugins</span><br></pre></td></tr></table></figure><blockquote><p>如果网络不通，也可以从源码安装：<code>claude --plugin-dir /path/to/powermem/apps/claude-code-plugin</code></p></blockquote><h3 id="3-3-初始化插件"><a href="#3-3-初始化插件" class="headerlink" title="3.3 初始化插件"></a>3.3 初始化插件</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/memory-powermem:init</span><br></pre></td></tr></table></figure><p>这会自动创建插件本地虚拟环境、安装 powermem 后端、启动管理服务器。</p><h3 id="3-4-Windows-用户：修复-hooks-命令"><a href="#3-4-Windows-用户：修复-hooks-命令" class="headerlink" title="3.4 Windows 用户：修复 hooks 命令"></a>3.4 Windows 用户：修复 hooks 命令</h3><p><strong>init 生成的 hooks.json 默认使用 <strong><code>sh</code></strong>，Windows 需要改为 PowerShell。</strong></p><p><img src="/img/2026-06-12-powermem-operation-guide/09.png" alt="Windows 下修复 hooks 命令路径" loading="lazy" decoding="async"></p><p>hooks 文件位置：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">C:\Users\&lt;你的用户名&gt;\.claude\plugins\cache\powermem\memory-powermem\0.1.0\hooks\hooks.json</span><br></pre></td></tr></table></figure><p>将所有 <code>sh &quot;${CLAUDE_PLUGIN_ROOT}/hooks/run-hook.sh&quot;</code> 替换为：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">&quot;command&quot;</span><span class="punctuation">:</span> <span class="string">&quot;powershell.exe -NoProfile -ExecutionPolicy Bypass -File \&quot;$&#123;CLAUDE_PLUGIN_ROOT&#125;/hooks/run-hook.ps1\&quot;&quot;</span></span><br></pre></td></tr></table></figure><p>完整示例：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;hooks&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;UserPromptSubmit&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">      <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;hooks&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">          <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;command&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;command&quot;</span><span class="punctuation">:</span> <span class="string">&quot;powershell.exe -NoProfile -ExecutionPolicy Bypass -File \&quot;$&#123;CLAUDE_PLUGIN_ROOT&#125;/hooks/run-hook.ps1\&quot;&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;timeout&quot;</span><span class="punctuation">:</span> <span class="number">120</span></span><br><span class="line">          <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">]</span></span><br><span class="line">      <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;SessionEnd&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">      <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;hooks&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">          <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;command&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;command&quot;</span><span class="punctuation">:</span> <span class="string">&quot;powershell.exe -NoProfile -ExecutionPolicy Bypass -File \&quot;$&#123;CLAUDE_PLUGIN_ROOT&#125;/hooks/run-hook.ps1\&quot;&quot;</span></span><br><span class="line">          <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">]</span></span><br><span class="line">      <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;PostCompact&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">      <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;matcher&quot;</span><span class="punctuation">:</span> <span class="string">&quot;auto|manual&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;hooks&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">          <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;command&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;command&quot;</span><span class="punctuation">:</span> <span class="string">&quot;powershell.exe -NoProfile -ExecutionPolicy Bypass -File \&quot;$&#123;CLAUDE_PLUGIN_ROOT&#125;/hooks/run-hook.ps1\&quot;&quot;</span></span><br><span class="line">          <span class="punctuation">&#125;</span></span><br><span class="line">        <span class="punctuation">]</span></span><br><span class="line">      <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">]</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><h3 id="3-5-配置连接远程服务器"><a href="#3-5-配置连接远程服务器" class="headerlink" title="3.5 配置连接远程服务器"></a>3.5 配置连接远程服务器</h3><p>如果 powermem-server 不在本机（比如在远程 Linux），需要配置环境变量。</p><p>方式一：在 Claude Code 的 <code>settings.json</code> 中配置（推荐）：</p><p>编辑 <code>~/.claude/settings.json</code>，添加：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;env&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;POWERMEM_BASE_URL&quot;</span><span class="punctuation">:</span> <span class="string">&quot;http://&lt;服务器IP&gt;:8848&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;POWERMEM_API_KEY&quot;</span><span class="punctuation">:</span> <span class="string">&quot;your-secret-key&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p><img src="/img/2026-06-12-powermem-operation-guide/10.png" alt="配置 Claude Code 连接远程服务器" loading="lazy" decoding="async"></p><p>方式二：在启动 Claude Code 前设置环境变量：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">export</span> POWERMEM_BASE_URL=http://&lt;服务器IP&gt;:8848</span><br><span class="line"><span class="built_in">export</span> POWERMEM_API_KEY=your-secret-key</span><br></pre></td></tr></table></figure><h3 id="3-6-重启-Claude-Code"><a href="#3-6-重启-Claude-Code" class="headerlink" title="3.6 重启 Claude Code"></a>3.6 重启 Claude Code</h3><p>重新启动 Claude Code 即可生效。</p><h3 id="3-7-验证"><a href="#3-7-验证" class="headerlink" title="3.7 验证"></a>3.7 验证</h3><p>记忆落库时机：</p><ul><li><strong>用户发送消息时</strong>：自动检索相关记忆，注入到上下文中（默认开启）</li><li><strong>执行 &#x2F;compact 时</strong>：将压缩摘要保存为记忆</li><li><strong>退出会话时</strong>：将完整会话记录保存为记忆</li></ul><p>验证方法：结束一个会话后，在 Dashboard 的 Memories 页面查看是否有新记忆写入。</p><hr><h2 id="四、OpenClaw-安装-PowerMem-并连接落库"><a href="#四、OpenClaw-安装-PowerMem-并连接落库" class="headerlink" title="四、OpenClaw 安装 PowerMem 并连接落库"></a>四、OpenClaw 安装 PowerMem 并连接落库</h2><p><img src="/img/2026-06-12-powermem-operation-guide/11.png" alt="OpenClaw 安装 PowerMem 插件流程" loading="lazy" decoding="async"></p><h3 id="4-1-安装插件"><a href="#4-1-安装插件" class="headerlink" title="4.1 安装插件"></a>4.1 安装插件</h3><p>直接跟 OpenClaw 说：</p><blockquote><p>通过 memory-powermem 帮我安装一下 powermem 记忆引擎插件</p></blockquote><p>或手动执行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">openclaw plugins install memory-powermem</span><br></pre></td></tr></table></figure><h3 id="4-2-配置嵌入模型"><a href="#4-2-配置嵌入模型" class="headerlink" title="4.2 配置嵌入模型"></a>4.2 配置嵌入模型</h3><p>阿里云百炼的 coding plan 没有嵌入模型，需要手动编辑 powermem 环境文件：</p><p>找到插件数据目录下的 <code>powermem.env</code>（通常在 <code>~/.openclaw/</code> 下），添加&#x2F;修改嵌入模型相关配置：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">EMBEDDING_PROVIDER=siliconflow</span><br><span class="line">EMBEDDING_API_KEY=sk-xxx</span><br><span class="line">EMBEDDING_MODEL=BAAI/bge-m3</span><br><span class="line">EMBEDDING_DIMS=1024</span><br></pre></td></tr></table></figure><p><img src="/img/2026-06-12-powermem-operation-guide/12.png" alt="OpenClaw 选择嵌入模型提供商" loading="lazy" decoding="async"></p><blockquote><p>根据实际使用的嵌入服务调整 provider、model 和维度。</p></blockquote><p><img src="/img/2026-06-12-powermem-operation-guide/13.png" alt="填写嵌入模型名称与维度参数" loading="lazy" decoding="async"></p><p><img src="/img/2026-06-12-powermem-operation-guide/14.png" alt="嵌入模型配置完成后的确认界面" loading="lazy" decoding="async"></p><h3 id="4-3-连接远程服务器（可选）"><a href="#4-3-连接远程服务器（可选）" class="headerlink" title="4.3 连接远程服务器（可选）"></a>4.3 连接远程服务器（可选）</h3><p>默认 CLI 模式使用本地 <code>pmem</code> 存储，无需额外服务器。</p><p>如果需要共享团队的 PowerMem 后端，在 OpenClaw 中配置 <code>requestConfig.memory_db</code> 指向服务器地址：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://&lt;服务器IP&gt;:8848</span><br></pre></td></tr></table></figure><h3 id="4-4-验证"><a href="#4-4-验证" class="headerlink" title="4.4 验证"></a>4.4 验证</h3><ol><li>让 OpenClaw 记住一句话：<code>帮我记住测试探针：dragonfruit-zx9</code></li><li>新开对话，让 OpenClaw 回忆：<code>dragonfruit-zx9 是什么</code></li><li>能正确召回即表示工作正常</li></ol><hr><h2 id="PowerMem-记忆如何”自进化”？"><a href="#PowerMem-记忆如何”自进化”？" class="headerlink" title="PowerMem 记忆如何”自进化”？"></a>PowerMem 记忆如何”自进化”？</h2><p><img src="/img/2026-06-12-powermem-operation-guide/15.png" alt="PowerMem 记忆捕获存储检索进化闭环" loading="lazy" decoding="async"></p><p>PowerMem 不止是一个存储桶——它是一个<strong>持续进化的记忆层</strong>。每条记忆从捕获到落库再到被检索，经历一个完整的生命周期：</p><ol><li><strong>捕获（Capture）</strong>：用户每次发消息，PowerMem 自动检索相关记忆注入上下文；执行 <code>/compact</code> 时，压缩摘要自动落为记忆；会话结束时，完整会话记录被保存</li><li><strong>存储（Store）</strong>：文本经过 Embedding 向量化，与元数据一同落入 SQLite &#x2F; OceanBase 数据库，被持久化保存</li><li><strong>检索（Retrieve）</strong>：用户提问时，语义向量检索找到最相关的 Top-K 条记忆，注入到上下文中增强 Agent 回答质量</li><li><strong>进化（Evolve）</strong>：重复记忆被去重合并，用户画像持续更新，过期记忆淘汰、新记忆增强</li></ol><p>这个四步循环让 Agent 越用越聪明，越用越懂你。</p><hr><h2 id="快速参考"><a href="#快速参考" class="headerlink" title="快速参考"></a>快速参考</h2><p><img src="/img/2026-06-12-powermem-operation-guide/16.png" alt="PowerMem 常用命令快速参考表" loading="lazy" decoding="async"></p><h3 id="整体链路图"><a href="#整体链路图" class="headerlink" title="整体链路图"></a>整体链路图</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">┌──────────────────────────────────────────────────────────┐</span><br><span class="line">│  Linux 服务器                                            │</span><br><span class="line">│                                                          │</span><br><span class="line">│  ┌─────────────┐    ┌──────────────┐                     │</span><br><span class="line">│  │ powermem    │    │  Dashboard   │                     │</span><br><span class="line">│  │ -server     │    │  :8848/      │                     │</span><br><span class="line">│  │ :8848       │    │  dashboard/  │                     │</span><br><span class="line">│  └──────┬──────┘    └──────────────┘                     │</span><br><span class="line">│         │                                                │</span><br><span class="line">│    .env 配置                                             │</span><br><span class="line">│    - DATABASE_PROVIDER                                   │</span><br><span class="line">│    - LLM_PROVIDER / API_KEY / MODEL                      │</span><br><span class="line">│    - EMBEDDING_PROVIDER / API_KEY / MODEL                │</span><br><span class="line">└─────────┬────────────────────────────────────────────────┘</span><br><span class="line">          │ HTTP API (:8848)</span><br><span class="line">          │</span><br><span class="line">     ┌────┴─────────────┐</span><br><span class="line">     │                  │</span><br><span class="line">     ▼                  ▼</span><br><span class="line">┌──────────┐      ┌──────────┐</span><br><span class="line">│ Claude   │      │ OpenClaw │</span><br><span class="line">│ Code     │      │          │</span><br><span class="line">│ (插件    │      │ (插件    │</span><br><span class="line">│  hooks)  │      │ CLI/HTTP)│</span><br><span class="line">└──────────┘      └──────────┘</span><br></pre></td></tr></table></figure><h3 id="常用命令速查"><a href="#常用命令速查" class="headerlink" title="常用命令速查"></a>常用命令速查</h3><table><thead><tr><th>操作</th><th>命令</th></tr></thead><tbody><tr><td>安装</td><td><code>uv pip install &quot;powermem[cli,server,mcp,seekdb]&quot;</code></td></tr><tr><td>初始化配置</td><td><code>pmem config init</code></td></tr><tr><td>启动服务器</td><td><code>powermem-server --host 0.0.0.0 --port 8848</code></td></tr><tr><td>健康检查</td><td><code>curl http://localhost:8848/api/v1/system/health</code></td></tr><tr><td>Dashboard</td><td><code>http://localhost:8848/dashboard/</code></td></tr><tr><td>API 文档</td><td><code>http://localhost:8848/docs</code></td></tr></tbody></table>]]>
    </content>
    <id>https://ilongda.com/2026/2026-06-12-powermem-operation-guide/</id>
    <link href="https://ilongda.com/2026/2026-06-12-powermem-operation-guide/"/>
    <published>2026-06-11T22:18:50.000Z</published>
    <summary>PowerMem 简明操作手册：Linux 安装配置、HTTP 服务、Dashboard、Claude Code 与 OpenClaw 接入，快速搭建可自进化的 Agent 记忆层。</summary>
    <title>PowerMem 操作手册：从 Linux 部署到 Claude Code / OpenClaw 接入</title>
    <updated>2026-06-11T22:18:50.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="最新动态" scheme="https://ilongda.com/categories/%E6%9C%80%E6%96%B0%E5%8A%A8%E6%80%81/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="智能运维" scheme="https://ilongda.com/tags/%E6%99%BA%E8%83%BD%E8%BF%90%E7%BB%B4/"/>
    <category term="AI Agent" scheme="https://ilongda.com/tags/AI-Agent/"/>
    <category term="seekdb" scheme="https://ilongda.com/tags/seekdb/"/>
    <category term="AgentSeek" scheme="https://ilongda.com/tags/AgentSeek/"/>
    <category term="社区月报" scheme="https://ilongda.com/tags/%E7%A4%BE%E5%8C%BA%E6%9C%88%E6%8A%A5/"/>
    <category term="异步索引" scheme="https://ilongda.com/tags/%E5%BC%82%E6%AD%A5%E7%B4%A2%E5%BC%95/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"OceanBase 社区月报：AgentSeek 首发，seekdb 1.3.0 流式写入提速 22 倍","description":"OceanBase 社区月报：seekdb 1.3.0 异步索引与流式写入提速约 22 倍，AgentSeek 智能体工程套件首发，obd / obdiag 与生态认证同步更新。","image":"https://ilongda.com/img/2026-06-10-oceanbase-community-monthly-agentseek-seekdb/01.webp","wordCount":1442,"datePublished":"2026-06-10T14:34:16.000Z","dateModified":"2026-06-10T14:34:16.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-06-10-oceanbase-community-monthly-agentseek-seekdb/"},"url":"https://ilongda.com/2026/2026-06-10-oceanbase-community-monthly-agentseek-seekdb/","inLanguage":"zh-CN","keywords":["OceanBase","智能运维","AI Agent","seekdb","AgentSeek","社区月报","异步索引"],"articleSection":["最新动态"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"最新动态","item":"https://ilongda.com/categories/最新动态/"},{"@type":"ListItem","position":3,"name":"OceanBase 社区月报：AgentSeek 首发，seekdb 1.3.0 流式写入提速 22 倍","item":"https://ilongda.com/2026/2026-06-10-oceanbase-community-monthly-agentseek-seekdb/"}]}</script><blockquote><p><strong>本期速览</strong></p><ul><li><strong>seekdb 1.3.0</strong>：异步索引模型，streaming 写入吞吐相对同步模式约提升 22 倍</li><li><strong>AgentSeek</strong>：基于 OceanBase &amp; LangChain 的智能体工程套件首个版本，覆盖数据底座到应用层</li><li><strong>obd v4.4.0 &#x2F; obdiag v5.0.0</strong>：可视化部署 seekdb；Agent 诊断体验基于 LangChain &#x2F; LangGraph 增强</li><li>生态兼容认证新增 1 款产品</li></ul></blockquote><span id="more"></span><h2 id="AI-产品更新"><a href="#AI-产品更新" class="headerlink" title="AI 产品更新"></a>AI 产品更新</h2><h3 id="OceanBase-seekdb-1-3-0-发布：性能提升-22-倍，P99-无抖动"><a href="#OceanBase-seekdb-1-3-0-发布：性能提升-22-倍，P99-无抖动" class="headerlink" title="OceanBase seekdb 1.3.0 发布：性能提升 22 倍，P99 无抖动"></a>OceanBase seekdb 1.3.0 发布：性能提升 22 倍，P99 无抖动</h3><p>OceanBase seekdb 正式发布了 1.3.0 版本——一次以「多平台覆盖与高性能」为主题的重大版本更新。</p><p><img src="/img/2026-06-10-oceanbase-community-monthly-agentseek-seekdb/01.webp" alt="seekdb 1.3.0 异步索引与流式写入性能提升" decoding="async"></p><p>该版本引入了基于 Change Stream 增量框架的 <strong>异步索引模型</strong> ，将写入操作与索引构建彻底解耦，为 AI Agent 负载带来极致的写入吞吐和稳定的检索性能—— <strong>streaming 场景下吞吐量相比同步模式提升约 22 倍</strong> 。同时 Diff &amp; Merge 现已支持向量列，Fork Table &#x2F; Fork Database 与异步索引全面对齐，进一步增强多版本数据管理能力。</p><p>完整更新日志见：GitHub Release v1.3.0 <sup>[1]</sup></p><h3 id="OceanBase-AgentSeek（智能体工程套件）首个版本发布"><a href="#OceanBase-AgentSeek（智能体工程套件）首个版本发布" class="headerlink" title="OceanBase AgentSeek（智能体工程套件）首个版本发布"></a>OceanBase AgentSeek（智能体工程套件）首个版本发布</h3><p><strong>OceanBase AgentSeek 是基于 OceanBase &amp; LangChain 打造的智能体工程套件</strong> ，提供一系列工具和库，帮助开发者快速构建具备数据闭环能力的智能体飞轮。</p><p><img src="/img/2026-06-10-oceanbase-community-monthly-agentseek-seekdb/02.webp" alt="AgentSeek 智能体工程套件五层架构" loading="lazy" decoding="async"></p><p>AgentSeek 完整架构图</p><p>作为智能体工程套件，AgentSeek 旨在补全以下架构（并非全自研，而是融合开源生态）：</p><ol><li><strong>数据底座</strong> ：与 OceanBase 合作，提供从端侧（seekdb）到云端的支持，兼容 MySQL 协议，方便国内用户。</li><li><strong>上下文语义层</strong> ：统一管理记忆、RAG 内容、工具调用结果等，具备自进化、可检索、证据链溯源能力。</li><li><strong>运行时层</strong> ：核心层，将本地应用转化为服务，支持 Docker、K8S 等部署方式，初步集成 Agent Protocol、MCP、A2A 等协议，旨在服务化 LangChain 生态应用。</li><li><strong>网关层</strong> ：对接钉钉、飞书、Slack、Discord 等 IM 工具，作为智能体入口。同时支持通过 AG-UI 等协议快速构建功能全面的智能体前端界面（支持 Human-in-the-loop、流式输出等）。</li><li><strong>应用层</strong> ：基于运行时层和标准协议，构建具体智能体应用。</li></ol><p>所有提及项目均已开源，欢迎试用、贡献 PR&#x2F;Issue！</p><ul><li><strong>AgentSeek</strong><sup><strong>[2]</strong></sup></li><li><strong>AgentSeek-api</strong><sup><strong>[3]</strong></sup></li><li><strong>ContextSeek</strong><sup><strong>[4]</strong></sup></li><li><strong>langchain-oceanbase</strong><sup><strong>[5]</strong></sup></li><li><strong>OceanBase seekdb</strong><sup><strong>[6]</strong></sup></li></ul><h2 id="工具侧重要更新"><a href="#工具侧重要更新" class="headerlink" title="工具侧重要更新"></a>工具侧重要更新</h2><h3 id="obd-v4-4-0：安装部署工具新增支持可视化部署-seekdb"><a href="#obd-v4-4-0：安装部署工具新增支持可视化部署-seekdb" class="headerlink" title="obd v4.4.0：安装部署工具新增支持可视化部署 seekdb"></a>obd v4.4.0：安装部署工具新增支持可视化部署 seekdb</h3><p>主要新增功能如下：</p><ul><li>支持 <strong>可视化部署 seekdb</strong> 。</li><li>支持为 seekdb 部署监控组件 obagent&#x2F;prometheus&#x2F;ob-dashboard。</li><li>支持 obshell https 协议。</li><li>新增 <code>obd cluster tenant set-sync-mode</code> 命令，支持设置主备租户同步模式（最大性能&#x2F;最大可用&#x2F;最大保护）。</li><li>新增 <code>--sync-mode</code> 、 <code>--net-timeout</code> 、 <code>--health-check-time</code> 参数，支持在创建时指定同步模式和网络超时配置。</li><li>新增 <strong>switchover</strong> （计划内切换）和 <strong>failover</strong> （故障切换）相关插件，支持主备租户角色切换操作。</li></ul><h3 id="obdiag-7-v5-0-0：obdiag-agent-支持更丰富的交互体验"><a href="#obdiag-7-v5-0-0：obdiag-agent-支持更丰富的交互体验" class="headerlink" title="obdiag[7] v5.0.0：obdiag agent 支持更丰富的交互体验"></a>obdiag[7] v5.0.0：obdiag agent 支持更丰富的交互体验</h3><p>自 obdiag <strong>V5.0.0</strong> 起，Agent 底层迁移至基于 <strong>LangChain&#x2F;LangGraph</strong> 的 <strong>deepagents TUI</strong> ，支持更丰富的交互体验（如 Textual 终端 UI、技能管理、子 Agent 等）。Agent 支持自然语言描述诊断需求，并调用 obdiag 的采集、分析、巡检、根因分析等能力。</p><h2 id="生态产品认证进展：新增-1-款兼容产品"><a href="#生态产品认证进展：新增-1-款兼容产品" class="headerlink" title="生态产品认证进展：新增 1 款兼容产品"></a>生态产品认证进展：新增 1 款兼容产品</h2><p>5 月新增 1 款生态兼容认证产品，详情如下：</p><table><thead><tr><th>伙伴名称</th><th>产品名称</th><th>产品版本</th><th>OB 版本</th><th>证书编号</th></tr></thead><tbody><tr><td>国投人力资源服务有限公司</td><td>国聘网校数智化培训平台</td><td>V2.0</td><td>V4</td><td>OB2026050001B</td></tr></tbody></table><h2 id="社区动态"><a href="#社区动态" class="headerlink" title="社区动态"></a>社区动态</h2><p>5 月 30 日，由 OceanBase 与 LangChain Community 联合主办的「 <strong>构建高可靠、低成本企业级 Agent Infra</strong> 」线下技术沙龙，在上海张江科学之门圆满落幕。活动汇聚数据库、大模型、Agent 开发领域一线技术从业者、企业技术负责人与开源社区开发者，围绕以下四大核心内容深度交流：</p><ul><li>Agent 原生数据底座建设</li><li>AgentSeek 平台落地</li><li>真实产业案例拆解</li><li>现场实操演示</li></ul><p>活动完成自研企业级智能体工程平台 <strong>AgentSeek 重磅首发</strong> ，为上海本地 AI 开发者带来一场聚焦落地、干货密集的技术分享会。</p><p>查看活动回顾： <a href="https://mp.weixin.qq.com/s?__biz=Mzk3NTE2NzU5NQ==&mid=2247491420&idx=1&sn=7586b385bc5a5b7e1a4f09ec9e9de7ed&scene=21#wechat_redirect">上海 Meetup 干货全集：信也降本、算秩未来混合检索，AgentSeek 智能体工程一站通关</a></p><p>6 月，社区将围绕 AgentSeek 陆续开展线上直播活动，介绍关于上下文进化、Agent 构建、AI 基础设施与 AgentOps 等方面的思路和选择。欢迎大家关注 6 月线上活动： <a href="https://mp.weixin.qq.com/s?__biz=Mzk3NTE2NzU5NQ==&mid=2247491380&idx=1&sn=cc6b7e69dadc8260bfee59cf1e167659&scene=21#wechat_redirect">Agent 自进化的另一条路——让上下文成为活的数据资产</a> ~</p><p>Agent自进化：上下文变资产</p><blockquote><p>我们每个月都会和大家展开一次社区进展的汇报沟通会，希望通过更多的互动交流让 OceanBase 开源社区更加透明，实现信息共享，也希望能营造更加轻松的氛围，为大家答疑解惑，让大家畅所欲言。</p><p>如果您对我们的社区有任何建议，欢迎在 OceanBase GitHub <sup>[8]</sup> 上提 Issues 或 PR，也欢迎大家成为 Contributor，参与到社区建设中来~</p></blockquote><p>参考资料</p><p>[1]</p><p>GitHub Release v1.3.0: <a href="https://github.com/oceanbase/seekdb/releases/tag/v1.3.0">https://github.com/oceanbase/seekdb/releases/tag/v1.3.0</a></p><p>[2]</p><p>AgentSeek: <a href="https://github.com/ob-labs/agentseek">https://github.com/ob-labs/agentseek</a></p><p>[3]</p><p>AgentSeek-api: <a href="https://github.com/ob-labs/agentseek-api">https://github.com/ob-labs/agentseek-api</a></p><p>[4]</p><p>ContextSeek: <a href="https://github.com/ob-labs/contextseek">https://github.com/ob-labs/contextseek</a></p><p>[5]</p><p>langchain-oceanbase: <a href="https://github.com/oceanbase/langchain-oceanbase">https://github.com/oceanbase/langchain-oceanbase</a></p><p>[6]</p><p>OceanBase seekdb: <a href="https://github.com/oceanbase/seekdb">https://github.com/oceanbase/seekdb</a></p><p>[7]</p><p>obdiag: <a href="https://github.com/oceanbase/obdiag">https://github.com/oceanbase/obdiag</a></p><p>[8]</p><p>OceanBase GitHub: <a href="https://github.com/oceanbase/oceanbase">https://github.com/oceanbase/oceanbase</a></p><p>社区月报 · 目录</p><p>作者提示: 个人观点，仅供参考</p><p>阅读原文</p>]]>
    </content>
    <id>https://ilongda.com/2026/2026-06-10-oceanbase-community-monthly-agentseek-seekdb/</id>
    <link href="https://ilongda.com/2026/2026-06-10-oceanbase-community-monthly-agentseek-seekdb/"/>
    <published>2026-06-10T14:34:16.000Z</published>
    <summary>OceanBase 社区月报：seekdb 1.3.0 异步索引与流式写入提速约 22 倍，AgentSeek 智能体工程套件首发，obd / obdiag 与生态认证同步更新。</summary>
    <title>OceanBase 社区月报：AgentSeek 首发，seekdb 1.3.0 流式写入提速 22 倍</title>
    <updated>2026-06-10T14:34:16.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="产品详解" scheme="https://ilongda.com/categories/%E4%BA%A7%E5%93%81%E8%AF%A6%E8%A7%A3/"/>
    <category term="向量数据库" scheme="https://ilongda.com/tags/%E5%90%91%E9%87%8F%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    <category term="HNSW" scheme="https://ilongda.com/tags/HNSW/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="AI Agent" scheme="https://ilongda.com/tags/AI-Agent/"/>
    <category term="混合检索" scheme="https://ilongda.com/tags/%E6%B7%B7%E5%90%88%E6%A3%80%E7%B4%A2/"/>
    <category term="seekdb" scheme="https://ilongda.com/tags/seekdb/"/>
    <category term="版本发布" scheme="https://ilongda.com/tags/%E7%89%88%E6%9C%AC%E5%8F%91%E5%B8%83/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"OceanBase seekdb 1.3.0 发布：性能提升 22 倍，P99 无抖动","description":"OceanBase seekdb 1.3.0 发布，引入基于 Change Stream 的异步索引模型，将写入与索引构建解耦，streaming 场景吞吐提升约 22 倍、并发 P99 几乎无抖动，并带来 Fork/Diff & Merge 向量列等能力。","image":"https://ilongda.com/img/seekdb-1-3-0-release/01.png","wordCount":1822,"datePublished":"2026-06-09T13:06:21.000Z","dateModified":"2026-06-09T13:06:21.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-06-09-seekdb-1-3-0-release/"},"url":"https://ilongda.com/2026/2026-06-09-seekdb-1-3-0-release/","inLanguage":"zh-CN","keywords":["向量数据库","HNSW","OceanBase","AI Agent","混合检索","seekdb","版本发布"],"articleSection":["产品详解"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"产品详解","item":"https://ilongda.com/categories/产品详解/"},{"@type":"ListItem","position":3,"name":"OceanBase seekdb 1.3.0 发布：性能提升 22 倍，P99 无抖动","item":"https://ilongda.com/2026/2026-06-09-seekdb-1-3-0-release/"}]}</script><blockquote><p>🚀 想亲自体验这 22 倍的性能飞跃吗？seekdb 已在 GitHub 开源，欢迎来 <a href="https://github.com/oceanbase/seekdb">https://github.com/oceanbase/seekdb</a> 试玩！异步索引、Fork Table 等新鲜特性都已就位，就等你来探索～</p></blockquote><p>OceanBase seekdb 1.3.0 版本：一次以”多平台覆盖与高性能”为主题的重大版本更新。</p><ul><li>引入了基于 Change Stream 增量框架的异步索引模型，将写入操作与索引构建彻底解耦</li><li>提升了 AI Agent 负载的检索性能与写入吞吐——streaming 场景下吞吐量相比同步模式提升约 22 倍。</li><li>Diff &amp; Merge 支持向量列</li><li>Fork Table &#x2F; Fork Database 与异步索引全面对齐</li><li>多版本数据管理能力增强</li></ul><p>完整更新日志见： <a href="https://github.com/oceanbase/seekdb/releases/tag/v1.3.0">GitHub Release v1.3.0</a></p><p>本文是 OceanBase seekdb 1.3.0 的技术解读，我们从 Agent 真实负载场景切入，结合第三方测试数据，详细说明该版本在架构层面的设计取舍与解决思路。如果你正在为 Agent 选型，希望这篇文章能帮你少踩一个坑。</p><span id="more"></span><p><strong>Agent 的真实负载是 streaming workload——大多数向量数据库不是为它设计的。</strong></p><p>如果你正在为 Agent 选向量数据库，大概率参考的是 ann-benchmarks 或者各家官方发的性能对比。那些测试跑的是这样的负载：先批量导入全部数据，建好索引，再做只读查询。</p><p>这不是 Agent 的负载，Agent 的真实负载是这样的：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> step <span class="keyword">in</span> agent.run():</span><br><span class="line">    memory.write(step.observation)        <span class="comment"># 持续写入</span></span><br><span class="line">    relevant = memory.search(step.query)  <span class="comment"># 毫秒后检索</span></span><br></pre></td></tr></table></figure><p>写入和检索同时发生，间隔是毫秒级，而且是并发的。这套负载有个名字——streaming workload。</p><p>VectorDBBench 专门为此设计了 StreamingPerformanceCase：固定速率持续写入 + 并发查询，跟生产环境的 Agent 一模一样。</p><p>VectorDBBench 由 Zilliz（Milvus 背后的公司）维护，是一个第三方开源 benchmark 框架。我们用它测了 6 款主流向量数据库。</p><p><strong>一个被忽略的指标：并发下你的 P99 会涨多少？</strong></p><p>测试条件：Cohere 10M 数据集（768 维），16 vCPU &#x2F; 64 GiB，统一 HNSW 索引参数（M&#x3D;16 &#x2F; ef_construction&#x3D;256 &#x2F; ef_search&#x3D;200），持续写入 500 行&#x2F;秒。</p><p><img src="/img/seekdb-1-3-0-release/01.png" alt="六款向量数据库 streaming 负载性能对比图" decoding="async"></p><p>大多数人看 benchmark 只看 QPS 和串行延迟。但 Agent 在生产环境里不是单线程运行的。<strong>真正决定你 SLA 的是并发 P99——以及它在并发加大后涨了多少倍。</strong></p><p>看图里”P99 Jitter”那组：</p><ul><li>ES：10.3 倍——串行 P99 只有 5.2ms（比 OceanBase seekdb 快），但并发一开就涨到 53.6ms</li><li>某向量数据库 A：9.7 倍——串行 15.9ms，并发直接飙到 153.6ms</li><li>OceanBase seekdb：1.1 倍——从 19.7ms 到 21.7ms，几乎不动</li></ul><p>这不是参数调优的问题——是架构问题。下一节详细解释。</p><p>※ 完整测试脚本和配置：github.com&#x2F;oceanbase&#x2F;vdb-streambench，欢迎提 PR 补充更多产品。</p><p><strong>为什么 streaming 负载下 P99 会炸</strong></p><p>向量数据库 A、B、D 在它们擅长的场景（批量导入 + 只读查询）下表现优秀——它们本来就是为那个场景设计的。但 streaming 写入会暴露一个结构性的问题：不断产生新的 segment。查询时需要 fanout 到 N 个 segment 分别做 knn 再合并结果。单线程下勉强可控，<strong>并发一上来，N 个 segment × M 个查询线程在 CPU 上互相争抢，P99 就会飙升。</strong></p><p><strong>大多数向量数据库的索引段数量会随 streaming 写入膨胀，并发查询的争抢越来越严重。OceanBase seekdb 的索引数量是固定的（永远只有两个），所以不会。</strong></p><p>具体来说，OceanBase seekdb 1.3.0 为 streaming 负载设计了两个机制：</p><p><strong>第一，写入路径不碰索引。</strong> 事务提交后只写 redo log 就返回。一条独立的 Change Stream 管道在后台异步消费 redo log，把向量写入内存中的 delta HNSW 索引。写入和索引构建物理上完全解耦——写入不会被索引构建阻塞。</p><p><strong>第二，查询路径固定只走两个索引。</strong> OceanBase seekdb 维护一个 delta HNSW（增量层，接收新写入）和一个 snapshot HNSW（主存量层），类似 LSM-Tree 的分层思路。查询时对两个索引各做一次 knn search 再合并结果——不管写入了多少数据，索引数量不膨胀，并发查询不争抢。</p><p><strong>Agent 需要的不只是快——还需要后悔药</strong></p><p>性能讲完了。但做过 Agent 的人都知道，还有一个痛点：Agent 需要试探性地修改数据（改 memory、跑实验、可能写坏表），<strong>你需要一个安全的沙箱和回滚机制。</strong></p><p>大多数向量数据库没有这个概念。OceanBase seekdb 直接在内核实现了 Copy-on-Write：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 秒级快照，不复制数据</span></span><br><span class="line">FORK DATABASE agent_state <span class="keyword">TO</span> sandbox_42;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- Agent 在沙箱里随便折腾</span></span><br><span class="line">USE sandbox_42;</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> memory(embedding, content)</span><br><span class="line"><span class="keyword">VALUES</span>(<span class="string">&#x27;[0.1,...]&#x27;</span>, <span class="string">&#x27;new observation&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 试探成功 → merge 回主线</span></span><br><span class="line"><span class="keyword">MERGE</span> <span class="keyword">TABLE</span> sandbox_42.memory <span class="keyword">INTO</span> agent_state.memory STRATEGY THEIRS;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 试探失败 → 扔掉，主线不受影响</span></span><br><span class="line"><span class="keyword">DROP</span> DATABASE sandbox_42;</span><br></pre></td></tr></table></figure><p>这是内核级 COW，不是应用层的 snapshot&#x2F;restore。fork 秒级完成，不复制数据，每个沙箱是完整可写的数据库（表结构、向量索引、自增列全部正常）。三种冲突策略（ <code>FAIL</code> &#x2F; <code>THEIRS</code> &#x2F; <code>OURS</code> ）让你精确控制 Agent 的修改有多少可以被信任。同时支持 <code>FORK DATABASE</code> 和 <code>FORK TABLE</code> 两种粒度。</p><p><strong>一条 SQL 完成混合检索</strong></p><p>Agent 的检索通常不是纯向量相似度。你可能需要同时过滤作者、时间范围，再加上全文匹配。在 OceanBase seekdb 里，这是一条 SQL 的事：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> id, title, l2_distance(emb, <span class="string">&#x27;[0.12,0.34,...]&#x27;</span>) <span class="keyword">AS</span> dist</span><br><span class="line"><span class="keyword">FROM</span> docs</span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">MATCH</span>(content) AGAINST(<span class="string">&#x27;quarterly report&#x27;</span>)</span><br><span class="line">  <span class="keyword">AND</span> author_id <span class="operator">=</span> <span class="number">42</span></span><br><span class="line">  <span class="keyword">AND</span> created_at <span class="operator">&gt;</span> <span class="string">&#x27;2026-01-01&#x27;</span></span><br><span class="line"><span class="keyword">ORDER</span> <span class="keyword">BY</span> dist APPROXIMATE LIMIT <span class="number">10</span>;</span><br></pre></td></tr></table></figure><p>向量 + 全文 + 标量过滤在同一个执行计划里下推，不需要客户端拼装多次查询结果。完整 MySQL 协议兼容，LangChain &#x2F; LlamaIndex &#x2F; Dify &#x2F; 任何 MySQL 客户端直接对接。</p><p><strong>30 秒试一下</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install -U pyseekdb</span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> pyseekdb</span><br><span class="line">client = pyseekdb.Client(path=<span class="string">&quot;./agent_state.db&quot;</span>)</span><br><span class="line">memory = client.get_or_create_collection(name=<span class="string">&quot;episodic&quot;</span>)</span><br><span class="line"></span><br><span class="line">memory.upsert(ids=[<span class="string">&quot;1&quot;</span>, <span class="string">&quot;2&quot;</span>, <span class="string">&quot;3&quot;</span>], documents=[</span><br><span class="line">    <span class="string">&quot;user prefers dark mode&quot;</span>,</span><br><span class="line">    <span class="string">&quot;user speaks English and Chinese&quot;</span>,</span><br><span class="line">    <span class="string">&quot;user timezone is UTC+8&quot;</span>,</span><br><span class="line">])</span><br><span class="line">memory.refresh_index()</span><br><span class="line">results = memory.query(query_texts=<span class="string">&quot;ui preferences?&quot;</span>, n_results=<span class="number">1</span>)</span><br><span class="line"><span class="built_in">print</span>(results[<span class="string">&quot;documents&quot;</span>])</span><br><span class="line"></span><br><span class="line">memory.upsert(ids=[<span class="string">&quot;4&quot;</span>], documents=[<span class="string">&quot;user saw pricing page 3 times today&quot;</span>])</span><br><span class="line">memory.refresh_index()</span><br><span class="line">results = memory.query(query_texts=<span class="string">&quot;purchase intent signals&quot;</span>, n_results=<span class="number">1</span>)</span><br><span class="line"><span class="built_in">print</span>(results[<span class="string">&quot;documents&quot;</span>])</span><br></pre></td></tr></table></figure><p>无需 server，无需 schema，嵌入式模式在进程内运行。</p><p><strong>关于 OceanBase seekdb</strong></p><p>OceanBase seekdb 完全开源（Apache 2.0），由 OceanBase 团队开发。你可能已经在用 OceanBase 了——它跑在支付宝、淘宝、滴滴、小米等公司的生产环境里。</p><p>OceanBase seekdb 继承了同一套存储引擎和 SQL 执行器，专注于 Agent 场景的向量 + 关系型混合负载——开源半年已有 2,500+ GitHub star，LangChain &#x2F; LlamaIndex &#x2F; Dify &#x2F; Coze 等主流框架均已集成。</p><p>如果你正在为 Agent 选数据库——花 30 秒跑一下上面的 demo。</p><p><strong>⭐</strong> github.com&#x2F;oceanbase&#x2F;seekdb — 一个 star 让更多人发现这个项目，也让我们有动力继续投入。</p><p>遇到问题或想讨论你的 Agent 场景：GitHub Issues · GitHub Discussions</p>]]>
    </content>
    <id>https://ilongda.com/2026/2026-06-09-seekdb-1-3-0-release/</id>
    <link href="https://ilongda.com/2026/2026-06-09-seekdb-1-3-0-release/"/>
    <published>2026-06-09T13:06:21.000Z</published>
    <summary>
      <![CDATA[OceanBase seekdb 1.3.0 发布，引入基于 Change Stream 的异步索引模型，将写入与索引构建解耦，streaming 场景吞吐提升约 22 倍、并发 P99 几乎无抖动，并带来 Fork/Diff & Merge 向量列等能力。]]>
    </summary>
    <title>OceanBase seekdb 1.3.0 发布：性能提升 22 倍，P99 无抖动</title>
    <updated>2026-06-09T13:06:21.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="技术详解" scheme="https://ilongda.com/categories/%E6%8A%80%E6%9C%AF%E8%AF%A6%E8%A7%A3/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="AI Agent" scheme="https://ilongda.com/tags/AI-Agent/"/>
    <category term="PowerMem" scheme="https://ilongda.com/tags/PowerMem/"/>
    <category term="Agent 记忆" scheme="https://ilongda.com/tags/Agent-%E8%AE%B0%E5%BF%86/"/>
    <category term="记忆系统" scheme="https://ilongda.com/tags/%E8%AE%B0%E5%BF%86%E7%B3%BB%E7%BB%9F/"/>
    <category term="遗忘机制" scheme="https://ilongda.com/tags/%E9%81%97%E5%BF%98%E6%9C%BA%E5%88%B6/"/>
    <category term="艾宾浩斯遗忘曲线" scheme="https://ilongda.com/tags/%E8%89%BE%E5%AE%BE%E6%B5%A9%E6%96%AF%E9%81%97%E5%BF%98%E6%9B%B2%E7%BA%BF/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"从神经元到代码工程：PowerMem 记忆系统的遗忘设计","description":"本文从突触可塑性、记忆巩固、信息论与艾宾浩斯遗忘曲线出发，解析 PowerMem 记忆系统的遗忘机制设计：三层记忆架构、指数衰减模型与检索排序权重，阐明遗忘为何是 Agent 记忆系统的核心能力。","image":"https://ilongda.com/img/powermem-forgetting-design/01.png","wordCount":1715,"datePublished":"2026-06-08T00:45:57.000Z","dateModified":"2026-06-08T00:45:57.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-06-08-powermem-forgetting-design/"},"url":"https://ilongda.com/2026/2026-06-08-powermem-forgetting-design/","inLanguage":"zh-CN","keywords":["OceanBase","AI Agent","PowerMem","Agent 记忆","记忆系统","遗忘机制","艾宾浩斯遗忘曲线"],"articleSection":["技术详解"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"技术详解","item":"https://ilongda.com/categories/技术详解/"},{"@type":"ListItem","position":3,"name":"从神经元到代码工程：PowerMem 记忆系统的遗忘设计","item":"https://ilongda.com/2026/2026-06-08-powermem-forgetting-design/"}]}</script><blockquote><p>大自然为生物设计了记忆和遗忘系统。我们希望将其翻译成可以配置和调优的代码。</p></blockquote><blockquote><p>🧠 如果你也想让自己的 AI Agent 拥有”省token、更聪明”的记忆能力，不妨来 <a href="https://github.com/oceanbase/powermem">https://github.com/oceanbase/powermem</a> 逛逛～ PowerMem 已经帮你把遗忘的学问变成了可调参的代码，开箱即用！</p></blockquote><h2 id="为什么需要遗忘"><a href="#为什么需要遗忘" class="headerlink" title="为什么需要遗忘"></a>为什么需要遗忘</h2><p>如果 AI Agent 将所有我说过的话都记住，会是一个什么样的场景？乍一听很合理。但事实是，真正真实可靠的 memory 并不是将所有内容都记住就万事大吉。<strong>在记住的同时，遗忘是很重要的事情</strong>。在 Agent 的记忆系统中也一样，遗忘不是缺陷，而是能力。</p><p><img src="/img/powermem-forgetting-design/01.png" alt="AI Agent 记忆与遗忘能力概念配图" decoding="async"></p><p>欢迎大家关注 OceanBase 社区公众号 “老纪的技术唠嗑局”。认知科学和工程实践都有一个结论：没有遗忘的记忆系统不是更强大，而是更低效。原因很简单：</p><ol><li><strong>检索质量衰减</strong>：新旧记忆在语义空间中相互干扰，高频无关结果稀释了精准匹配。随着记忆体量增长，检索信噪比持续下降。</li><li><strong>存储成本不可控</strong>：无限累积的记忆需要无限存储，且大部分低价值信息永远不会被检索，造成资源浪费。</li></ol><p>PowerMem 对于遗忘机制有很精妙的设计，它决定了记忆何时消亡和记忆在检索时的排序权重。</p><span id="more"></span><h2 id="1-大自然的遗忘设计，从神经元到认知系统"><a href="#1-大自然的遗忘设计，从神经元到认知系统" class="headerlink" title="1. 大自然的遗忘设计，从神经元到认知系统"></a>1. 大自然的遗忘设计，从神经元到认知系统</h2><h3 id="1-1-突触可塑性"><a href="#1-1-突触可塑性" class="headerlink" title="1.1 突触可塑性"></a>1.1 突触可塑性</h3><p>在神经科学层面，记忆的物质基础是<strong>神经元之间的突触连接</strong>。</p><p><img src="/img/powermem-forgetting-design/02.png" alt="神经元之间突触连接的示意图" loading="lazy" decoding="async"></p><p>连接不是静态的，它受两种对立机制的持续调控：</p><ul><li><strong>长时程增强（LTP）</strong>：高频使用某个神经通路时，对应突触连接被强化，这是<strong>记忆</strong>的生物学基础。</li><li><strong>长时程抑制（LTD）</strong>：低频使用某个神经通路时，对应突触连接被削弱，这是<strong>遗忘</strong>的生物学基础。</li></ul><p>如果所有突触都被同等强化，神经网络将彻底失去区分<strong>信号</strong>与<strong>噪音</strong>的能力。LTD 通过选择性削弱不活跃连接，将有限的突触资源集中于活跃通路。<strong>遗忘是记忆系统获得分辨力的代价。</strong></p><h3 id="1-2-海马体到新皮层的筛选"><a href="#1-2-海马体到新皮层的筛选" class="headerlink" title="1.2 海马体到新皮层的筛选"></a>1.2 海马体到新皮层的筛选</h3><p>再进一步的机制是<strong>记忆巩固（Memory Consolidation）</strong>。新形成的记忆首先暂存在海马体中；接着在睡眠阶段，大脑通过**记忆重放（Memory Replay）**将海马体中的记忆逐步转移至新皮层进行长期存储。</p><blockquote><p>海马体类似于计算机的 RAM，容量有限、读写快速，但保持时间短。</p></blockquote><p><img src="/img/powermem-forgetting-design/03.png" alt="海马体向新皮层转移的记忆巩固过程示意图" loading="lazy" decoding="async"></p><p>但这个转移不是全量的。只有那些在清醒时被反复激活的、与已有知识建立了丰富关联的、或伴随强烈情绪体验的信息，才能获得<strong>优先转移权</strong>。孤立、单次、缺乏情绪标记的信息，则在转移过程中自然脱落。</p><blockquote><p><strong>这个机制是 PowerMem 三层记忆模型（working → short_term → long_term）的生物学蓝本。</strong></p></blockquote><h3 id="1-3-遗忘不是因为存不进去，而是取不出来"><a href="#1-3-遗忘不是因为存不进去，而是取不出来" class="headerlink" title="1.3 遗忘不是因为存不进去，而是取不出来"></a>1.3 遗忘不是因为存不进去，而是取不出来</h3><p>干扰理论揭示的核心事实是，<strong>记忆的困难不在于存不进去，而在于取不出来</strong>。且随着存储信息越来越多，记忆之间的交叉干扰呈指数级增长。遗忘机制的作用就是通过衰减低价值记忆，降低检索空间中的干扰密度。</p><h2 id="2-香农的信息论视角：遗忘是一台信息过滤器"><a href="#2-香农的信息论视角：遗忘是一台信息过滤器" class="headerlink" title="2. 香农的信息论视角：遗忘是一台信息过滤器"></a>2. 香农的信息论视角：遗忘是一台信息过滤器</h2><h3 id="2-1-信息量的数学定义"><a href="#2-1-信息量的数学定义" class="headerlink" title="2.1 信息量的数学定义"></a>2.1 信息量的数学定义</h3><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">I(x) = -log₂(p(x))</span><br></pre></td></tr></table></figure><p>一个事件的信息量与其发生概率成反比，越是罕见、出人意料的事件，携带的信息量越大。</p><h3 id="2-2-映射到记忆系统"><a href="#2-2-映射到记忆系统" class="headerlink" title="2.2 映射到记忆系统"></a>2.2 映射到记忆系统</h3><ul><li>昨天吃的什么早餐 → 每天都在发生，概率 p≈1 → 不值得长期存储</li><li>公司数据库的主密码 → 极少被问及，p 极小 → 必须持久化保留</li></ul><p>所以一套完善的遗忘机制实质上是一台<strong>信息过滤器</strong>。</p><h2 id="3-艾宾浩斯遗忘曲线"><a href="#3-艾宾浩斯遗忘曲线" class="headerlink" title="3. 艾宾浩斯遗忘曲线"></a>3. 艾宾浩斯遗忘曲线</h2><h3 id="3-1-把记忆变成可测量的数据"><a href="#3-1-把记忆变成可测量的数据" class="headerlink" title="3.1 把记忆变成可测量的数据"></a>3.1 把记忆变成可测量的数据</h3><p>1885 年艾宾浩斯以自己为被试，发明了约 2300 个无意义音节进行实验：</p><table><thead><tr><th>时间间隔</th><th>记忆保留率</th></tr></thead><tbody><tr><td>刚学完</td><td>100%</td></tr><tr><td>20 分钟</td><td>~58%</td></tr><tr><td>1 小时</td><td>~44%</td></tr><tr><td>9 小时</td><td>~36%</td></tr><tr><td>1 天</td><td>~33%</td></tr><tr><td>2 天</td><td>~28%</td></tr><tr><td>6 天</td><td>~25%</td></tr><tr><td>31 天</td><td>~21%</td></tr></tbody></table><p>两个至今未被推翻的结论：<strong>遗忘是先快后慢的指数曲线</strong>；<strong>复习可以改写曲线</strong>。</p><h3 id="3-2-现代指数衰减模型"><a href="#3-2-现代指数衰减模型" class="headerlink" title="3.2 现代指数衰减模型"></a>3.2 现代指数衰减模型</h3><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">R(t) = e^(-λt)</span><br></pre></td></tr></table></figure><p>遗忘的核心特征是，<strong>遗忘的速度与当前还保留的记忆量成正比</strong>。</p><p><img src="/img/powermem-forgetting-design/04.png" alt="艾宾浩斯遗忘曲线的指数衰减模型图" loading="lazy" decoding="async"></p><h3 id="3-4-间隔重复与理想的困难"><a href="#3-4-间隔重复与理想的困难" class="headerlink" title="3.4 间隔重复与理想的困难"></a>3.4 间隔重复与理想的困难</h3><p>艾宾浩斯还有一个发现：间隔重复可以重置遗忘曲线，而且每次重置后的衰减速度比上一次更慢。Robert Bjork 于 1994 年提出的 <strong>“理想的困难”（Desirable Difficulty）</strong> 概念精确描述了这一现象：<strong>刚好费力到足以刺激适应的提取</strong>，才是最高效的学习方式。</p><h2 id="4-PowerMem-的三层记忆架构"><a href="#4-PowerMem-的三层记忆架构" class="headerlink" title="4. PowerMem 的三层记忆架构"></a>4. PowerMem 的三层记忆架构</h2><h3 id="4-1-从生物学到代码的映射"><a href="#4-1-从生物学到代码的映射" class="headerlink" title="4.1 从生物学到代码的映射"></a>4.1 从生物学到代码的映射</h3><table><thead><tr><th>层级</th><th>生物学类比</th><th>衰减速率倍率</th><th>典型存活时间</th><th>晋升条件</th></tr></thead><tbody><tr><td><strong>working</strong>（工作记忆）</td><td>前额叶皮层</td><td>×2.0</td><td>数小时~1 天</td><td>access≥3 或 importance≥0.6</td></tr><tr><td><strong>short_term</strong>（短期记忆）</td><td>海马体</td><td>×1.5</td><td>数天~数周</td><td>access≥3 或 importance≥0.6</td></tr><tr><td><strong>long_term</strong>（长期记忆）</td><td>新皮层</td><td>×1.0</td><td>数周~数月</td><td>—（已在顶层）</td></tr></tbody></table><p>分类逻辑：importance≥0.8→long_term, ≥0.6→short_term, &lt;0.6→working。<strong>衰减倍率是核心差异化参数。</strong></p><h3 id="4-2-遗忘管理全局架构"><a href="#4-2-遗忘管理全局架构" class="headerlink" title="4.2 遗忘管理全局架构"></a>4.2 遗忘管理全局架构</h3><ul><li><strong>ImportanceEvaluator</strong>：判断信息重要性，输出 0.0~1.0 分数</li><li><strong>EbbinghausAlgorithm</strong>：衰减计算、复习调度、遗忘&#x2F;晋升&#x2F;归档决策</li><li><strong>EbbinghausIntelligencePlugin</strong>：在记忆创建、访问、搜索关键节点注入管理逻辑</li><li><strong>MemoryOptimizer</strong>：精确去重（MD5）+ 语义去重（余弦相似度）+ 记忆压缩（LLM）</li></ul><p><img src="/img/powermem-forgetting-design/05.png" alt="PowerMem 遗忘管理全局架构图" loading="lazy" decoding="async"></p><h3 id="4-3-遗忘不只是删除"><a href="#4-3-遗忘不只是删除" class="headerlink" title="4.3 遗忘不只是删除"></a>4.3 遗忘不只是删除</h3><p>搜索结果按以下公式排序：<code>final_score = relevance_score × decay_factor</code></p><p><strong>遗忘不是单纯的删除开关，而是检索质量的调节器。</strong></p><h2 id="总结：为什么需要遗忘"><a href="#总结：为什么需要遗忘" class="headerlink" title="总结：为什么需要遗忘"></a>总结：为什么需要遗忘</h2><p><strong>遗忘是排序的基础</strong>，通过衰减制造差异化。<strong>遗忘使记忆进化</strong>，频繁访问的记忆被不断巩固。<strong>遗忘是连续的，而非二元的</strong>——从 1.0 到 0.0 的连续衰减谱系，这是更符合人类记忆的工作方式。</p><p>大自然是这么设计的，PowerMem 将其翻译成了可以配置、调优、理解的代码。</p><blockquote><p>PowerMem 的 GitHub 地址：<a href="https://github.com/oceanbase/powermem">https://github.com/oceanbase/powermem</a></p></blockquote><p><em>本文基于 PowerMem v1.1.1 版本进行撰写。</em></p><p><img src="/img/powermem-forgetting-design/06.png" alt="PowerMem 开源项目宣传配图" loading="lazy" decoding="async"></p>]]>
    </content>
    <id>https://ilongda.com/2026/2026-06-08-powermem-forgetting-design/</id>
    <link href="https://ilongda.com/2026/2026-06-08-powermem-forgetting-design/"/>
    <published>2026-06-08T00:45:57.000Z</published>
    <summary>本文从突触可塑性、记忆巩固、信息论与艾宾浩斯遗忘曲线出发，解析 PowerMem 记忆系统的遗忘机制设计：三层记忆架构、指数衰减模型与检索排序权重，阐明遗忘为何是 Agent 记忆系统的核心能力。</summary>
    <title>从神经元到代码工程：PowerMem 记忆系统的遗忘设计</title>
    <updated>2026-06-08T00:45:57.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="AI &amp; 应用" scheme="https://ilongda.com/categories/AI-%E5%BA%94%E7%94%A8/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="向量检索" scheme="https://ilongda.com/tags/%E5%90%91%E9%87%8F%E6%A3%80%E7%B4%A2/"/>
    <category term="RAG" scheme="https://ilongda.com/tags/RAG/"/>
    <category term="知识库" scheme="https://ilongda.com/tags/%E7%9F%A5%E8%AF%86%E5%BA%93/"/>
    <category term="seekdb" scheme="https://ilongda.com/tags/seekdb/"/>
    <category term="文档解析" scheme="https://ilongda.com/tags/%E6%96%87%E6%A1%A3%E8%A7%A3%E6%9E%90/"/>
    <category term="PaddleOCR" scheme="https://ilongda.com/tags/PaddleOCR/"/>
    <category term="OCR" scheme="https://ilongda.com/tags/OCR/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"如何结合 PaddleOCR 与 OceanBase 实现企业资产智能化的第一公里","description":"本文来自百度飞桨星河社区的杨有志，介绍如何用 PaddleOCR-VL-1.6 将企业非结构化文档解析为 AI 可消费的 Markdown/JSON 格式，再借助 OceanBase 与 seekdb 完成入库、向量检索与混合检索，打通企业资产智能化\"解析→入库→检索\"的第一公里。","image":"https://ilongda.com/img/paddleocr-oceanbase-asset-intelligence/01.jpg","wordCount":1667,"datePublished":"2026-06-05T01:21:55.000Z","dateModified":"2026-06-05T01:21:55.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-06-05-paddleocr-oceanbase-asset-intelligence/"},"url":"https://ilongda.com/2026/2026-06-05-paddleocr-oceanbase-asset-intelligence/","inLanguage":"zh-CN","keywords":["OceanBase","向量检索","RAG","知识库","seekdb","文档解析","PaddleOCR","OCR"],"articleSection":["AI & 应用"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"AI & 应用","item":"https://ilongda.com/categories/AI-应用/"},{"@type":"ListItem","position":3,"name":"如何结合 PaddleOCR 与 OceanBase 实现企业资产智能化的第一公里","item":"https://ilongda.com/2026/2026-06-05-paddleocr-oceanbase-asset-intelligence/"}]}</script><p>作者：杨有志，百度飞桨星河社区</p><h2 id="为什么是”第一公里”不是”最后一公里”？"><a href="#为什么是”第一公里”不是”最后一公里”？" class="headerlink" title="为什么是”第一公里”不是”最后一公里”？"></a>为什么是”第一公里”不是”最后一公里”？</h2><p>你可能在阅读技术文章或了解产品时，经常看到宣传文案上写着”某 Agent 的推出，标志着企业面向 Agent 的最后一公里”。但据我观察，许多企业仍处于数字化转型过程中，其业务形态多样且持续变化，现有的智能体框架或产品未必是最终的解决方案。</p><p>与其追求看似颠覆性的”最后一公里”，我们更应该务实关注 AI 数字化转型的”第一公里”——如何将企业内大量非结构化的数据，通过 PaddleOCR 等工具进行解析，并经过入库流程，真正沉淀为企业级可用的知识资产。</p><span id="more"></span><h2 id="一、企业智能化的第一公里：文档资产化"><a href="#一、企业智能化的第一公里：文档资产化" class="headerlink" title="一、企业智能化的第一公里：文档资产化"></a>一、企业智能化的第一公里：文档资产化</h2><p>在与团队内部同事交流 AI 相关问题时，一个经典场景是：他们拥有大量 PDF、Excel、PPT 等文档，当试图将这些复杂文档直接丢给智能体时，智能体往往无法胜任。<strong>其核心问题在于，企业或个人的大量文档尚未转化为智能体可理解、可消费、可增删改查、可迭代的知识资产。</strong></p><p>PaddleOCR 在其中扮演的角色是：将原始的非结构化、复杂排版、智能体难以直接理解的数据，转换为 Agent 可消费的数据格式（如 Markdown 或 JSON）。在此基础上，我们才能进行后续加工，无论是做 Embedding、文本切分（chunking），还是进行知识抽取。</p><p><img src="/img/paddleocr-oceanbase-asset-intelligence/01.jpg" alt="PaddleOCR 将非结构化文档解析为 AI 可消费格式" decoding="async"></p><p>例如，最新发布的 PaddleOCR-VL-1.6 版本，正在把”文档解析”这件事推向新的精度高度。相比此前版本，PaddleOCR-VL-1.6 不只是一次常规升级，而是在企业级复杂文档场景中，进一步强化了 OCR 作为”AI 数据入口”的能力。</p><h3 id="全新-SOTA-精度：重新定义文档解析上限"><a href="#全新-SOTA-精度：重新定义文档解析上限" class="headerlink" title="全新 SOTA 精度：重新定义文档解析上限"></a>全新 SOTA 精度：重新定义文档解析上限</h3><p>PaddleOCR-VL-1.6 在 OmniDocBench v1.6 上取得了 96.3% 的最新 SOTA 成绩，同时在 OmniDocBench v1.5、Real5-OmniDocBench 等多个基准测试中继续刷新纪录，文本、公式、表格等核心能力全面领先开源与闭源方案。</p><p><img src="/img/paddleocr-oceanbase-asset-intelligence/02.png" alt="PaddleOCR-VL-1.6 在 OmniDocBench 基准测试中的成绩对比" loading="lazy" decoding="async"></p><p>尤其是在”表格结构识别，古籍、生僻字识别，印章、Spotting 场景，图表与复杂版面解析，描件、倾斜拍摄、低质量文档恢复”等复杂场景中，能力提升非常明显。这意味着，企业过去难以结构化处理的 PDF、扫描件、票据、历史档案等内容，现在都可以更稳定地转化为 AI 可消费的数据资产。</p><h4 id="典型应用场景"><a href="#典型应用场景" class="headerlink" title="典型应用场景"></a>典型应用场景</h4><p>PaddleOCR-VL-1.6 的意义，并不只是 benchmark 上再提升几个百分点。真正卡住企业的问题往往在于，文档仍然无法被 AI 稳定消费：复杂表格难解析、扫描件质量不稳定、古籍与生僻字识别困难、合同与票据结构混乱。而 PaddleOCR-VL-1.6 的提升，正是在解决这些”第一公里”问题。</p><p><img src="/img/paddleocr-oceanbase-asset-intelligence/03.png" alt="PaddleOCR-VL-1.6 复杂文档解析典型应用场景" loading="lazy" decoding="async"></p><p>无论是金融合同、企业报表，还是历史档案、教育试卷，这些过去高度依赖人工处理的文档，现在都能更稳定地转化为 Markdown、JSON 等 AI 可直接使用的数据格式。</p><p>PaddleOCR-VL-1.6 已经不仅仅是 OCR 模型，更像是企业 AI 数据链路中的”解析基础设施”。</p><h3 id="从办公文档到-AI-友好数据：Markdown、JSON-直接进入链路"><a href="#从办公文档到-AI-友好数据：Markdown、JSON-直接进入链路" class="headerlink" title="从办公文档到 AI 友好数据：Markdown、JSON 直接进入链路"></a>从办公文档到 AI 友好数据：Markdown、JSON 直接进入链路</h3><p>PaddleOCR-VL-1.6 并不仅仅只会”识别文字”。它更重要的能力，是将企业内部大量非结构化文档，直接转化为适用于 Agent、RAG、知识库系统的大模型友好格式。</p><p><img src="/img/paddleocr-oceanbase-asset-intelligence/04.png" alt="办公文档转化为 Markdown、JSON 等 AI 友好格式" loading="lazy" decoding="async"></p><p>你无需再进行大量有损格式转换（例如 PPT 转 PDF、截图转文本），而是可以直接对原始文档进行高质量解析。</p><h3 id="零成本迁移"><a href="#零成本迁移" class="headerlink" title="零成本迁移"></a>零成本迁移</h3><p>虽然能力大幅升级，但 PaddleOCR-VL-1.6 在工程侧几乎没有迁移成本。其模型结构与 PaddleOCR-VL-1.5 完全一致：推理链路无需重构、原有接口基本兼容、部署方式保持一致、可直接替换升级。对于企业来说，这意味着不需要重新改造整套 OCR Pipeline，就可以直接获得更高精度与更强泛化能力。</p><h2 id="二、文档资产智能化链路：从解析到入库与检索"><a href="#二、文档资产智能化链路：从解析到入库与检索" class="headerlink" title="二、文档资产智能化链路：从解析到入库与检索"></a>二、文档资产智能化链路：从解析到入库与检索</h2><p>PaddleOCR 的核心价值在于将非结构化数据转化为 Agent 可消费格式。后续通常还需对知识进行进一步处理。例如：法律公司处理案件时，可能需要将文档信息抽取成实体和关系，构建知识图谱；出版行业可能只需对书籍内容进行 Embedding 和切片处理，然后存入 OceanBase 数据库。</p><p><img src="/img/paddleocr-oceanbase-asset-intelligence/05.png" alt="文档解析到 OceanBase 入库与检索的链路图" loading="lazy" decoding="async"></p><p>在数据资产入库后，即可在 OceanBase 上利用其支持的检索接口（关键词检索、向量检索、混合检索等），并通过 Agent 定义相应的工具来提供检索服务。从技术流来看，PaddleOCR 处于知识文档解析的上游，OceanBase 则是下游的数据存储与检索层。</p><p>这条”解析→入库→检索”的链路，已经在 ClawMaster 项目（OpenClaw 的管理工具）中跑通了端到端的闭环。ClawMaster 底层接入了 PowerMem 作为知识底座，内置 <code>paddleocr-doc-parsing</code> 技能。不止于”存进去、搜出来”，这条链路还可以让知识资产持续”生长”。ClawMaster 的 LLM Wiki 功能就是一例：PaddleOCR 解析出的 Markdown 被注入 Wiki 后，LLM 会自动抽取实体、建立交叉引用、检测事实冲突。</p><h3 id="适用于个人开发者的低门槛链路"><a href="#适用于个人开发者的低门槛链路" class="headerlink" title="适用于个人开发者的低门槛链路"></a>适用于个人开发者的低门槛链路</h3><p>面向开发者的轻量级 AI 原生数据库 OceanBase seekdb，让”解析→入库→检索”这条链路的门槛进一步降低。seekdb 继承了 OceanBase 的存储引擎和 MySQL 兼容性，同时原生支持向量索引（HNSW&#x2F;IVF）、全文索引（BM25）和混合搜索——一条 SQL 即可完成多路召回与重排序。</p><p><img src="/img/paddleocr-oceanbase-asset-intelligence/06.png" alt="seekdb 向量、全文与混合检索能力配图" loading="lazy" decoding="async"></p><p>seekdb 内置了 <code>AI_EMBED</code>、<code>AI_COMPLETE</code>、<code>AI_RERANK</code> 等 AI Function，支持在 SQL 中直接调用模型做库内推理——这意味着 PaddleOCR 解析出的文档内容，从切片、Embedding 到入库检索，甚至推理问答，都可以在同一个数据库实例内闭环完成。seekdb 支持 1C2G 小规格运行，也支持嵌入式部署（原生 Python 集成）。</p><p><strong>相关链接：</strong></p><ul><li>体验 PaddleOCR 能力：aistudio.baidu.com</li><li>轻量级 AI 原生数据库 seekdb：<a href="https://github.com/oceanbase/seekdb">https://github.com/oceanbase/seekdb</a></li><li>长期记忆系统 PowerMem：<a href="https://github.com/oceanbase/powermem">https://github.com/oceanbase/powermem</a></li><li>龙虾管理大师 ClawMaster：<a href="https://github.com/openmaster-ai/clawmaster-workshop">https://github.com/openmaster-ai/clawmaster-workshop</a></li></ul>]]>
    </content>
    <id>https://ilongda.com/2026/2026-06-05-paddleocr-oceanbase-asset-intelligence/</id>
    <link href="https://ilongda.com/2026/2026-06-05-paddleocr-oceanbase-asset-intelligence/"/>
    <published>2026-06-05T01:21:55.000Z</published>
    <summary>本文来自百度飞桨星河社区的杨有志，介绍如何用 PaddleOCR-VL-1.6 将企业非结构化文档解析为 AI 可消费的 Markdown/JSON 格式，再借助 OceanBase 与 seekdb 完成入库、向量检索与混合检索，打通企业资产智能化&quot;解析→入库→检索&quot;的第一公里。</summary>
    <title>如何结合 PaddleOCR 与 OceanBase 实现企业资产智能化的第一公里</title>
    <updated>2026-06-05T01:21:55.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="最新动态" scheme="https://ilongda.com/categories/%E6%9C%80%E6%96%B0%E5%8A%A8%E6%80%81/"/>
    <category term="混合检索" scheme="https://ilongda.com/tags/%E6%B7%B7%E5%90%88%E6%A3%80%E7%B4%A2/"/>
    <category term="LangChain" scheme="https://ilongda.com/tags/LangChain/"/>
    <category term="Agent" scheme="https://ilongda.com/tags/Agent/"/>
    <category term="seekdb" scheme="https://ilongda.com/tags/seekdb/"/>
    <category term="PowerMem" scheme="https://ilongda.com/tags/PowerMem/"/>
    <category term="Meetup" scheme="https://ilongda.com/tags/Meetup/"/>
    <category term="AgentSeek" scheme="https://ilongda.com/tags/AgentSeek/"/>
    <category term="信也科技" scheme="https://ilongda.com/tags/%E4%BF%A1%E4%B9%9F%E7%A7%91%E6%8A%80/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"上海 Meetup 干货全集：信也降本、算秩未来混合检索，AgentSeek 智能体工程一站通关","description":"OceanBase 与 LangChain Community 联合主办的上海 Agent Infra 技术沙龙回顾：AgentSeek 企业级智能体工程平台首发，信也科技核心库全量升级 OceanBase 降本 70%，算秩未来基于混合检索治理 20TB 训练语料。","image":"https://ilongda.com/img/shanghai-meetup-recap/01.jpg","wordCount":1052,"datePublished":"2026-06-03T01:24:29.000Z","dateModified":"2026-06-03T01:24:29.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-06-03-shanghai-meetup-recap/"},"url":"https://ilongda.com/2026/2026-06-03-shanghai-meetup-recap/","inLanguage":"zh-CN","keywords":["混合检索","LangChain","Agent","seekdb","PowerMem","Meetup","AgentSeek","信也科技"],"articleSection":["最新动态"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"最新动态","item":"https://ilongda.com/categories/最新动态/"},{"@type":"ListItem","position":3,"name":"上海 Meetup 干货全集：信也降本、算秩未来混合检索，AgentSeek 智能体工程一站通关","item":"https://ilongda.com/2026/2026-06-03-shanghai-meetup-recap/"}]}</script><p>5 月 30 日，由 OceanBase 与 LangChain Community 联合主办的「构建高可靠、低成本企业级 Agent Infra」线下技术沙龙，在上海张江科学之门落幕。活动汇聚数据库、大模型、Agent 开发领域一线技术从业者、企业技术负责人与开源社区开发者，围绕 Agent 原生数据底座建设、真实产业案例拆解等核心内容深度交流。</p><p><img src="/img/shanghai-meetup-recap/01.jpg" alt="上海 Agent Infra 技术沙龙活动现场" decoding="async"></p><span id="more"></span><h2 id="底层基建：统一多模数据底座"><a href="#底层基建：统一多模数据底座" class="headerlink" title="底层基建：统一多模数据底座"></a>底层基建：统一多模数据底座</h2><p>OceanBase 开源负责人封仲淹率先开启首场主题分享，直指当下多数企业依托文件系统承载 Agent 记忆未来存在诸多问题：初期上手简便，但数据体量上涨后极易出现文件冗余爆炸、检索效率低迷、数据无法统一治理等难题。他预判 Agent 上下文与记忆管理终将迈向多模态、可治理、可检索、可自进化的统一数据底座发展路线。</p><p><img src="/img/shanghai-meetup-recap/02.png" alt="封仲淹分享 Agent 统一多模数据底座主题演讲" loading="lazy" decoding="async"></p><p>OceanBase 依托 PowerMem 记忆引擎 + seekdb 统一数据底座。LoCoMo、AppWorld 实测数据：问答准确率提升 65.9%、P95 时延下降 91.6%、Token 损耗缩减 96.5%；复杂任务完成通过率由 24% 提升至 39%，涨幅 62.5%，同步实现 Token 成本下降 32%、任务执行步骤精简 34.7%。</p><p><img src="/img/shanghai-meetup-recap/03.jpg" alt="PowerMem 记忆引擎与 seekdb 实测性能数据展示" loading="lazy" decoding="async"></p><h2 id="重磅新品首发：AgentSeek-企业级智能体工程平台"><a href="#重磅新品首发：AgentSeek-企业级智能体工程平台" class="headerlink" title="重磅新品首发：AgentSeek 企业级智能体工程平台"></a>重磅新品首发：AgentSeek 企业级智能体工程平台</h2><p>由 LangChain &amp; OceanBase Ambassador 张海立正式发布 AgentSeek 企业级智能体工程解决方案。他明确指出：AgentSeek 不是新的开发框架，而是面向开源社区与企业用户的智能体工程套件，核心使命是补齐 LangChain 生态在服务化、部署、上下文治理、数据底座等环节的生产级短板。</p><p><img src="/img/shanghai-meetup-recap/04.png" alt="张海立发布 AgentSeek 企业级智能体工程平台" loading="lazy" decoding="async"></p><p>张海立深度解读智能体工程核心理念：Agent 开发不是一次性编写，而是 build → ship → observe → refine → repeat 的持续迭代闭环。AgentSeek 五层全栈架构：数据底座层（OceanBase&#x2F;seekdb）、上下文语义层（ContextSeek）、运行时层（agentseek-api）、IM 网关层、应用层。四大项目全部开源上线 GitHub。</p><h2 id="金融标杆实践：信也科技（拍拍贷）全量升级至-OceanBase"><a href="#金融标杆实践：信也科技（拍拍贷）全量升级至-OceanBase" class="headerlink" title="金融标杆实践：信也科技（拍拍贷）全量升级至 OceanBase"></a>金融标杆实践：信也科技（拍拍贷）全量升级至 OceanBase</h2><p>信也科技数据库负责人夏平带来金融级核心业务数据库架构升级实战分享。选择 OceanBase 基于三大核心优势：LSM-Tree 高压缩引擎实现极致降本、原生分布式架构彻底告别分库分表、金融级 Paxos 高可用满足合规刚需。</p><p><img src="/img/shanghai-meetup-recap/05.jpg" alt="信也科技夏平分享核心库升级 OceanBase 实战" loading="lazy" decoding="async"></p><p>落地实践三大关键突破：历史冷数据存储成本直降约 70%，从 89TB 优化至 29TB；构建同城双活与备租户容灾体系，实现 RPO&#x3D;0、RTO&lt;8 秒；多租户资源利用率提升 40%、新业务部署周期缩短 90%。</p><p><img src="/img/shanghai-meetup-recap/06.png" alt="信也科技存储降本 70% 与同城双活容灾成果" loading="lazy" decoding="async"></p><h2 id="AI-混合检索升级：算秩未来统一搜索架构"><a href="#AI-混合检索升级：算秩未来统一搜索架构" class="headerlink" title="AI 混合检索升级：算秩未来统一搜索架构"></a>AI 混合检索升级：算秩未来统一搜索架构</h2><p>算秩未来数据库专家陈松以生命科学大模型训练语料合成为案例，深度拆解如何依托 OceanBase 构建标量 + 全文 + 正则 + 向量一体化检索底座。原始语料超 20TB、30 亿行数据、1.4 万+ 文件。</p><p><img src="/img/shanghai-meetup-recap/07.jpg" alt="算秩未来陈松分享 20TB 训练语料混合检索案例" loading="lazy" decoding="async"></p><p>团队基于 OceanBase 将海量非结构化 JSONL 语料转化为 9 张结构化业务表，形成三级检索体系（L1 精确查询、L2 模糊&#x2F;全文检索、L3 向量语义检索）。20TB 文件从无序散落升级为可治理、可索引、可追溯、可 AI 直接调用的数据资产。</p><p><img src="/img/shanghai-meetup-recap/08.png" alt="基于 OceanBase 的三级检索体系架构" loading="lazy" decoding="async"></p><h2 id="现场演示：一行命令部署智能体"><a href="#现场演示：一行命令部署智能体" class="headerlink" title="现场演示：一行命令部署智能体"></a>现场演示：一行命令部署智能体</h2><p>杰创智能解决方案总监申红磊、张海立分别带来个人数字助手、数据分析深度智能体两大场景实战演示。</p><p><img src="/img/shanghai-meetup-recap/09.jpg" alt="申红磊与张海立现场演示智能体实战场景" loading="lazy" decoding="async"></p><p>申红磊仅用一条命令就完成环境搭建，无需配置环境、无需处理依赖。AgentSeek 支持个人→团队→企业平滑扩展，底层统一使用数据库存储，一套架构从本地 Demo 无缝升级到企业级 OceanBase 集群。</p><p><img src="/img/shanghai-meetup-recap/10.png" alt="AgentSeek 一行命令部署智能体演示" loading="lazy" decoding="async"></p><p><img src="/img/shanghai-meetup-recap/11.jpg" alt="上海 Meetup 现场观众交流互动" loading="lazy" decoding="async"></p><p>活动全程干货密集。未来，OceanBase 将联合 LangChain 走进更多城市，持续聚焦 Agent 与数据融合、上下文工程等实战主题。</p><p><img src="/img/shanghai-meetup-recap/12.jpg" alt="上海 Meetup 活动嘉宾与观众合影留念" loading="lazy" decoding="async"></p><p>👉 活动回顾视频：<a href="https://open.oceanbase.com/activities/4923992">https://open.oceanbase.com/activities/4923992</a></p>]]>
    </content>
    <id>https://ilongda.com/2026/2026-06-03-shanghai-meetup-recap/</id>
    <link href="https://ilongda.com/2026/2026-06-03-shanghai-meetup-recap/"/>
    <published>2026-06-03T01:24:29.000Z</published>
    <summary>OceanBase 与 LangChain Community 联合主办的上海 Agent Infra 技术沙龙回顾：AgentSeek 企业级智能体工程平台首发，信也科技核心库全量升级 OceanBase 降本 70%，算秩未来基于混合检索治理 20TB 训练语料。</summary>
    <title>上海 Meetup 干货全集：信也降本、算秩未来混合检索，AgentSeek 智能体工程一站通关</title>
    <updated>2026-06-03T01:24:29.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="AI &amp; 应用" scheme="https://ilongda.com/categories/AI-%E5%BA%94%E7%94%A8/"/>
    <category term="LangChain" scheme="https://ilongda.com/tags/LangChain/"/>
    <category term="Agent" scheme="https://ilongda.com/tags/Agent/"/>
    <category term="智能体" scheme="https://ilongda.com/tags/%E6%99%BA%E8%83%BD%E4%BD%93/"/>
    <category term="seekdb" scheme="https://ilongda.com/tags/seekdb/"/>
    <category term="AgentSeek" scheme="https://ilongda.com/tags/AgentSeek/"/>
    <category term="智能体工程" scheme="https://ilongda.com/tags/%E6%99%BA%E8%83%BD%E4%BD%93%E5%B7%A5%E7%A8%8B/"/>
    <category term="数据闭环" scheme="https://ilongda.com/tags/%E6%95%B0%E6%8D%AE%E9%97%AD%E7%8E%AF/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"基于OceanBase&LangChain打造智能体系统解决方案，让Agent快速上生产","description":"LangChain&OceanBase社区大使沧海九粟在上海Meetup发布AgentSeek——基于OceanBase与LangChain的智能体工程套件，涵盖数据底座、上下文语义层、运行时等五层架构，帮助开发者快速构建数据闭环、让Agent上生产。","image":"https://ilongda.com/img/oceanbase-langchain-agent-solution/01.png","wordCount":1236,"datePublished":"2026-06-02T00:39:48.000Z","dateModified":"2026-06-02T00:39:48.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-06-02-oceanbase-langchain-agent-solution/"},"url":"https://ilongda.com/2026/2026-06-02-oceanbase-langchain-agent-solution/","inLanguage":"zh-CN","keywords":["LangChain","Agent","智能体","seekdb","AgentSeek","智能体工程","数据闭环"],"articleSection":["AI & 应用"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"AI & 应用","item":"https://ilongda.com/categories/AI-应用/"},{"@type":"ListItem","position":3,"name":"基于OceanBase&LangChain打造智能体系统解决方案，让Agent快速上生产","item":"https://ilongda.com/2026/2026-06-02-oceanbase-langchain-agent-solution/"}]}</script><p>5月30日，OceanBase社区联合LangChain中国社区在上海举办了一场meetup。LangChain&amp;OceanBase社区大使”沧海九粟”正式发布了基于OceanBase和LangChain打造的智能体系统解决方案——AgentSeek。</p><h2 id="一、AgentSeek-是什么？不是什么？"><a href="#一、AgentSeek-是什么？不是什么？" class="headerlink" title="一、AgentSeek 是什么？不是什么？"></a>一、AgentSeek 是什么？不是什么？</h2><p>首先明确一点：<strong>AgentSeek 不是一个新框架</strong>。目前市场上已有众多优秀框架，例如 LangChain 社区推出的 LangChain、LangGraph 和 Deep Agents，能力非常全面，足以应对多数场景。OpenClaw、Hermes 等产品也从不同层面对标 LangChain 生态。</p><p>那么，AgentSeek 究竟是什么呢？它是一个**”智能体工程套件”**，提供一系列工具和库，帮助开发者快速构建具备数据闭环能力的智能体飞轮。</p><span id="more"></span><h2 id="二、什么是智能体工程？从概念到落地"><a href="#二、什么是智能体工程？从概念到落地" class="headerlink" title="二、什么是智能体工程？从概念到落地"></a>二、什么是智能体工程？从概念到落地</h2><p>“智能体工程”这一概念由 LangChain 在去年五月首届全球开发者大会上提出，虽然后来被 Andrej Karpathy 提出的”上下文工程”短暂掩盖，但在今年五月中旬的第二届大会上，LangChain 已将其落地为商业级产品和平台。LangChain 作为行业领头羊（估值约 100 亿人民币，B 轮），为何要推动智能体工程？其核心理念类比软件工程：智能体开发不仅是做出功能，更涉及研发、测试、评估、上线、监控等完整工程化活动。</p><p><strong>工程化的重点不在于开发过程本身，而在于”上线即学习的起点”</strong>。LangChain 强调尽快让智能体上线，产生生产数据，形成数据闭环。</p><h2 id="三、仅有”上线和持续学习”足够吗？"><a href="#三、仅有”上线和持续学习”足够吗？" class="headerlink" title="三、仅有”上线和持续学习”足够吗？"></a>三、仅有”上线和持续学习”足够吗？</h2><p>去年这可能足够，但如今远远不够。LangChain 团队在今年重新澄清：<strong>Agent &#x3D; Model + Harness</strong>。即模型之外的所有组件都可称为 Harness。返璞归真后，构建智能体就是模型、Harness 和一个循环。</p><p>随着认知边界扩展，Harness 需要考虑的要素越来越多。LangChain 近期文章细分为 16 个小类，可归纳为四大类：文件系统、记忆与持续化学习、上下文工程、长任务运行。</p><p>LangChain 用一年时间，将智能体工程从概念落实为平台，并在今年 5 月 13 日的第二届开发者大会上正式发布 LangSmith 平台。该平台发布了九大核心产品，分为三类：加速开发生命周期、加强基础设施监管、增强可观测性与治理。</p><p>最令人震撼的是，LangChain <strong>“悄无声息”地开发了自己的数据库</strong>。这强烈印证了与 OceanBase 这类数据库厂商合作的价值。竞争焦点已不再是概念或框架，而是智能体研发商业化必须是工程化的完整闭环，闭环的核心是数据闭环。</p><h2 id="四、开源生态的补位与-AgentSeek-的使命"><a href="#四、开源生态的补位与-AgentSeek-的使命" class="headerlink" title="四、开源生态的补位与 AgentSeek 的使命"></a>四、开源生态的补位与 AgentSeek 的使命</h2><p>因此，我们提出：<strong>“我们想做生产智能体，首先要帮助大家上生产。”</strong> 这呼应了 LangChain 的 “Shipping is how you learn”。我们与 OceanBase 开源社区合作，尝试通过开源项目进行补位，聚焦智能体工程和 Harness 的关键环节。</p><h3 id="AgentSeek-架构解析"><a href="#AgentSeek-架构解析" class="headerlink" title="AgentSeek 架构解析"></a>AgentSeek 架构解析</h3><p>作为智能体工程套件，AgentSeek 旨在补全以下五层架构（并非全自研，而是融合开源生态）：</p><ol><li><strong>数据底座</strong>：与 OceanBase 合作，提供从端侧（seekdb）到云端的支持，兼容 MySQL 协议，方便国内用户。</li><li><strong>上下文语义层</strong>：统一管理记忆、RAG 内容、工具调用结果等，具备自进化、可检索、证据链溯源能力。</li><li><strong>运行时层</strong>：核心层，将本地应用转化为服务，支持 Docker、K8S 等部署方式。</li><li><strong>网关层</strong>：对接钉钉、飞书、Slack、Discord 等 IM 工具，作为智能体入口。</li><li><strong>应用层</strong>：基于运行时层和标准协议，构建具体智能体应用。</li></ol><p><img src="/img/oceanbase-langchain-agent-solution/01.png" alt="AgentSeek 五层架构示意图" decoding="async"></p><h3 id="AgentSeek-的核心支柱"><a href="#AgentSeek-的核心支柱" class="headerlink" title="AgentSeek 的核心支柱"></a>AgentSeek 的核心支柱</h3><ol><li><strong>AgentSeek API</strong>：提供兼容 Agent Protocol 的轻量级 Server 参考实现，支持 MCP、流式输出、A2A 等。</li><li><strong>SeekContext</strong>：在记忆之上统一管理智能体上下文，支持内容分层、溯源、自进化（包括内敛和发散 Dream 系统）。</li><li><strong>OceanBase seekdb</strong>：轻量化的AI原生数据库，兼容 MySQL 的生态能力，解决了 LangChain 生态对 PostgreSQL 的强依赖问题。</li></ol><p><img src="/img/oceanbase-langchain-agent-solution/02.png" alt="AgentSeek 三大核心支柱组件示意图" loading="lazy" decoding="async"></p><p>这些工作都与 LangChain 生态原生集成，具备开箱即用的可观测性能力。</p><h2 id="五、总结与展望"><a href="#五、总结与展望" class="headerlink" title="五、总结与展望"></a>五、总结与展望</h2><p>LangSmith 是 LangChain 给企业的飞轮，AgentSeek 是给社区开发者的飞轮，希望能帮你少走一段路，剩下的路，咱们一起走。AgentSeek 目前聚焦于几个核心支柱，未来计划接入更多开源 Sandbox、Gateway，并提供开源可观测性方案。</p><p><img src="/img/oceanbase-langchain-agent-solution/03.png" alt="AgentSeek 未来规划与展望配图" loading="lazy" decoding="async"></p><p><strong>所有提及项目均已开源，欢迎试用、贡献 PR&#x2F;Issue！</strong> 同时也请大家持续关注 LangChain 生态，它仍是快速学习并将智能体系统产品化的最优路径之一。</p>]]>
    </content>
    <id>https://ilongda.com/2026/2026-06-02-oceanbase-langchain-agent-solution/</id>
    <link href="https://ilongda.com/2026/2026-06-02-oceanbase-langchain-agent-solution/"/>
    <published>2026-06-02T00:39:48.000Z</published>
    <summary>
      <![CDATA[LangChain&OceanBase社区大使沧海九粟在上海Meetup发布AgentSeek——基于OceanBase与LangChain的智能体工程套件，涵盖数据底座、上下文语义层、运行时等五层架构，帮助开发者快速构建数据闭环、让Agent上生产。]]>
    </summary>
    <title>
      <![CDATA[基于OceanBase&LangChain打造智能体系统解决方案，让Agent快速上生产]]>
    </title>
    <updated>2026-06-02T00:39:48.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="实战分享" scheme="https://ilongda.com/categories/%E5%AE%9E%E6%88%98%E5%88%86%E4%BA%AB/"/>
    <category term="向量数据库" scheme="https://ilongda.com/tags/%E5%90%91%E9%87%8F%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    <category term="HNSW" scheme="https://ilongda.com/tags/HNSW/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="向量检索" scheme="https://ilongda.com/tags/%E5%90%91%E9%87%8F%E6%A3%80%E7%B4%A2/"/>
    <category term="PoC" scheme="https://ilongda.com/tags/PoC/"/>
    <category term="性能调优" scheme="https://ilongda.com/tags/%E6%80%A7%E8%83%BD%E8%B0%83%E4%BC%98/"/>
    <category term="IVF" scheme="https://ilongda.com/tags/IVF/"/>
    <category term="资源规划" scheme="https://ilongda.com/tags/%E8%B5%84%E6%BA%90%E8%A7%84%E5%88%92/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"OceanBase 花三年时间整理出的向量数据库最佳实践","description":"两位 OceanBase 向量数据库专家总结三年 PoC 实战经验，系统讲解向量索引选型、内存与磁盘资源估算、分区设计、索引参数配置、混合查询调优、性能验证与常见性能问题排查方法。","image":"https://ilongda.com/img/vector-database-best-practices/01.jpeg","wordCount":3549,"datePublished":"2026-06-01T01:17:53.000Z","dateModified":"2026-06-01T01:17:53.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-06-01-vector-database-best-practices/"},"url":"https://ilongda.com/2026/2026-06-01-vector-database-best-practices/","inLanguage":"zh-CN","keywords":["向量数据库","HNSW","OceanBase","向量检索","PoC","性能调优","IVF","资源规划"],"articleSection":["实战分享"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"实战分享","item":"https://ilongda.com/categories/实战分享/"},{"@type":"ListItem","position":3,"name":"OceanBase 花三年时间整理出的向量数据库最佳实践","item":"https://ilongda.com/2026/2026-06-01-vector-database-best-practices/"}]}</script><h2 id="楔子"><a href="#楔子" class="headerlink" title="楔子"></a>楔子</h2><p>AI 时代，各种 AI Infra 都离不开向量数据的存储、检索。而做向量场景的 PoC，每次都要重新算一遍内存、选一遍索引、调一遍参数……</p><p>OceanBase 有两位不愿意透露姓名的大佬——序风、舸灏，在最近三年支持了无数 AI 场景的向量数据库 PoC（Proof of Concept）工作，有着究极丰富的向量数据库运维和调优经验。</p><p>这篇文章，是他们第一次把<strong>压箱底的向量数据库运维经验总结</strong>拿出来，在社区公众号为大家进行分享。文中包含了使用向量数据库时，需要考虑的方方面面。</p><p>（本文适合收藏，以备不时之需）</p><p><img src="/img/vector-database-best-practices/01.jpeg" alt="OceanBase 向量数据库三年 PoC 经验总结封面配图" decoding="async"></p><span id="more"></span><p>欢迎大家关注 OceanBase 社区公众号”老纪的技术唠嗑局”。</p><p><img src="/img/vector-database-best-practices/02.png" alt="OceanBase 社区公众号老纪的技术唠嗑局关注入口" loading="lazy" decoding="async"></p><p>本文涵盖了：向量索引选型、内存与 CPU 规划、磁盘空间估算、分区设计、索引参数配置、混合查询调优、性能验证方法与实测数据、常见性能问题排查等等。适用于向量数据库 PoC 评估、向量索引类型选择、租户资源规划和查询性能调优。</p><p>本文的前置阅读材料是 <a href="https://mp.weixin.qq.com/s?__biz=Mzk3NTE2NzU5NQ==&mid=2247484673&idx=1&sn=2ad8498590a45beb48a3411e4b622b9f&scene=21#wechat_redirect">《浅入了解向量数据库》</a>。</p><h2 id="上篇：向量构建设计实践"><a href="#上篇：向量构建设计实践" class="headerlink" title="上篇：向量构建设计实践"></a>上篇：向量构建设计实践</h2><p><strong>【选型与规划】</strong> 这一部分会讲清楚：什么场景选什么索引、内存 CPU 磁盘怎么算、表怎么建、参数怎么配。</p><h2 id="1-索引选型"><a href="#1-索引选型" class="headerlink" title="1. 索引选型"></a>1. 索引选型</h2><p><strong>开篇就给结论：选型不靠经验，靠两条数据——数据规模和内存预算。</strong></p><p>快速决策树如下：</p><p><img src="/img/vector-database-best-practices/03.png" alt="基于数据规模和内存预算的向量索引选型决策树" loading="lazy" decoding="async"></p><p>上图的决策逻辑简述：数据规模 &lt; 1000 万不分区，1000 万 ~ 5 亿和 &gt; 5 亿均做分区（单分区 1000 万）。&lt; 5 亿且内存充裕选 HNSW 或 HNSW_SQ，内存有限选 HNSW_BQ；&gt; 5 亿统一选 HNSW_BQ。内存极低时按维度选 IVF——维度 &lt; 384 选 IVF_FLAT，≥ 384 选 IVF_PQ。</p><p><strong>注意</strong>：HNSW_BQ 要求维度 ≥ 384, IVF_PQ 要求维度 ≥ 128。单分区 1000 万向量并不是强制要求，通常建议大数据量下单分区控制在 500 万～2000 万向量，单个分区的向量数不能超过 5000 万。</p><table><thead><tr><th>案例场景</th><th>推荐方案</th><th>详细章节</th></tr></thead><tbody><tr><td>384 维，亿级，geohash 过滤</td><td>HNSW_SQ 或 HNSW_BQ，按 geohash 分区</td><td>第 4 章、第 6 章</td></tr><tr><td>1024 维，十亿级，多维过滤</td><td>HNSW_BQ，skill_id 一级分区，doc_id 二级分区</td><td>第 4 章</td></tr><tr><td>768 维，千万~亿级</td><td>HNSW_SQ 或 HNSW_BQ</td><td>第 1 章</td></tr><tr><td>任意维度，十亿级，只增不删</td><td>IVF_PQ</td><td>第 1 章、第 2 章</td></tr></tbody></table><h3 id="1-1-HNSW-系列"><a href="#1-1-HNSW-系列" class="headerlink" title="1.1. HNSW 系列"></a>1.1. HNSW 系列</h3><p>HNSW 系列索引是内存索引，查询时需要<strong>长驻内存，注意它不是缓存，无法像 KV Cache 那样临时换出</strong>。在重建时会有一段时间内存中存在新旧两份索引。</p><table><thead><tr><th>类型</th><th>内存（相对 HNSW）</th><th>召回率</th><th>查询性能</th><th>适用场景</th></tr></thead><tbody><tr><td><strong>HNSW_SQ</strong></td><td>1&#x2F;4 ~ 1&#x2F;3</td><td>略低于 HNSW</td><td><strong>最高</strong></td><td>千万级首选，性能和内存的平衡点</td></tr><tr><td><strong>HNSW_BQ</strong></td><td><strong>1&#x2F;20</strong></td><td>低于 SQ，需 refine 补偿</td><td>中高</td><td>亿级以上，内存有限时的唯一选择</td></tr></tbody></table><p>如果内存成本足够，HNSW_SQ 是大多数场景下的最佳选择。HNSW_BQ 的极致量化（RapidQ）让索引本身极小，但查询时需要从磁盘捞原始向量做重排，因此磁盘性能对其性能有一定影响，TopK 越大影响越明显。</p><p><img src="/img/vector-database-best-practices/04.png" alt="HNSW 系列内存索引特性与适用场景配图" loading="lazy" decoding="async"></p><h3 id="1-2-IVF-系列"><a href="#1-2-IVF-系列" class="headerlink" title="1.2. IVF 系列"></a>1.2. IVF 系列</h3><p>IVF 索引常驻磁盘，内存占用极低，适合内存预算极度有限的场景。</p><table><thead><tr><th>类型</th><th>查询性能</th><th>构建速度</th><th>召回率</th><th>适用场景</th></tr></thead><tbody><tr><td><strong>IVF_FLAT</strong></td><td>较慢</td><td>快</td><td>高</td><td>内存紧张但维度不高（&lt;384）</td></tr><tr><td><strong>IVF_PQ</strong></td><td>比 FLAT 快</td><td>慢</td><td>略低</td><td>维度高（≥384）、内存极度紧张</td></tr></tbody></table><p><strong>如果大家要拿多种不同的向量数据库对比性能，则一定要注意区分索引类型</strong>：磁盘索引的 RT 通常比内存索引高数倍，这点各家是都一样的。<strong>不能单纯按照索引名称对比性能，而要按照实际的内存 &#x2F; 磁盘索引类型来对比。</strong></p><p><img src="/img/vector-database-best-practices/05.png" alt="IVF 磁盘索引与内存索引性能对比配图" loading="lazy" decoding="async"></p><p><strong>注意</strong>：IVF 系列索引在 OceanBase 4.6.0 版本以前都不支持堆表的分区表。IVF_PQ 使用 l2 距离时需额外缓存预计算结果，大规模场景优先用 cosine 距离。IVF 系列索引，随表创建索引后写入数据相当于暴力搜索，要在写完数据后重建 IVF 索引。</p><h2 id="2-资源规划"><a href="#2-资源规划" class="headerlink" title="2. 资源规划"></a>2. 资源规划</h2><p><strong>PoC 报方案前最怕被反问”内存够不够、机器买几台”——这一章给你一个最直观的算法。</strong></p><p><img src="/img/vector-database-best-practices/06.png" alt="向量数据库内存与 CPU 资源规划配图" loading="lazy" decoding="async"></p><h3 id="2-1-内存估算与规划"><a href="#2-1-内存估算与规划" class="headerlink" title="2.1. 内存估算与规划"></a>2.1. 内存估算与规划</h3><p>OceanBase 自带了向量索引内存估算函数 <code>dbms_vector.index_vector_memory_advisor</code>，可根据索引类型、数据规模和参数计算所需向量内存：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 1 亿条 384 维向量，单分区最多 1000 万条</span></span><br><span class="line"><span class="keyword">SELECT</span> dbms_vector.index_vector_memory_advisor(</span><br><span class="line">  <span class="string">&#x27;HNSW_BQ&#x27;</span>, <span class="number">100000000</span>, <span class="number">384</span>, <span class="string">&#x27;FLOAT32&#x27;</span>,</span><br><span class="line">  <span class="string">&#x27;M=32, TYPE=HNSW_BQ, ef_construction=400, distance=cosine, refine_type=SQ8&#x27;</span>,</span><br><span class="line">  <span class="number">10000000</span></span><br><span class="line">);</span><br></pre></td></tr></table></figure><p>参数依次是：索引类型、总数据量、维度、数据类型、索引参数、单分区最大行数。</p><p><strong>1024 维（最常见，text-embedding-3-large、bge-large 等）：</strong></p><table><thead><tr><th>数据规模</th><th>推荐索引</th><th>分区</th><th>向量内存（单副本）</th></tr></thead><tbody><tr><td>100 万</td><td>HNSW_SQ</td><td>不分区</td><td>2.7 GB</td></tr><tr><td>500 万</td><td>HNSW_SQ</td><td>不分区</td><td>14.2 GB</td></tr><tr><td>1000 万</td><td>HNSW_SQ</td><td>不分区</td><td>28.4 GB</td></tr><tr><td>3000 万</td><td>HNSW_BQ</td><td>3 分区</td><td>构建 34.4 GB，运行时 17.2 GB</td></tr><tr><td>1 亿</td><td>HNSW_BQ</td><td>10 分区</td><td>构建 74.6 GB，运行时 57.4 GB</td></tr><tr><td>10 亿</td><td>HNSW_BQ</td><td>100 分区</td><td>构建 591.2 GB，运行时 574.0 GB</td></tr><tr><td>10 亿</td><td>IVF_PQ</td><td>100 分区</td><td>构建 6.3 GB，运行时 1.9 GB</td></tr></tbody></table><p><strong>768 维（text-embedding-3-small、bge-base 等）：</strong></p><table><thead><tr><th>数据规模</th><th>推荐索引</th><th>分区</th><th>向量内存（单副本）</th></tr></thead><tbody><tr><td>1000 万</td><td>HNSW_SQ</td><td>不分区</td><td>22.6 GB</td></tr><tr><td>1 亿</td><td>HNSW_BQ</td><td>10 分区</td><td>构建 67.8 GB，运行时 53.8 GB</td></tr><tr><td>10 亿</td><td>HNSW_BQ</td><td>100 分区</td><td>构建 552.2 GB，运行时 538.2 GB</td></tr><tr><td>10 亿</td><td>IVF_PQ</td><td>100 分区</td><td>构建 4.8 GB，运行时 1.4 GB</td></tr></tbody></table><blockquote><p><strong>同样是 10 亿向量、单分区 1000 万：HNSW_BQ 构建峰值 591.2 GB，IVF_PQ 运行时 1.9 GB——内存差距约 300 倍。</strong> 这就是为什么<strong>内存预算决定了索引选型</strong>。</p></blockquote><p><img src="/img/vector-database-best-practices/07.png" alt="HNSW_BQ 与 IVF_PQ 内存占用差距对比配图" loading="lazy" decoding="async"></p><p><strong>注意</strong>：向量内存估算函数计算的是单副本下的内存用量。租户内存 &#x3D; 向量内存 ÷ <code>ob_vector_memory_limit_percentage</code>（默认 50%）。</p><h4 id="HNSW-内存详解"><a href="#HNSW-内存详解" class="headerlink" title="HNSW 内存详解"></a>HNSW 内存详解</h4><table><thead><tr><th>索引类型</th><th>构建时内存</th><th>运行时常驻</th><th>说明</th></tr></thead><tbody><tr><td>HNSW</td><td>76.3 GB</td><td>76.3 GB</td><td>全量常驻，不释放</td></tr><tr><td>HNSW_SQ</td><td>22.6 GB</td><td>22.6 GB</td><td>量化后常驻，约 HNSW 的 1&#x2F;3</td></tr><tr><td>HNSW_BQ</td><td>22.6 GB</td><td>5.4 GB</td><td>构建时需要 SQ 缓存，完成后只剩 BQ 索引</td></tr></tbody></table><h4 id="IVF-内存详解"><a href="#IVF-内存详解" class="headerlink" title="IVF 内存详解"></a>IVF 内存详解</h4><table><thead><tr><th>索引类型</th><th>索引参数</th><th>构建时内存</th><th>运行时常驻</th></tr></thead><tbody><tr><td>IVF_FLAT</td><td>nlist&#x3D;3000</td><td>3.4 GB</td><td>13.2 MB</td></tr><tr><td>IVF_PQ (cosine)</td><td>nlist&#x3D;3000, m&#x3D;384</td><td>3.4 GB</td><td>14.3 MB</td></tr><tr><td>IVF_PQ (l2)</td><td>nlist&#x3D;3000, m&#x3D;384</td><td>5.0 GB</td><td><strong>1.7 GB</strong></td></tr></tbody></table><p>l2 距离下 IVF_PQ 的常驻内存是 cosine 的 120 倍——因为 l2 要额外缓存预计算结果。</p><h3 id="2-2-CPU-与-NUMA-对向量查询的影响"><a href="#2-2-CPU-与-NUMA-对向量查询的影响" class="headerlink" title="2.2. CPU 与 NUMA 对向量查询的影响"></a>2.2. CPU 与 NUMA 对向量查询的影响</h3><p>相比普通 SQL 查询，向量搜索的瓶颈主要在<strong>内存带宽</strong>，以及 CPU 支持的 SIMD 指令集。核数不是越多越好：特别是 64 核以后，每核分到的内存带宽减少、L3 cache 抢得厉害。<strong>核数不是越多越好。向量搜索的瓶颈是内存带宽和 SIMD 指令，超过 64 核之后，跨 NUMA 访问和 L3 cache 争抢会让性能不升反降。</strong></p><h3 id="2-3-磁盘空间与查询性能"><a href="#2-3-磁盘空间与查询性能" class="headerlink" title="2.3. 磁盘空间与查询性能"></a>2.3. 磁盘空间与查询性能</h3><table><thead><tr><th>索引类型</th><th>磁盘估算</th></tr></thead><tbody><tr><td>HNSW</td><td>约等于原始向量大小 × 1.2</td></tr><tr><td>HNSW_SQ</td><td>约等于原始向量大小 × 1.2 &#x2F; 3</td></tr><tr><td>HNSW_BQ</td><td>约等于原始向量大小 × 1.2 &#x2F; 20</td></tr><tr><td>IVF_FLAT</td><td>约等于原始向量大小</td></tr><tr><td>IVF_PQ</td><td>约等于原始向量大小 &#x2F; 8</td></tr></tbody></table><p>原始向量大小计算公式：<code>行数 × 维度 × 4 字节</code>，例如 1 亿 384 维 float32 &#x3D; 144 GB。</p><p>总的说，几种索引算法受磁盘性能影响的程度：HNSW_SQ &lt; HNSW_BQ &lt; IVF&#x2F;IVF_PQ。</p><h2 id="3-重要配置项说明"><a href="#3-重要配置项说明" class="headerlink" title="3. 重要配置项说明"></a>3. 重要配置项说明</h2><p><strong>3 个参数，调与不调差距可能是 QPS 翻倍。</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 1. 并行构建采样精度（千万级 5000，亿级 10000，十亿级以上 100000）</span></span><br><span class="line"><span class="keyword">ALTER</span> <span class="keyword">SYSTEM</span> <span class="keyword">SET</span> _px_object_sampling <span class="operator">=</span> <span class="number">10000</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 2. 向量索引内存占比（默认自适应 50%，内存不够可手动调高到 60%）</span></span><br><span class="line"><span class="keyword">ALTER</span> <span class="keyword">SYSTEM</span> <span class="keyword">SET</span> ob_vector_memory_limit_percentage <span class="operator">=</span> <span class="number">50</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 3. 查询策略（4.6.0 起默认 LATENCY_FIRST，老版本默认 RECALL_FIRST）</span></span><br><span class="line"><span class="keyword">ALTER</span> <span class="keyword">SYSTEM</span> <span class="keyword">SET</span> ob_vector_search_strategy <span class="operator">=</span> <span class="string">&#x27;LATENCY_FIRST&#x27;</span>;</span><br></pre></td></tr></table></figure><h2 id="4-表结构与分区设计"><a href="#4-表结构与分区设计" class="headerlink" title="4. 表结构与分区设计"></a>4. 表结构与分区设计</h2><p>同时满足以下两条，建议分区：数据量千万级以上、查询条件里有明确的标量列能用来裁剪分区。<strong>目标单分区：500 万 ~ 2000 万行。结论：在满足 500-2000 万的前提下，分区越少越好。</strong></p><table><thead><tr><th>总数据量</th><th>分区数</th><th>单分区量</th></tr></thead><tbody><tr><td>5000 万</td><td>5-10</td><td>500-1000 万</td></tr><tr><td>1 亿</td><td>10-20</td><td>500-1000 万</td></tr><tr><td>4.5 亿</td><td>25-45</td><td>1000-1800 万</td></tr><tr><td>10 亿</td><td>50-100</td><td>1000-2000 万</td></tr></tbody></table><p>二级分区（两个维度过滤，如 skill_id + doc_id）：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> iop_knowledge (</span><br><span class="line">  _id <span class="type">varchar</span>(<span class="number">200</span>), doc_id <span class="type">varchar</span>(<span class="number">100</span>), skill_id <span class="type">varchar</span>(<span class="number">100</span>),</span><br><span class="line">  search_vec vector(<span class="number">1024</span>),</span><br><span class="line">  <span class="keyword">UNIQUE</span> KEY idx_id (_id, skill_id, doc_id) <span class="keyword">LOCAL</span></span><br><span class="line">) ORGANIZATION HEAP <span class="keyword">partition</span> <span class="keyword">by</span> key(skill_id) partitions <span class="number">30</span></span><br><span class="line">subpartition <span class="keyword">by</span> key(doc_id) subpartitions <span class="number">4</span>;</span><br></pre></td></tr></table></figure><h3 id="“稀疏”的向量列"><a href="#“稀疏”的向量列" class="headerlink" title="“稀疏”的向量列"></a>“稀疏”的向量列</h3><p>实测：主表 9 亿行，768 维列仅 2600 万行有值。大表上查 RT 21ms，拆到小表后降到 3ms 以内。<strong>9 亿行的主表查 21ms，拆出非空 2600 万行到独立小表后降到 3ms——延迟下降 7 倍。向量列稀疏时，大表分区扫描的隐藏开销远比想象高。</strong></p><h2 id="5-索引创建与参数配置"><a href="#5-索引创建与参数配置" class="headerlink" title="5. 索引创建与参数配置"></a>5. 索引创建与参数配置</h2><p>强烈建议全量数据导入后再创建索引。并行度设租户 CPU 的 2 倍。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- HNSW_BQ</span></span><br><span class="line"><span class="keyword">CREATE</span> <span class="comment">/*+ PARALLEL(64) */</span> VECTOR INDEX idx_vec <span class="keyword">ON</span> htl_image_recall(picturevector)</span><br><span class="line"><span class="keyword">WITH</span> (distance<span class="operator">=</span>cosine, type<span class="operator">=</span>hnsw_bq, m<span class="operator">=</span><span class="number">32</span>, ef_construction<span class="operator">=</span><span class="number">400</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- HNSW_SQ</span></span><br><span class="line"><span class="keyword">CREATE</span> <span class="comment">/*+ PARALLEL(64) */</span> VECTOR INDEX idx_vec <span class="keyword">ON</span> htl_image_recall(picturevector)</span><br><span class="line"><span class="keyword">WITH</span> (distance<span class="operator">=</span>cosine, type<span class="operator">=</span>hnsw_sq, m<span class="operator">=</span><span class="number">32</span>, ef_construction<span class="operator">=</span><span class="number">400</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- IVF_PQ</span></span><br><span class="line"><span class="keyword">CREATE</span> <span class="comment">/*+ PARALLEL(64) */</span> VECTOR INDEX idx_vec <span class="keyword">ON</span> htl_image_recall(picturevector)</span><br><span class="line"><span class="keyword">WITH</span> (distance<span class="operator">=</span>cosine, type<span class="operator">=</span>ivf_pq, lib<span class="operator">=</span>OB, m<span class="operator">=</span><span class="number">192</span>, nlist<span class="operator">=</span><span class="number">3000</span>, nbits<span class="operator">=</span><span class="number">8</span>,</span><br><span class="line">      sample_per_nlist<span class="operator">=</span><span class="number">256</span>) BLOCK_SIZE<span class="operator">=</span><span class="number">1048576</span>;</span><br></pre></td></tr></table></figure><h3 id="HNSW-系列参数"><a href="#HNSW-系列参数" class="headerlink" title="HNSW 系列参数"></a>HNSW 系列参数</h3><table><thead><tr><th>参数</th><th>默认值</th><th>范围</th><th>作用</th></tr></thead><tbody><tr><td>distance</td><td>必填</td><td>l2 &#x2F; cosine &#x2F; inner_product</td><td>多数 embedding 用 cosine</td></tr><tr><td>type</td><td>必填</td><td>hnsw &#x2F; hnsw_sq &#x2F; hnsw_bq</td><td>—</td></tr><tr><td>m</td><td>16</td><td>[5, 64]</td><td>每节点最大邻居数</td></tr><tr><td>ef_construction</td><td>200</td><td>[5, 1000]</td><td>构建时候选集大小</td></tr><tr><td>ef_search</td><td>64</td><td>[1, 16000]</td><td>查询时候选集大小</td></tr><tr><td>refine_k</td><td>4.0</td><td>[1.0, 1000.0]</td><td>仅 BQ，重排比例</td></tr><tr><td>refine_type</td><td>sq8</td><td>sq8 &#x2F; fp32</td><td>仅 BQ</td></tr></tbody></table><h3 id="按规模的参数推荐"><a href="#按规模的参数推荐" class="headerlink" title="按规模的参数推荐"></a>按规模的参数推荐</h3><p>百万级：HNSW_SQ(m&#x3D;16,ef_construction&#x3D;200,ef_search&#x3D;240)；HNSW_BQ(m&#x3D;16,ef_construction&#x3D;200,ef_search&#x3D;240,refine_k&#x3D;4)</p><p>千万级：HNSW_SQ(m&#x3D;32,ef_construction&#x3D;400,ef_search&#x3D;350)；HNSW_BQ(m&#x3D;32,ef_construction&#x3D;400,ef_search&#x3D;1000,refine_k&#x3D;10)；IVF_PQ(nlist&#x3D;3000,m&#x3D;dim&#x2F;2,nbits&#x3D;8,nprobes&#x3D;20)</p><p>亿级（分区表）：参数按<strong>单分区最大数据量</strong>来定。</p><h3 id="增量与重建"><a href="#增量与重建" class="headerlink" title="增量与重建"></a>增量与重建</h3><p>索引创建后增量写入的向量立即可查，但增量部分不做量化压缩，会额外占内存。HNSW 系列增量达 20% 时自动触发后台重建，IVF 新增超 30% 后需手动 <code>CALL dbms_vector.rebuild_index()</code>。</p><h2 id="6-查询与调优"><a href="#6-查询与调优" class="headerlink" title="6. 查询与调优"></a>6. 查询与调优</h2><p>不带标量过滤：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> id, cosine_distance(embedding, <span class="variable">@query_vector</span>) <span class="keyword">AS</span> distance</span><br><span class="line"><span class="keyword">FROM</span> htl_image_recall <span class="keyword">ORDER</span> <span class="keyword">BY</span> distance APPROXIMATE LIMIT <span class="number">100</span>;</span><br></pre></td></tr></table></figure><p><strong>APPROXIMATE 必须写</strong>（简写 APPROX 也行）。</p><p>混合查询（geohash + 向量）：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> id, picturename, cosine_distance(picturevector, <span class="variable">@query_vector</span>) <span class="keyword">AS</span> distance</span><br><span class="line"><span class="keyword">FROM</span> htl_image_recall</span><br><span class="line"><span class="keyword">WHERE</span> geohash <span class="keyword">IN</span> (<span class="string">&#x27;gcq2j&#x27;</span>, <span class="string">&#x27;u10kk&#x27;</span>, <span class="string">&#x27;wvkut&#x27;</span>)</span><br><span class="line"><span class="keyword">ORDER</span> <span class="keyword">BY</span> distance APPROXIMATE LIMIT <span class="number">100</span>;</span><br></pre></td></tr></table></figure><p><img src="/img/vector-database-best-practices/08.png" alt="geohash 标量过滤与向量混合查询示意图" loading="lazy" decoding="async"></p><h3 id="召回与延迟的权衡"><a href="#召回与延迟的权衡" class="headerlink" title="召回与延迟的权衡"></a>召回与延迟的权衡</h3><p>ef_search（HNSW 系列）和 nprobes（IVF）是核心旋钮。</p><p><strong>HNSW 系列（768 维，千万级，目标 Recall ≈ 0.95）</strong>：Top10 ef_search&#x3D;100; Top100(HNSW_SQ) ef_search&#x3D;350; Top100(HNSW_BQ) ef_search&#x3D;1000, refine_k&#x3D;10</p><p><strong>IVF 单分区（千万级）</strong>：Top10 nprobes&#x3D;1; Top100 nprobes&#x3D;20; Top1000 nprobes&#x3D;90</p><h2 id="7-性能验证"><a href="#7-性能验证" class="headerlink" title="7. 性能验证"></a>7. 性能验证</h2><p>四个核心指标：QPS、平均 RT、P95&#x2F;P99 RT、召回率。</p><p><img src="/img/vector-database-best-practices/09.png" alt="QPS、RT 与召回率性能验证指标配图" loading="lazy" decoding="async"></p><p>召回率测试：准备 100 个以上查询向量，分别跑精确搜索和近似搜索，对比结果：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 精确搜索（ground truth）</span></span><br><span class="line"><span class="keyword">SELECT</span> <span class="comment">/*+ PARALLEL(32) */</span> id, cosine_distance(picturevector, <span class="variable">@query_vector</span>) <span class="keyword">AS</span> distance</span><br><span class="line"><span class="keyword">FROM</span> htl_image_recall <span class="keyword">WHERE</span> geohash <span class="keyword">IN</span> (<span class="string">&#x27;gcq2j&#x27;</span>, <span class="string">&#x27;u10kk&#x27;</span>) <span class="keyword">ORDER</span> <span class="keyword">BY</span> distance LIMIT <span class="number">100</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 近似搜索</span></span><br><span class="line"><span class="keyword">SELECT</span> id, cosine_distance(picturevector, <span class="variable">@query_vector</span>) <span class="keyword">AS</span> distance</span><br><span class="line"><span class="keyword">FROM</span> htl_image_recall <span class="keyword">WHERE</span> geohash <span class="keyword">IN</span> (<span class="string">&#x27;gcq2j&#x27;</span>, <span class="string">&#x27;u10kk&#x27;</span>) <span class="keyword">ORDER</span> <span class="keyword">BY</span> distance APPROXIMATE LIMIT <span class="number">100</span>;</span><br></pre></td></tr></table></figure><p>压测时最好进行合并（major freeze）和预热，减小回表和读盘对查询性能的影响。</p><p><strong>实测性能参考</strong>：</p><p>百万级 768 维（m&#x3D;16, ef_construction&#x3D;200, Top100, ef_search&#x3D;240）：</p><table><thead><tr><th>索引类型</th><th>QPS</th><th>召回率</th><th>内存</th></tr></thead><tbody><tr><td>HNSW</td><td>3475</td><td>0.9499</td><td>7.3 GB</td></tr><tr><td>HNSW_SQ</td><td>5599</td><td>0.9468</td><td>2.1 GB</td></tr><tr><td>HNSW_BQ (refine_k&#x3D;4)</td><td>3113</td><td>0.9278</td><td>0.4 GB</td></tr></tbody></table><p>千万级 768 维（m&#x3D;32, ef_construction&#x3D;400, Top100）：</p><table><thead><tr><th>索引类型</th><th>QPS</th><th>召回率</th><th>ef_search</th></tr></thead><tbody><tr><td>HNSW</td><td>2637</td><td>0.9574</td><td>350</td></tr><tr><td>HNSW_BQ (refine_k&#x3D;10)</td><td>857</td><td>0.9531</td><td>1000</td></tr></tbody></table><p>4.5 亿 384 维混合查询（HNSW_SQ, m&#x3D;32, 45 分区，20 并发）：</p><table><thead><tr><th>geohash 过滤个数</th><th>QPS</th><th>平均 RT</th></tr></thead><tbody><tr><td>10</td><td>810</td><td>24ms</td></tr><tr><td>20</td><td>717</td><td>28ms</td></tr><tr><td>40</td><td>488</td><td>40ms</td></tr></tbody></table><h2 id="8-向量查询性能问题排查手册"><a href="#8-向量查询性能问题排查手册" class="headerlink" title="8. 向量查询性能问题排查手册"></a>8. 向量查询性能问题排查手册</h2><p><strong>出问题时不要乱调参数，按这张表的”现象 → 原因 → 动作”走，90% 的问题能在 10 分钟内定位。</strong></p><p><img src="/img/vector-database-best-practices/10.png" alt="向量查询性能问题排查流程配图" loading="lazy" decoding="async"></p><table><thead><tr><th>现象</th><th>最可能的原因</th><th>动作</th></tr></thead><tbody><tr><td>延迟秒级</td><td>没做分区裁剪</td><td>EXPLAIN 看 partitions 字段</td></tr><tr><td>延迟秒级</td><td>没加 APPROXIMATE</td><td>EXPLAIN 确认是否走了向量索引</td></tr><tr><td>P99 &gt;&gt; P50</td><td>部分分区索引没加载到内存</td><td>查 GV$OB_VECTOR_MEMORY</td></tr><tr><td>RT 偏高</td><td>向量列大量 NULL，大表扫描开销</td><td>拆非空行到小表，实测 RT 从 21ms 降至 3ms</td></tr><tr><td>召回低</td><td>ef_search &#x2F; nprobes 太小</td><td>逐步调大 ef_search 或 nprobes</td></tr><tr><td>混合查询慢</td><td>标量字段没索引</td><td>建标量索引</td></tr><tr><td>混合查询慢</td><td>自动策略没选对</td><td>hint 手动指定</td></tr></tbody></table><h2 id="9-内存相关"><a href="#9-内存相关" class="headerlink" title="9. 内存相关"></a>9. 内存相关</h2><p>OceanBase 4.3.5 BP3 之后可用 GV$OB_VECTOR_MEMORY 视图：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> b.zone, a.svr_ip, a.svr_port, a.tenant_id,</span><br><span class="line">  ROUND(a.vector_mem_hold<span class="operator">/</span><span class="number">1024</span><span class="operator">/</span><span class="number">1024</span><span class="operator">/</span><span class="number">1024</span>,<span class="number">2</span>) <span class="keyword">AS</span> hold_gb,</span><br><span class="line">  ROUND(a.vector_mem_used<span class="operator">/</span><span class="number">1024</span><span class="operator">/</span><span class="number">1024</span><span class="operator">/</span><span class="number">1024</span>,<span class="number">2</span>) <span class="keyword">AS</span> used_gb,</span><br><span class="line">  ROUND(a.vector_mem_limit<span class="operator">/</span><span class="number">1024</span><span class="operator">/</span><span class="number">1024</span><span class="operator">/</span><span class="number">1024</span>,<span class="number">2</span>) <span class="keyword">AS</span> limit_gb</span><br><span class="line"><span class="keyword">FROM</span> GV$OB_VECTOR_MEMORY a <span class="keyword">JOIN</span> gv$ob_units b</span><br><span class="line">  <span class="keyword">ON</span> a.tenant_id <span class="operator">=</span> b.tenant_id <span class="keyword">AND</span> a.svr_ip <span class="operator">=</span> b.svr_ip <span class="keyword">AND</span> a.svr_port <span class="operator">=</span> b.svr_port</span><br><span class="line"><span class="keyword">ORDER</span> <span class="keyword">BY</span> b.zone, used_gb <span class="keyword">DESC</span>;</span><br></pre></td></tr></table></figure><h2 id="10-向量索引创建"><a href="#10-向量索引创建" class="headerlink" title="10. 向量索引创建"></a>10. 向量索引创建</h2><p>通过 <code>__all_virtual_ddl_diagnose_info</code> 确认索引创建状态，<code>gv$session_longops</code> 查看创建中的索引。通过 <code>real_parallelism</code> 关键字确认创建向量索引的并行度。</p><p>收集 traceid 示例：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">obdiag gather <span class="built_in">log</span> --from=<span class="string">&#x27;2026-03-16 21:00:00&#x27;</span> --to=<span class="string">&#x27;2026-03-17 17:00:00&#x27;</span> --scope=all --grep=<span class="string">&#x27;YB420A80D369-000649E8EDEED23D-0-0&#x27;</span></span><br></pre></td></tr></table></figure><h2 id="写在最后"><a href="#写在最后" class="headerlink" title="写在最后"></a>写在最后</h2><p>这份指南来自多个真实 PoC 项目的经验总结。<strong>如果这份指南对你有帮助，请转发给同样需要”向量检索”的同事和朋友~</strong></p><p><img src="/img/vector-database-best-practices/11.png" alt="向量数据库最佳实践指南结尾配图" loading="lazy" decoding="async"></p><p>最后附上 PoC 经验总结前两篇文章：</p><p><img src="/img/vector-database-best-practices/12.png" alt="PoC 经验总结系列第一篇文章封面" loading="lazy" decoding="async"></p><p><img src="/img/vector-database-best-practices/13.png" alt="PoC 经验总结系列第二篇文章封面" loading="lazy" decoding="async"></p><p>添加 OB 社区小助手，进入技术交流群</p><p><img src="/img/vector-database-best-practices/14.png" alt="OB 社区小助手技术交流群入口" loading="lazy" decoding="async"></p><p><img src="/img/vector-database-best-practices/15.png" alt="生成的二维码" loading="lazy" decoding="async"></p>]]>
    </content>
    <id>https://ilongda.com/2026/2026-06-01-vector-database-best-practices/</id>
    <link href="https://ilongda.com/2026/2026-06-01-vector-database-best-practices/"/>
    <published>2026-06-01T01:17:53.000Z</published>
    <summary>两位 OceanBase 向量数据库专家总结三年 PoC 实战经验，系统讲解向量索引选型、内存与磁盘资源估算、分区设计、索引参数配置、混合查询调优、性能验证与常见性能问题排查方法。</summary>
    <title>OceanBase 花三年时间整理出的向量数据库最佳实践</title>
    <updated>2026-06-01T01:17:53.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="AI &amp; 应用" scheme="https://ilongda.com/categories/AI-%E5%BA%94%E7%94%A8/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="LangChain" scheme="https://ilongda.com/tags/LangChain/"/>
    <category term="Agent" scheme="https://ilongda.com/tags/Agent/"/>
    <category term="上下文工程" scheme="https://ilongda.com/tags/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/"/>
    <category term="Harness" scheme="https://ilongda.com/tags/Harness/"/>
    <category term="AgentSeek" scheme="https://ilongda.com/tags/AgentSeek/"/>
    <category term="数据底座" scheme="https://ilongda.com/tags/%E6%95%B0%E6%8D%AE%E5%BA%95%E5%BA%A7/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"LangChain紧急补课？基于Harness讲清All-in-one数据底座价值与实践探索","description":"本文从 Harness 的定义与分层结构出发，结合开源项目 Bub 的插件化设计与 Tape 数据闭环理念，探讨数据库原生 Harness 的技术路线，以及 OceanBase 以 All-in-one 数据底座支撑 Agent 数据内循环的探索实践。","image":"https://ilongda.com/img/langchain-harness-allinone-data-base/01.png","wordCount":2788,"datePublished":"2026-05-26T13:06:19.000Z","dateModified":"2026-05-26T13:06:19.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-05-26-langchain-harness-allinone-data-base/"},"url":"https://ilongda.com/2026/2026-05-26-langchain-harness-allinone-data-base/","inLanguage":"zh-CN","keywords":["OceanBase","LangChain","Agent","上下文工程","Harness","AgentSeek","数据底座"],"articleSection":["AI & 应用"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"AI & 应用","item":"https://ilongda.com/categories/AI-应用/"},{"@type":"ListItem","position":3,"name":"LangChain紧急补课？基于Harness讲清All-in-one数据底座价值与实践探索","item":"https://ilongda.com/2026/2026-05-26-langchain-harness-allinone-data-base/"}]}</script><p>作者：尚卓燃，ASF Member &amp; OceanBase 研发</p><p>上周，兹拉坦发表了一篇文章分析主流 Agent 框架 LangChain 公司从零构建数据库的举措，一个事实是 Agent 竞赛正从模型层悄然转向数据层。当 Agent 运行产生海量半结构化、高频写入、长生命周期的 trace 数据时，传统数据库架构难免捉襟见肘；而数据在观测平台、向量库、缓存系统之间反复搬运，更让”沉淀—提炼—反哺”的闭环效率大打折扣。</p><p>这揭示了一个关键分野：**从 Agent 框架往下做数据库，与从成熟数据库往上接 Agent 框架，起点不同，成本结构迥异。**后者意味着数据从第一行代码起即为原生公民，运行、记录、提炼、评测、反哺全部在同一底座内完成，无需跨系统搬运的损耗。**All-in-one 数据底座的价值正在于此——让 Agent 的数据闭环成为”内循环”，而非割裂的工程拼图。**本文从 Harness 的定义出发，结合开源项目 Bub 的设计实践，探讨 Agent 架构的分层理念，最终落到数据库原生 Harness 的技术路线——以及 OceanBase 在这一领域的探索实践与价值。</p><span id="more"></span><h2 id="一、理解-Agent-与-Harness-的构成及关系"><a href="#一、理解-Agent-与-Harness-的构成及关系" class="headerlink" title="一、理解 Agent 与 Harness 的构成及关系"></a>一、理解 Agent 与 Harness 的构成及关系</h2><p>Agent 的完整形态可以表述为「模型 + Harness」。Harness 涵盖模型之外的所有工程组件——类比马具之于马匹，Harness 是人驾驭模型到达目的地所需的一整套工具，包括缰绳、马鞍、路线，对应到技术层面就是反馈机制、记录系统与训练方法。</p><p>Harness 本身具有明确的分层结构。第一层由 Coding Agent 构建方或 SDK 厂商提供，包含基础工具与对外接口；第二层则由用户在业务侧扩展自己需要的组件，比如引入 RAG 系统、Memory 系统、BI 链路等业务逻辑。</p><p><img src="/img/langchain-harness-allinone-data-base/01.png" alt="Harness 分层结构示意图" decoding="async"></p><p>在 Agent 场景中，模型本身并非一个持续状态化的系统——它根据请求返回响应，而不感知具体的业务状态。真正让 Agent 能在产品和团队中稳定工作的，是 Harness 所承担的 <strong>上下文管理、工具调用、状态记录、运行轨迹追踪、效果评估以及数据流转</strong> 等一系列职责。</p><p>在此过程中，我们会逐步识别并抽象出一些关键要素，定义为 <strong>“原语（Primitive）”</strong>。例如，系统提示词（System Prompt）、技能（Skills）、任务完成方法论、多智能体间通信机制等，都是随着实践沉淀下来的重要原语。将这些原语标准化并纳入 Harness，一方面能提升业务表现、扩展能力，另一方面也使 Harness 本身逐渐产品化。</p><p>同时，**从 Harness 中采集的数据至关重要。它们既用于评估工作流效果，经过脱敏处理后也可构成标准数据集，用于训练下一代模型。**模型改进后，又会反哺 Harness 中原语的发现与优化，甚至对过往行为进行纠偏，从而形成一个持续改进的飞轮。下图（源自 LangChain 的博客）清晰地展示了这一闭环。</p><p><img src="/img/langchain-harness-allinone-data-base/02.png" alt="LangChain 博客中的数据闭环飞轮示意图" loading="lazy" decoding="async"></p><h2 id="二、构建可扩展的智能体：以-Bub-项目为例"><a href="#二、构建可扩展的智能体：以-Bub-项目为例" class="headerlink" title="二、构建可扩展的智能体：以 Bub 项目为例"></a>二、构建可扩展的智能体：以 Bub 项目为例</h2><p>Bub 是 GitHub 上的一个开源的 Python Agent 项目，其设计体现了控制 Agent 复杂度的关键思路：通过精简内核与插件化扩展实现稳定性与灵活性的平衡。</p><p>当前主流 Agent 产品如 ChatGPT、通义千问、ModelScope 服务以及 Dify、Flowise 等低代码平台，均已内置 Agent Loop。但一个核心问题是：Agent 的能力范围必须与业务场景精准匹配。尽管 Skills 和工具可以扩展能力，但为了保证任务完成的高效性，仍需针对具体场景组装工具集。</p><p>很多热门产品如 OpenClaw、Nanobot、Hermes Agent 等产品把过多功能捆绑在一起，这带来了两个问题：对用户造成功能干扰和心智负担；对开发者而言，系统复杂度高，维护困难（例如 OpenClaw 的版本升级常引发广泛功能失效）。这种高度耦合的设计在生产环境中难以直接使用。许多厂商因此选择基于特定版本二次封装，或走向完全自研。</p><p>Bub 采用了不同的架构策略：构建一个轻量内核，并通过插件机制扩展功能。也就是将额外功能分离为插件，仅维护精心设计的精简内核实现稳定的 Agent Loop，通过功能插件逐步引入业务所需能力。用户只需验证插件工作状态是否正常，如果某个插件出现问题，摘除这个问题插件即可恢复系统服务，极大提升了可维护性。</p><p><img src="/img/langchain-harness-allinone-data-base/03.png" alt="Bub 轻量内核与插件化扩展架构图" loading="lazy" decoding="async"></p><p>Bub 的核心设计哲学是不关注单个 Agent 的强大程度，而是关注单次交互中的阶段划分。无论是 Bub 内置 Agent 还是外部引入的 Codex、LangChain，均可完成工作。Bub 将交互拆分为明确阶段：对话状态构建、提示词组装、Channel 的 Input&#x2F;Output 定义等。这种阶段化拆解使流程控制成为可能，通过 Hooks 暴露各阶段接入点，而非在单个 Agent 内堆砌所有逻辑。</p><p>一个关键设计是解除 Output 的强制绑定。传统系统将消息回复严格绑定到输入 Channel，而 Bub 允许 Agent 在特定场景下「沉默」——不返回消息。这在个人助手场景看似缺陷，但在多人协作或多 Agent 协作场景中，避免噪音的沉默反而是友好特性。</p><p>当前，社区正涌现一系列方案来促进 Agent 设计的标准化与模块化，例如：</p><ul><li><strong>Agents.md</strong>：用于注入系统和任务相关的提示词。</li><li><strong>Skills</strong>：将通用 SOP（如文档写作、代码审查）沉淀为可分发资产，无需硬编码到 Agent Loop 中。</li><li><strong>MCP (Model Context Protocol)</strong>：通过插件提供各类 IM Channel 适配、定时任务、AG-UI 可视化界面等。</li></ul><p>这正是 2026 年主流 Agent 框架演进的方向。Bub 项目便是这一理念的实践，它仅用数百行代码的核心接口，便构建了一个灵活的基础设施。</p><h2 id="三、从上下文到数据闭环：Tape-概念与数据库原生的-Harness"><a href="#三、从上下文到数据闭环：Tape-概念与数据库原生的-Harness" class="headerlink" title="三、从上下文到数据闭环：Tape 概念与数据库原生的 Harness"></a>三、从上下文到数据闭环：Tape 概念与数据库原生的 Harness</h2><h3 id="1-以-Tape-为核心构建数据闭环"><a href="#1-以-Tape-为核心构建数据闭环" class="headerlink" title="1. 以 Tape 为核心构建数据闭环"></a>1. 以 Tape 为核心构建数据闭环</h3><p><strong>Tape</strong>（是 Bub 以及我们正在开发的 AgentSeek 项目的核心概念）并非简单的聊天记录。它在某种程度上与 Trace（追踪）类似，记录了单次 Agent 运行过程中的关键事实。</p><p>但与 OpenTelemetry 等可观测性体系中的 Trace 不同，Tape 的视图更简洁，虽有关联性但不过度关注细节。它的独特价值在于：</p><ul><li><strong>既是可观测性数据，也是上下文模型</strong>：Tape 承载了关键任务的可观测性，同时作为 Agent 运行时的上下文模型。这意味着 <strong>人与 AI 可以基于同一份数据视图来协作</strong>。Agent 可以通过读取自身的 Tape 进行行为复盘。</li><li><strong>赋能 Agent 自省与问题诊断</strong>：传统上，Agent 出错需工程师通过可观测性平台排查。基于 Tape，用户可直接与 Agent 对话，询问”刚才为何失败？”；工程师的排查也变为与 Agent 的自然对话，因为根因信息已内置于其上下文中。</li><li><strong>支持自动化评估与分析</strong>：基于 Tape 记录，可以由 Agent 自主对比不同模型或同一模型在不同任务下的表现，实现自动化的对照评估，而无需依赖面向人的看板。</li><li><strong>服务于模型训练</strong>：通过脱敏和格式化导出，Tape 同样可以便捷地转化为特定任务的数据集，用于模型的训练和微调，从而真正打通从上下文、可观测性到模型训练的数据闭环。</li></ul><h3 id="2-为何需要数据库原生的-Harness"><a href="#2-为何需要数据库原生的-Harness" class="headerlink" title="2. 为何需要数据库原生的 Harness"></a>2. 为何需要数据库原生的 Harness</h3><p>以 OpenClaw 为代表的 Agent 系统，其数据严重依赖文件系统（如各种 <code>.md</code> 文件）。虽然对人类和 Agent 阅读友好，但极不利于数据的加工、分析和处理。现代的上下文工程需要在原始任务轨迹之上构建一层 Memory，它既是对轨迹的摘要，也是索引。OpenClaw 社区后来出现的无损上下文插件，如 lossless-claw，开始使用 SQLite 等数据库来串联调用链和记忆，这正说明了数据库在此环节中的必要性。</p><p><strong>将数据库作为 Harness 的基石</strong>，**意味着所有 Agent 运行数据天生就是数据库中的”一等公民”。**可观测性、数据提取、归档分析都能利用数据库的原生能力，无需维护复杂异构的数据栈（如 MySQL + Elasticsearch + Redis）。这提供了一个统一的数据底座，简化了架构，降低了运维成本。</p><p>OceanBase 是这一路线的优质选项，为什么？其核心优势包括：</p><ul><li><strong>AI 工作负载就绪</strong>：OceanBase 及其衍生的工具均为 AI Agent 工作负载优化提供了向量检索、融合检索能力。SQL 能力结合向量、全文检索均为内置功能，无需额外维护多个技术栈。</li><li><strong>HTAP 能力</strong>：作为混合事务&#x2F;分析处理数据库，可直接支持对 Agent 运行数据的实时查询和复杂分析，助力数据闭环。</li><li><strong>统一存储与无缝扩展</strong>：各类数据可统一存储，支持运行轨迹分析、检索等工作负载探索。从端侧的单机部署（如 OceanBase seekdb）可无缝扩展至分布式 OceanBase 集群，为业务增长提供平滑升级路径。</li></ul><h2 id="四、AgentSeek：数据库原生-Harness-的探索"><a href="#四、AgentSeek：数据库原生-Harness-的探索" class="headerlink" title="四、AgentSeek：数据库原生 Harness 的探索"></a>四、AgentSeek：数据库原生 Harness 的探索</h2><p>魔搭社区的 Endless Context 项目是基于 Bub 和 Tape 理念构建的 OpenClaw 类智能体案例，也是数据库原生 Agent 的一个简单呈现。通过对 Agent 架构的持续探索，OceanBase 团队正在构建完全基于数据库原生能力的 Agent Harness——AgentSeek（5 月 30 日发布，文末预约现场名额）。</p><p>AgentSeek 的核心理念：让 Agent 运行时数据从第一天起成为数据库的一等公民，帮助用户构建数据闭环场景。该项目整合 OceanBase 产品能力与 AgentSeek 相关 Wrapper，目前处于积极推进阶段。</p><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>从 Harness 的分层定义，到 Bub 的插件化可扩展架构，再到 Tape 实现的可观测性与上下文一体化，最终落到数据库原生 Harness 的技术路线——Agent 基础设施的演进正从「功能堆砌」走向「数据驱动」。OceanBase 在这一领域的布局，既是技术架构的自然延伸，也是对 AI 时代数据底座需求的回应。</p><hr><p>5 月 30 日，<strong>OceanBase × LangChain Meetup，现场发布</strong> AgentSeek</p><p><img src="/img/langchain-harness-allinone-data-base/04.jpeg" alt="OceanBase × LangChain Meetup 报名海报" loading="lazy" decoding="async"></p><p>扫码预约现场名额</p>]]>
    </content>
    <id>https://ilongda.com/2026/2026-05-26-langchain-harness-allinone-data-base/</id>
    <link href="https://ilongda.com/2026/2026-05-26-langchain-harness-allinone-data-base/"/>
    <published>2026-05-26T13:06:19.000Z</published>
    <summary>本文从 Harness 的定义与分层结构出发，结合开源项目 Bub 的插件化设计与 Tape 数据闭环理念，探讨数据库原生 Harness 的技术路线，以及 OceanBase 以 All-in-one 数据底座支撑 Agent 数据内循环的探索实践。</summary>
    <title>LangChain紧急补课？基于Harness讲清All-in-one数据底座价值与实践探索</title>
    <updated>2026-05-26T13:06:19.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="技术详解" scheme="https://ilongda.com/categories/%E6%8A%80%E6%9C%AF%E8%AF%A6%E8%A7%A3/"/>
    <category term="AI Agent" scheme="https://ilongda.com/tags/AI-Agent/"/>
    <category term="LangChain" scheme="https://ilongda.com/tags/LangChain/"/>
    <category term="LLM" scheme="https://ilongda.com/tags/LLM/"/>
    <category term="上下文工程" scheme="https://ilongda.com/tags/%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B/"/>
    <category term="Claude Code" scheme="https://ilongda.com/tags/Claude-Code/"/>
    <category term="Agent Harness" scheme="https://ilongda.com/tags/Agent-Harness/"/>
    <category term="智能体架构" scheme="https://ilongda.com/tags/%E6%99%BA%E8%83%BD%E4%BD%93%E6%9E%B6%E6%9E%84/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"深度“解剖”AI Agent Harness","description":"本文译介 Akshay Pachaar 的长文《The Anatomy of an Agent Harness》，系统拆解 Anthropic、OpenAI、LangChain 的 Agent Harness 架构：编排循环、工具、记忆、上下文管理等 12 个核心组件，以及定义 Harness 的 7 个关键决策。","image":"https://ilongda.com/img/ai-agent-harness-deep-dive/01.png","wordCount":2188,"datePublished":"2026-05-25T00:58:12.000Z","dateModified":"2026-05-25T00:58:12.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-05-25-ai-agent-harness-deep-dive/"},"url":"https://ilongda.com/2026/2026-05-25-ai-agent-harness-deep-dive/","inLanguage":"zh-CN","keywords":["AI Agent","LangChain","LLM","上下文工程","Claude Code","Agent Harness","智能体架构"],"articleSection":["技术详解"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"技术详解","item":"https://ilongda.com/categories/技术详解/"},{"@type":"ListItem","position":3,"name":"深度“解剖”AI Agent Harness","item":"https://ilongda.com/2026/2026-05-25-ai-agent-harness-deep-dive/"}]}</script><p>Akshay Pachaar <em>2026年5月25日 07:00</em></p><blockquote><p>“如果你不是模型本身，那你就是 Harness”。—— Vivek Trivedy</p></blockquote><h2 id="楔子"><a href="#楔子" class="headerlink" title="楔子"></a>楔子</h2><p>在这个 OceanBase 社区公众号上，兹拉坦向来没有把一份儿外文资料翻译成中文后直接发布的习惯。因为我们希望每篇文章都是在自己阅读之后，把理解的东西提炼出来分享给大家。但今天的这篇文章，是个特例。</p><p>Akshay Pachaar 前段儿时间，在推特上发了一篇长文《The Anatomy of an Agent Harness》，系统地拆解了 Anthropic、OpenAI、LangChain 等公司的 Agent Harness 架构设计。这篇文章也是截至目前为止，兹拉坦读到过的，讲 Harness 最为清晰和全面的。而且这篇文章现在已经有 139 万的阅读量了。</p><p><img src="/img/ai-agent-harness-deep-dive/01.png" alt="Akshay Pachaar 推特长文《The Anatomy of an Agent Harness》" decoding="async"></p><p><img src="/img/ai-agent-harness-deep-dive/02.png" alt="原推文 139 万阅读量数据展示" loading="lazy" decoding="async"></p><span id="more"></span><p>也欢迎大家关注 OceanBase 社区公众号 “老纪的技术唠嗑局”。</p><h2 id="正文开始"><a href="#正文开始" class="headerlink" title="正文开始"></a>正文开始</h2><p>这篇文章聊的是 Anthropic、OpenAI 和 LangChain 他们究竟在造什么。让我们一起来看看——编排循环、工具、记忆、上下文管理，以及那些把“无状态”大语言模型变成全能智能体的底层机制。</p><p>你可能已经搭过聊天机器人，甚至用几个工具撸了一个 ReAct 循环。Demo 跑起来一切美好，但一上生产环境就原形毕露：模型转头就忘了三步前干过啥，工具调用悄无声息地挂掉，上下文窗口里塞满了没用的垃圾。</p><p>问题不在模型，在模型外面那一圈基础设施。</p><p>LangChain 用事实说了话：模型没换，参数没动，光改了外面那层架构，就在 TerminalBench 2.0 上从 30 名开外一路杀到第 5。还有一项研究让大模型自己去优化这套架构，结果通过率干到了 76.4%，比人类精心设计的系统还猛。现在，这套基础设施有了个正式名字：<strong>AI Agent Harness</strong>。</p><h2 id="什么是-Agent-Harness？"><a href="#什么是-Agent-Harness？" class="headerlink" title="什么是 Agent Harness？"></a>什么是 Agent Harness？</h2><p>Harness 这个词虽然 2026 年初才正式叫开，但背后的理念早就有了。<strong>Harness</strong> 就是套在大模型外面的那一整套软件架构：编排循环、工具、记忆、上下文管理、状态持久化、错误处理、护栏……全算。</p><p>Anthropic 在 Claude Code 文档里说得很直白：SDK 就是“驱动 Claude Code 的 Agent Harness”。OpenAI 的 Codex 团队也是一个意思。LangChain 的 Vivek Trivedy 给出的定义：<strong>“如果你不是模型本身，那你就是 Harness。”</strong> 简单粗暴。</p><p>很多人分不清这俩概念：<strong>“AI 智能体”</strong>（Agent）是你看到的那个表现；<strong>“Harness”</strong> 是幕后那台机器。<strong>当有人说“我做了一个智能体”，其实他是说“我搭了一套 Harness，然后把模型接上去了”。</strong></p><p><img src="/img/ai-agent-harness-deep-dive/03.png" alt="AI 智能体与幕后 Harness 关系图解" loading="lazy" decoding="async"></p><p>Beren Millidge 打了个特别到位的比方：裸奔的大模型就是一颗没有内存、没有硬盘、也没有输入输出的 CPU。<strong>上下文窗口</strong>是内存，<strong>外部数据库</strong>是硬盘，<strong>工具集成</strong>是设备驱动。而<strong>Harness</strong>，就是操作系统。“我们重新发明了冯·诺依曼架构”。</p><p><img src="/img/ai-agent-harness-deep-dive/04.png" alt="大模型类比冯·诺依曼架构的操作系统图解" loading="lazy" decoding="async"></p><h2 id="工程化的三个层次"><a href="#工程化的三个层次" class="headerlink" title="工程化的三个层次"></a>工程化的三个层次</h2><ul><li><strong>提示词工程</strong>：把喂给模型的指令写好。</li><li><strong>上下文工程</strong>：管好模型在什么时候能看到什么。</li><li><strong>Harness 工程</strong>：前两者全包，再加上整个应用架构——工具编排、状态持久化、错误恢复、验证循环、安全执行、生命周期管理。</li></ul><p>Harness 可不是什么提示词套壳（AI Wrapper），它是让智能体真正能自主行动的完整系统。</p><p><img src="/img/ai-agent-harness-deep-dive/05.png" alt="提示词工程、上下文工程与 Harness 工程三层次对比" loading="lazy" decoding="async"></p><h2 id="生产级-Harness-的-12-个核心组件"><a href="#生产级-Harness-的-12-个核心组件" class="headerlink" title="生产级 Harness 的 12 个核心组件"></a>生产级 Harness 的 12 个核心组件</h2><p>综合 Anthropic、OpenAI、LangChain 和一线从业者的经验，生产级 Harness 由 12 个核心组件构成。</p><p><img src="/img/ai-agent-harness-deep-dive/06.png" alt="生产级 Harness 的 12 个核心组件全景图" loading="lazy" decoding="async"></p><h3 id="1-编排循环-The-Orchestration-Loop"><a href="#1-编排循环-The-Orchestration-Loop" class="headerlink" title="1. 编排循环 (The Orchestration Loop)"></a>1. 编排循环 (The Orchestration Loop)</h3><p>“思考 - 行动 - 观察”（TAO）循环：拼提示词 → 调大模型 → 解析输出 → 执行工具调用 → 喂回结果 → 再来，直到任务完成。代码层面就是一个 <code>while</code> 循环。Anthropic 管自家运行时叫“笨循环”。</p><p><img src="/img/ai-agent-harness-deep-dive/07.png" alt="思考-行动-观察 TAO 编排循环流程图" loading="lazy" decoding="async"></p><h3 id="2-工具-Tools"><a href="#2-工具-Tools" class="headerlink" title="2. 工具 (Tools)"></a>2. 工具 (Tools)</h3><p>工具是智能体的“手”。Claude Code 提供了六大类工具：文件操作、搜索、执行、网页访问、代码分析和子智能体创建。OpenAI 的 Agents SDK 支持函数工具、托管工具以及 MCP 服务器工具。</p><h3 id="3-记忆-Memory"><a href="#3-记忆-Memory" class="headerlink" title="3. 记忆 (Memory)"></a>3. 记忆 (Memory)</h3><p><strong>短期记忆</strong>就是一次会话里的对话历史。<strong>长期记忆</strong>跨会话存在：Anthropic 用 MEMORY.md，LangGraph 用 JSON 存储，OpenAI 用 SQLite 或 Redis。Claude Code 搞了三层记忆架构。重要原则：<strong>智能体把自己的记忆当“提示”看，行动前必须拿实际状态验证</strong>。</p><h3 id="4-上下文管理-Context-Management"><a href="#4-上下文管理-Context-Management" class="headerlink" title="4. 上下文管理 (Context Management)"></a>4. 上下文管理 (Context Management)</h3><p>这是很多智能体悄悄翻车的重灾区。<strong>上下文腐烂</strong>：关键信息一旦落到窗口中间位置，模型表现就会掉 30% 以上——斯坦福管这叫“迷失在中间”。</p><p><img src="/img/ai-agent-harness-deep-dive/08.png" alt="上下文腐烂与迷失在中间问题示意图" loading="lazy" decoding="async"></p><p>生产环境应对策略：压缩（Compaction）、观察掩码（Observation Masking）、即时检索（Just-in-time Retrieval）、子智能体委托。</p><h3 id="5-提示词构建-Prompt-Construction"><a href="#5-提示词构建-Prompt-Construction" class="headerlink" title="5. 提示词构建 (Prompt Construction)"></a>5. 提示词构建 (Prompt Construction)</h3><p>分层的：系统提示词、工具定义、记忆文件、对话历史，最后是当前用户消息。</p><h3 id="6-输出解析-Output-Parsing"><a href="#6-输出解析-Output-Parsing" class="headerlink" title="6. 输出解析 (Output Parsing)"></a>6. 输出解析 (Output Parsing)</h3><p>现代 Harness 用<strong>原生工具调用</strong>：模型直接返回结构化的 <code>tool_calls</code> 对象。</p><h3 id="7-状态管理-State-Management"><a href="#7-状态管理-State-Management" class="headerlink" title="7. 状态管理 (State Management)"></a>7. 状态管理 (State Management)</h3><p>LangGraph 把状态建模成类型化字典，关键步骤自动存档。Claude Code 拿 Git 提交当存档点。</p><h3 id="8-错误处理-Error-Handling"><a href="#8-错误处理-Error-Handling" class="headerlink" title="8. 错误处理 (Error Handling)"></a>8. 错误处理 (Error Handling)</h3><p>10 个步骤，每步 99% 成功率，全流程成功率只剩 90.4%。LangGraph 分四类错误处理。</p><h3 id="9-护栏与安全-Guardrails-and-Safety"><a href="#9-护栏与安全-Guardrails-and-Safety" class="headerlink" title="9. 护栏与安全 (Guardrails and Safety)"></a>9. 护栏与安全 (Guardrails and Safety)</h3><p>OpenAI 搞三层防线。Anthropic 把“权限执行”和“模型推理”拆开——模型决定想干什么，Harness 决定让不让干。</p><p><img src="/img/ai-agent-harness-deep-dive/09.png" alt="Harness 护栏与安全多层防线架构图" loading="lazy" decoding="async"></p><h3 id="10-验证循环-Verification-Loops"><a href="#10-验证循环-Verification-Loops" class="headerlink" title="10. 验证循环 (Verification Loops)"></a>10. 验证循环 (Verification Loops)</h3><p>“能 Demo”和“能上线”的分水岭。Claude Code 创造者 Boris Cherny 说过，让模型验证自己的活儿，产出质量能翻 2~3 倍。</p><h3 id="11-子智能体编排-Subagent-Orchestration"><a href="#11-子智能体编排-Subagent-Orchestration" class="headerlink" title="11. 子智能体编排 (Subagent Orchestration)"></a>11. 子智能体编排 (Subagent Orchestration)</h3><p>Claude Code 支持三种玩法：克隆（Fork）、队友（Teammate）、工作树（Worktree）。</p><h2 id="循环运作：步进式演练"><a href="#循环运作：步进式演练" class="headerlink" title="循环运作：步进式演练"></a>循环运作：步进式演练</h2><p>零件认全了，看看它们在一次循环里是怎么配合干活的。</p><p><img src="/img/ai-agent-harness-deep-dive/10.png" alt="Harness 七步循环步进式演练流程图" loading="lazy" decoding="async"></p><p>七步循环：提示词组装 → 模型推理 → 输出分类 → 工具执行 → 结果打包 → 上下文更新 → 循环。</p><p>退出条件：模型给出无工具调用回复、达到最大轮次、Token 预算用完、护栏触发、用户中断。Anthropic 还开发了“Ralph 循环”两阶段方案用于跨窗口长任务。</p><h2 id="现实中的框架是怎么落地的"><a href="#现实中的框架是怎么落地的" class="headerlink" title="现实中的框架是怎么落地的"></a>现实中的框架是怎么落地的</h2><p><img src="/img/ai-agent-harness-deep-dive/11.png" alt="Anthropic、OpenAI、LangGraph 等框架落地对比图" loading="lazy" decoding="async"></p><ul><li><strong>Anthropic（Claude Agent SDK）</strong>：<code>query()</code> 函数暴露 Harness，运行时“笨循环”</li><li><strong>OpenAI（Agents SDK）</strong>：代码优先路线，Codex Harness 分三层</li><li><strong>LangGraph</strong>：显式状态图，两个节点加条件边</li><li><strong>CrewAI</strong>：基于角色的多智能体协作</li><li><strong>AutoGen</strong>：微软出品，五种编排模式</li></ul><h2 id="“脚手架”-The-Scaffolding-Metaphor"><a href="#“脚手架”-The-Scaffolding-Metaphor" class="headerlink" title="“脚手架” (The Scaffolding Metaphor)"></a>“脚手架” (The Scaffolding Metaphor)</h2><p><img src="/img/ai-agent-harness-deep-dive/12.png" alt="Harness 脚手架隐喻与协同进化原则配图" loading="lazy" decoding="async"></p><p><strong>协同进化原则</strong>：现在的模型在训练时，就已经把 Harness 考虑在内了。检验标准：换更强模型，性能提升而不需要增加 Harness 复杂度。</p><h2 id="定义-Harness-的-7-个关键决策"><a href="#定义-Harness-的-7-个关键决策" class="headerlink" title="定义 Harness 的 7 个关键决策"></a>定义 Harness 的 7 个关键决策</h2><p><img src="/img/ai-agent-harness-deep-dive/13.png" alt="定义 Harness 的 7 个关键决策概览图" loading="lazy" decoding="async"></p><ol><li><strong>单智能体 vs. 多智能体</strong>：先把单智能体潜力榨干</li><li><strong>ReAct vs. 先规划后执行</strong>：LLMCompiler 比顺序 ReAct 快 3.6 倍</li><li><strong>上下文管理策略</strong>：优先保留推理过程，减少 26~54% Token 消耗</li><li><strong>验证循环设计</strong>：引导（前馈）+ 传感器（反馈）</li><li><strong>权限与安全架构</strong>：宽松还是严格取决于场景</li><li><strong>工具范围管理</strong>：Vercel 砍掉 80% 工具反而更好</li><li><strong>Harness 的厚度</strong>：多少逻辑写死，多少留给模型</li></ol><h2 id="Harness-即产品"><a href="#Harness-即产品" class="headerlink" title="Harness 即产品"></a>Harness 即产品</h2><p>两个同模型智能体性能天差地别——差就差在 Harness 上。TerminalBench 证明光换 Harness 排名能蹿 20 多位。<strong>Harness 永远不会消失。即便是最强的模型，也需要 Harness 帮它管窗口、跑代码、存状态、验结果。</strong></p><p><img src="/img/ai-agent-harness-deep-dive/14.png" alt="Harness 即产品：同模型不同 Harness 性能差异" loading="lazy" decoding="async"></p><h2 id="小编评注"><a href="#小编评注" class="headerlink" title="小编评注"></a>小编评注</h2><p><strong>因为 Agent 时代会产生大量高频、半结构化、带上下文、需要回放和比较的过程性数据。</strong></p><p>现在有一个非常“刺眼”的问题：通用 Agent 把运行时数据落到 JSONL &#x2F; Markdown &#x2F; SQLite 等外围文件中。很多公司被 Postgres + pgvector + Redis + ClickHouse + LangSmith + JSONL 的运维成本搞疯了。</p><p><img src="/img/ai-agent-harness-deep-dive/15.png" alt="Agent 运行时数据散落多组件的运维困境配图" loading="lazy" decoding="async"></p><p>LangChain 为 LangSmith 自研了 SmithDB。详见：<a href="https://mp.weixin.qq.com/s?__biz=Mzk3NTE2NzU5NQ==&mid=2247491172&idx=1&sn=c52ebb2fdad4e08231bf2ff7eecf50f8&scene=21#wechat_redirect">LangChain “不务正业”，居然从零造了个数据库？</a></p><p><img src="/img/ai-agent-harness-deep-dive/16.jpg" alt="LangChain 自研 SmithDB 相关文章封面" loading="lazy" decoding="async"></p><p>Agent 的 context、execution history、task、observability 与 footprint，应该直接沉淀到数据库中。</p><p><img src="/img/ai-agent-harness-deep-dive/17.png" alt="Agent 过程性数据沉淀到数据库的架构示意图" loading="lazy" decoding="async"></p><h2 id="What’s-more"><a href="#What’s-more" class="headerlink" title="What’s more?"></a>What’s more?</h2><p>5 月 30 日，OceanBase × LangChain Meetup 上会重磅发布 AgentSeek。</p><p><img src="/img/ai-agent-harness-deep-dive/18.png" alt="OceanBase × LangChain Meetup 发布 AgentSeek 预告" loading="lazy" decoding="async"></p><p>AgentSeek 拥有 OB4AI + SeekVFS + SeekContext，可以把 context &#x2F; trace &#x2F; tool I&#x2F;O &#x2F; footprint 作为数据库原生对象承接。</p><p>点击下方图片，查看活动详情：</p><p><img src="/img/ai-agent-harness-deep-dive/19.png" alt="5 月 30 日上海 Meetup 活动详情海报" loading="lazy" decoding="async"></p><p>时间：5 月 30 日；地点：上海市浦东新区张江科学之门 T1 (模力·源) 35 楼</p><p>原文链接：《The Anatomy of an Agent Harness》: <a href="https://x.com/akshay_pachaar/status/2041146899319971922">https://x.com/akshay_pachaar&#x2F;status&#x2F;2041146899319971922</a></p>]]>
    </content>
    <id>https://ilongda.com/2026/2026-05-25-ai-agent-harness-deep-dive/</id>
    <link href="https://ilongda.com/2026/2026-05-25-ai-agent-harness-deep-dive/"/>
    <published>2026-05-25T00:58:12.000Z</published>
    <summary>本文译介 Akshay Pachaar 的长文《The Anatomy of an Agent Harness》，系统拆解 Anthropic、OpenAI、LangChain 的 Agent Harness 架构：编排循环、工具、记忆、上下文管理等 12 个核心组件，以及定义 Harness 的 7 个关键决策。</summary>
    <title>深度“解剖”AI Agent Harness</title>
    <updated>2026-05-25T00:58:12.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="AI &amp; 应用" scheme="https://ilongda.com/categories/AI-%E5%BA%94%E7%94%A8/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="智能运维" scheme="https://ilongda.com/tags/%E6%99%BA%E8%83%BD%E8%BF%90%E7%BB%B4/"/>
    <category term="AI Agent" scheme="https://ilongda.com/tags/AI-Agent/"/>
    <category term="开源社区" scheme="https://ilongda.com/tags/%E5%BC%80%E6%BA%90%E7%A4%BE%E5%8C%BA/"/>
    <category term="PowerMem" scheme="https://ilongda.com/tags/PowerMem/"/>
    <category term="Skill" scheme="https://ilongda.com/tags/Skill/"/>
    <category term="ClawMaster" scheme="https://ilongda.com/tags/ClawMaster/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"OceanBase 社区开启 Skill 宇宙！","description":"OceanBase 社区开源 oceanbase-skills 仓库，首发部署运维 Skill，让 AI Agent 用自然语言完成集群部署、租户管理、压测与备份恢复；同时探讨把 Skill 存入数据库做结构化管理的新思路，并介绍面向非技术用户的开源工具 ClawMaster。","image":"https://ilongda.com/img/oceanbase-community-skill-universe/01.png","wordCount":2404,"datePublished":"2026-05-22T00:21:37.000Z","dateModified":"2026-05-22T00:21:37.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-05-22-oceanbase-community-skill-universe/"},"url":"https://ilongda.com/2026/2026-05-22-oceanbase-community-skill-universe/","inLanguage":"zh-CN","keywords":["OceanBase","智能运维","AI Agent","开源社区","PowerMem","Skill","ClawMaster"],"articleSection":["AI & 应用"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"AI & 应用","item":"https://ilongda.com/categories/AI-应用/"},{"@type":"ListItem","position":3,"name":"OceanBase 社区开启 Skill 宇宙！","item":"https://ilongda.com/2026/2026-05-22-oceanbase-community-skill-universe/"}]}</script><blockquote><p>💭 对了，文中还悄悄提到了 PowerMem —— 一个能让你的 AI Agent “过目不忘”的记忆魔法库。感兴趣的话，欢迎来 <a href="https://github.com/oceanbase/powermem">https://github.com/oceanbase/powermem</a> 看看，给你的 Agent 装个”最强大脑”吧～</p></blockquote><h2 id="楔子"><a href="#楔子" class="headerlink" title="楔子"></a>楔子</h2><p>OceanBase 社区的研发大佬谐云，前段儿时间在 GitHub 上的 OceanBase 项目里悄咪咪地开源了一个新仓库：oceanbase-skills [1]</p><p><img src="/img/oceanbase-community-skill-universe/01.png" alt="GitHub 上 oceanbase-skills 开源仓库页面" decoding="async"></p><p>然后这个家伙发布了第一批和部署、运维相关的的 Skills —— oceanbase-deploy [2] 。安装之后，在 AI Agent 里用自然语言，就能完成数据库的集群部署、租户管理、性能压测和备份恢复等运维操作。</p><p>用过 OceanBase 的同学都知道， <code>obd</code> 命令行工具功能强大，但命令多、参数杂——部署要写配置文件，压测要记住 <code>--remote-tbl-dir</code> 是必填项，主备切换还得分清 <code>switchover</code> 和 <code>failover</code> 的适用场景……</p><span id="more"></span><p><strong>跑一次 TPC-H 压测，之前你要这样：</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. 查文档确认命令格式</span></span><br><span class="line"><span class="comment"># 2. 记住 --remote-tbl-dir 是必填参数</span></span><br><span class="line"><span class="comment"># 3. 手动创建目录</span></span><br><span class="line"><span class="built_in">mkdir</span> -p /tmp/tpch</span><br><span class="line"><span class="comment"># 4. 拼完整命令</span></span><br><span class="line">obd <span class="built_in">test</span> tpch ob-test --tenant=mysql_test --remote-tbl-dir=/tmp/tpch --scale-factor=1</span><br><span class="line"><span class="comment"># 5. 等着看有没有报错……</span></span><br></pre></td></tr></table></figure><p>有了这套 skill 之后之后， <strong>现在你只需要说一句话：</strong></p><blockquote><p>给 ob-test 的 <code>mysql_test</code> 租户跑 TPC-H</p></blockquote><p>AI 自动补全参数、创建目录、执行测试，22 条 SQL 全部跑完，总耗时不到 10 秒。</p><p>我们这些不懂技术的社区运营同学，在有了这批 Skills 之后，终于也能用自然语言运维 OceanBase 的系列产品了！嘿嘿~</p><h2 id="OceanBase-Skill-宇宙，由此开幕！"><a href="#OceanBase-Skill-宇宙，由此开幕！" class="headerlink" title="OceanBase Skill 宇宙，由此开幕！"></a>OceanBase Skill 宇宙，由此开幕！</h2><p>虽然这个仓库暂时只有一个和部署和运维相关的技能，但千里之行，始于足下。而且这个仓库里赫然写着：</p><blockquote><p>更多数据库相关 skill 持续开发中，计划覆盖：内核调优、SQL 诊断、数据迁移等。</p></blockquote><p>欢迎大家关注 OceanBase 社区公众号 “老纪的技术唠嗑局”，在这里，我们会持续为大家更新与 #AI 和 #Data 相关的技术内容~</p><h3 id="小彩蛋：你最想要哪个-Skill？"><a href="#小彩蛋：你最想要哪个-Skill？" class="headerlink" title="小彩蛋：你最想要哪个 Skill？"></a>小彩蛋：你最想要哪个 Skill？</h3><p>如果你正在研究怎么用 Skill 辅助数据库运维工作， <strong>欢迎在评论区告诉我你最想要哪个 Skill 进入 <code>oceanbase-skills</code> 仓库（上图有或没有的都可以）</strong> 。留言最多的那个，兹拉坦就帮大家早日安排上~</p><p>同时，也欢迎大家和我们一起来 <a href="https://github.com/oceanbase/oceanbase-skills">https://github.com/oceanbase/oceanbase-skills</a> 这里，进行共建~</p><h2 id="Skill-多了怎么管？下面这个思路有点意思！"><a href="#Skill-多了怎么管？下面这个思路有点意思！" class="headerlink" title="Skill 多了怎么管？下面这个思路有点意思！"></a>Skill 多了怎么管？下面这个思路有点意思！</h2><p>Agent 下面的 Skill 一旦多起来，功能有交集的就难免要”打架”，比如上面小彩蛋的这张兹拉坦的截图里就有一百个左右的常用 Skill，用来给这篇公众号文章配图的就不下五个。</p><p>现在 Agent 的做法是通过文件系统扫描——把 Skill 写成 Markdown 文件，放在文件系统里，需要使用时，会把所有 Skill.md 遍历扫一遍。</p><p>但在使用 Agent 的过程中，Skill 数量必然会持续变多、层级变深、规则变复杂，麻烦也会慢慢冒出来： <strong>在大量文本中定位特定 Skill 耗时会越来越长（扫描会变慢），Skill.md 之间的依赖关系也越来越难以追踪</strong></p><p>除此以外，长文档容易漏读，召回越来越不稳定，不同 Agent 对同一段 Markdown 的理解也可能不一样。更现实的是，Skill 的版本、依赖、适用场景，很难一直靠文件夹和文件名管清楚。而且上下文窗口有限制，可能会无法完整加载所有 Skill……</p><p>在昨天的 tcworld China [3] （技术内容领域的国际盛会）上，看到海芊大佬分享了一个很有创意的解法： <strong>把 Skill 从 Markdown 文件变成数据库里可快速查询的结构化数据。</strong></p><blockquote><p>传统依赖文本文件存储技能的方法，往往受模型解析能力限制，容易导致字符丢失或输出错误。把 Skill 存入结构化数据库，用查询语法驱动交互，能以低成本实现高稳定性的执行环境。</p></blockquote><p><img src="/img/oceanbase-community-skill-universe/02.png" alt="Skill 存入结构化数据库的方案分享现场" loading="lazy" decoding="async"></p><p>大致流程是：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Skill.md</span><br><span class="line">  → 解析器</span><br><span class="line">    → 轻量数据库入库</span><br><span class="line">      → QueryService 统一查询</span><br><span class="line">        → Agent 获取结构化结果</span><br></pre></td></tr></table></figure><p>这件事听起来像”把文件放进数据库”，但核心价值不是存储形式变了，而是 Skill 的调用方式变了。</p><p>以前是：</p><blockquote><p>Agent，你自己去文件堆里找找看。</p></blockquote><p>以后是：</p><blockquote><p>Agent，这是候选技能、适用条件、约束规则和示例，请按结构化结果执行。</p></blockquote><p>对于多 Agent 场景，这个思路尤其有价值。因为多个 Agent 如果都靠各自读 Markdown、各自理解，很容易出现偏差；如果大家都通过同一个 QueryService 查询 <strong>结构化的 Skill 元信息</strong> ，稳定性会更好。这样做不仅保证了 Skill 的完整性和可追溯性，也能提升模型在复杂任务执行中的鲁棒性，为大规模 Agent 应用提供了可扩展的工程化路径。</p><p><img src="/img/oceanbase-community-skill-universe/03.png" alt="结构化管理 Skill 方案讲解配图一" loading="lazy" decoding="async"></p><p><img src="/img/oceanbase-community-skill-universe/04.png" alt="结构化管理 Skill 方案讲解配图二" loading="lazy" decoding="async"></p><p><img src="/img/oceanbase-community-skill-universe/05.png" alt="结构化管理 Skill 方案讲解配图三" loading="lazy" decoding="async"></p><p><img src="/img/oceanbase-community-skill-universe/06.png" alt="结构化管理 Skill 方案讲解配图四" loading="lazy" decoding="async"></p><p>如果未来 Skill 管理能用类似思路做起来， <strong>Agent 生态就会少一点儿玄学，多一点些工程化</strong></p><p>后面有机会的话，OceanBase 社区会邀请海芊老板来 OceanBase 社区视频号”老纪的技术唠嗑局”，搞一场直播，专门和大家聊聊”结构化管理 Skill”这个话题，欢迎大家关注~</p><h2 id="AI-小白的第一个-AI-Agent-——-ClawMaster"><a href="#AI-小白的第一个-AI-Agent-——-ClawMaster" class="headerlink" title="AI 小白的第一个 AI Agent —— ClawMaster"></a>AI 小白的第一个 AI Agent —— ClawMaster</h2><h3 id="先闲白儿两句"><a href="#先闲白儿两句" class="headerlink" title="先闲白儿两句"></a>先闲白儿两句</h3><p>大家可以在上面的截图中，看到兹拉坦的常用 Skill 中有很多和技术文章相关的 Skill，包含了话题获取、排版、配图、发布等等。</p><p>每次开周会时，我老大也会习惯性地问这么一句话：今天你发的公众号文章，是不是又是用”AI 写的”。我每次都只能无奈地说：”是”。</p><p>其实我用 AI Agent 写作的方式，和数据库方向公众号最头部的冯若航大佬很类似。所以这里就直接偷懒引用冯佬的这篇文章 <a href="https://mp.weixin.qq.com/s?__biz=MzU5ODAyNTM5Ng==&mid=2247491818&idx=1&sn=a437b73d9b3ceae1225a7f5457432d42&scene=21#wechat_redirect">《是的，我用 AI 写文章，咋滴》</a> ，讲一遍用 AI 写文章的流程：</p><blockquote><p>选题是我的，框架是我的，AI 来填充初稿，然后反复打磨三到五轮，标题和封面图都让 AI 生成 100 个候选再从里面选。 <strong>AI 是倍乘器，不是加法器。</strong></p><p>它乘以什么，就放大什么。有洞见的人，AI 帮他放大洞见；脑子里一团浆糊的人，AI 帮他放大成更离谱的浆糊。</p><p>同一个模型，不同的人用出来天差地别。区别从来不在工具，在人。</p></blockquote><p><img src="/img/oceanbase-community-skill-universe/07.webp" alt="冯若航谈用 AI 写文章的观点配图" loading="lazy" decoding="async"></p><p>这篇文章写的时候，兹拉坦也在按这个逻辑用 Skill 来提效——大纲是我定的，素材整理全靠 Skill 帮忙，封面配图也用 Skill 生成。整件事做下来，效率提升是真实的，但”想表达什么”这件事依然得靠自己想清楚。</p><p>最后也引用冯佬的一句话：</p><blockquote><p>您自己判断，算不算”AI 写的”？</p></blockquote><p><img src="/img/oceanbase-community-skill-universe/08.png" alt="用 Skill 辅助写作与配图的实践示例" loading="lazy" decoding="async"></p><h3 id="我不是技术人员，但也想有强大的-AI-助理"><a href="#我不是技术人员，但也想有强大的-AI-助理" class="headerlink" title="我不是技术人员，但也想有强大的 AI 助理"></a>我不是技术人员，但也想有强大的 AI 助理</h3><p>最后想给大家介绍一个开源工具 —— ClawMaster [4] 。</p><h4 id="ClawMaster-适合谁？"><a href="#ClawMaster-适合谁？" class="headerlink" title="ClawMaster 适合谁？"></a>ClawMaster 适合谁？</h4><ul><li><strong>“我不是技术人员，但也想有强大的 AI 助理”</strong> —— 引导式安装、引导式使用，不要求你懂 JSON。</li><li><strong>“想让 OpenClaw 真的能帮我做事，不只是配好”</strong> —— 缩短”安装完成”到”真实产出”的距离。</li><li><strong>“我在帮团队或家人管 OpenClaw”</strong> —— 一个地方搞定频道、运行态、上手流程。</li><li><strong>“我在搭高级智能体工作流”</strong> —— 模型、可观测、记忆、会话、插件、技能、MCP 一站式。</li></ul><p>这个 ClawMaster 对技术小白非常友好，特别是零基础的运营同学。</p><p>通过两行命令，就可以把 ClawMaster 跑起来：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm i -g clawmaster</span><br><span class="line">clawmaster</span><br></pre></td></tr></table></figure><p>浏览器开 <code>http://localhost:16223</code></p><p>它还接入了 PowerMem [5] （OceanBase 团队开源的记忆引擎）作为底座。以前的记忆是一堆 Markdown 文件，现在变成可查询、带遗忘曲线的结构化存储。</p><p>最后 ClawMaster 还配合了 Karpathy 那套 LLM Wiki 构想 [6] ，内容进来一次，知识库持续复利生长——你没贴链接，Agent 写草稿时也带着你之前沉淀过的观点。</p><p>LLM Wiki 是什么？可以查看文末参考资料，深入了解~</p><h2 id="写在最后"><a href="#写在最后" class="headerlink" title="写在最后"></a>写在最后</h2><p>这篇文章从 <code>oceanbase-skills</code> 上线，到 Skill 管理的新思路，再到 ClawMaster。OceanBase 社区在 Data × AI 方向的这几步，都是从实际问题出发走出来的，没有特别宏大的叙事，只是一个 Skill、一个想法、一个工具。</p><h2 id="5-30-你来吗？OceanBase-×-LangChain-Meetup"><a href="#5-30-你来吗？OceanBase-×-LangChain-Meetup" class="headerlink" title="5.30 你来吗？OceanBase × LangChain Meetup"></a>5.30 你来吗？OceanBase × LangChain Meetup</h2><p>5 月 30 日， <a href="https://mp.weixin.qq.com/s?__biz=Mzk3NTE2NzU5NQ==&mid=2247491139&idx=1&sn=cc62af5e6ef11677d60e3ddebadc9dfb&scene=21#wechat_redirect">OceanBase × LangChain 社区 Meetup</a> 来了！不仅会有新产品的重磅发布，大家还可以一起来和 LangChain 中国区唯一的 Ambassador 张海立大佬（同时也是上面这个 ClawMaster 的作者），对当前 AI Agentic 时代的产品形态、技术架构等话题，进行交流和讨论~</p><p><strong>议程：</strong></p><p><strong>纯干货、强实战</strong></p><p>🕐 时间：5 月 30 日</p><p>🏠 地点：上海市浦东新区张江科学之门 T1 (模力・源) 35 楼大会议室</p><p>❗ 报名提醒：席位有限，先到先得！扫码立即预约，抢占 AI 工程化第一排座位！</p><p>参考资料</p><p>[1] oceanbase-skills: <a href="https://github.com/oceanbase/oceanbase-skills">https://github.com/oceanbase/oceanbase-skills</a><br>[2] oceanbase-deploy: <a href="https://github.com/oceanbase/oceanbase-skills/tree/master/skills/oceanbase-deploy">https://github.com/oceanbase/oceanbase-skills/tree/master/skills/oceanbase-deploy</a><br>[3] tcworld China: <a href="https://www.tcworld-china.cn/">https://www.tcworld-china.cn/</a><br>[4] ClawMaster: <a href="https://github.com/openmaster-ai/clawmaster">https://github.com/openmaster-ai/clawmaster</a><br>[5] PowerMem: <a href="https://github.com/oceanbase/powermem">https://github.com/oceanbase/powermem</a><br>[6] LLM Wiki 构想: <a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f">https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f</a></p>]]>
    </content>
    <id>https://ilongda.com/2026/2026-05-22-oceanbase-community-skill-universe/</id>
    <link href="https://ilongda.com/2026/2026-05-22-oceanbase-community-skill-universe/"/>
    <published>2026-05-22T00:21:37.000Z</published>
    <summary>OceanBase 社区开源 oceanbase-skills 仓库，首发部署运维 Skill，让 AI Agent 用自然语言完成集群部署、租户管理、压测与备份恢复；同时探讨把 Skill 存入数据库做结构化管理的新思路，并介绍面向非技术用户的开源工具 ClawMaster。</summary>
    <title>OceanBase 社区开启 Skill 宇宙！</title>
    <updated>2026-05-22T00:21:37.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Longda Feng</name>
    </author>
    <category term="最新动态" scheme="https://ilongda.com/categories/%E6%9C%80%E6%96%B0%E5%8A%A8%E6%80%81/"/>
    <category term="OceanBase" scheme="https://ilongda.com/tags/OceanBase/"/>
    <category term="OMS" scheme="https://ilongda.com/tags/OMS/"/>
    <category term="obdiag" scheme="https://ilongda.com/tags/obdiag/"/>
    <category term="向量索引" scheme="https://ilongda.com/tags/%E5%90%91%E9%87%8F%E7%B4%A2%E5%BC%95/"/>
    <category term="seekdb" scheme="https://ilongda.com/tags/seekdb/"/>
    <category term="PowerMem" scheme="https://ilongda.com/tags/PowerMem/"/>
    <category term="社区月报" scheme="https://ilongda.com/tags/%E7%A4%BE%E5%8C%BA%E6%9C%88%E6%8A%A5/"/>
    <content>
      <![CDATA[<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"OceanBase 社区月报：PowerMem、OMS、obdiag 全面更新","description":"OceanBase 社区 2026 年 5 月月报：PowerMem v1.0.0 接入 pyseekdb 支持嵌入式向量存储，OMS V4.2.13-CE 新增 ES、MongoDB、ClickHouse 数据源，obdiag 4.3.0 上线基于 MCP 的智能诊断 Agent，并带来内核缺陷修复与社区动态。","image":"https://ilongda.com/img/oceanbase-community-monthly-2026-05/01.png","wordCount":903,"datePublished":"2026-05-21T13:06:17.000Z","dateModified":"2026-05-21T13:06:17.000Z","isAccessibleForFree":true,"author":{"@type":"Person","name":"Longda Feng","url":"https://ilongda.com"},"publisher":{"@type":"Organization","name":"Longda's Interesting World","logo":{"@type":"ImageObject","url":"https://ilongda.com/img/my.jpg"}},"mainEntityOfPage":{"@type":"WebPage","@id":"https://ilongda.com/2026/2026-05-21-oceanbase-community-monthly-2026-05/"},"url":"https://ilongda.com/2026/2026-05-21-oceanbase-community-monthly-2026-05/","inLanguage":"zh-CN","keywords":["OceanBase","OMS","obdiag","向量索引","seekdb","PowerMem","社区月报"],"articleSection":["最新动态"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://ilongda.com/"},{"@type":"ListItem","position":2,"name":"最新动态","item":"https://ilongda.com/categories/最新动态/"},{"@type":"ListItem","position":3,"name":"OceanBase 社区月报：PowerMem、OMS、obdiag 全面更新","item":"https://ilongda.com/2026/2026-05-21-oceanbase-community-monthly-2026-05/"}]}</script><blockquote><p>OceanBase 社区月报概述：</p><ul><li>OceanBase 社区发布 PowerMem v1.0.0（接入 pyseekdb，无需单独部署数据库，支持嵌入式向量存储）</li><li>OMS V4.2.13-CE（新增 ES、MongoDB、ClickHouse 等数据源）</li><li>obdiag 4.3.0（基于 MCP 的智能诊断 Agent，上线 AI 诊断 Agent）</li></ul></blockquote><p><img src="/img/oceanbase-community-monthly-2026-05/01.png" alt="OceanBase 社区月报封面图" decoding="async"></p><span id="more"></span><h2 id="PowerMem-v1-0-0：正式支持嵌入式的-seekdb-作为存储后端"><a href="#PowerMem-v1-0-0：正式支持嵌入式的-seekdb-作为存储后端" class="headerlink" title="PowerMem v1.0.0：正式支持嵌入式的 seekdb 作为存储后端"></a>PowerMem v1.0.0：正式支持嵌入式的 seekdb 作为存储后端</h2><p>PowerMem 是一个基于 Apache 2.0 开源，旨在解决 AI 应用中记忆问题的轻量级组件。本版本最重要的变化是接入 <strong>pyseekdb</strong>，支持 <strong>OceanBase 向量存储下的嵌入式 seekdb</strong>：在本地指定数据目录即可运行，<strong>无需单独部署数据库服务</strong>。</p><h2 id="OceanBase-V4-4-1-CE-HF4：关键缺陷修复"><a href="#OceanBase-V4-4-1-CE-HF4：关键缺陷修复" class="headerlink" title="OceanBase V4.4.1_CE_HF4：关键缺陷修复"></a>OceanBase V4.4.1_CE_HF4：关键缺陷修复</h2><ul><li>优化全文索引构建，解决超大文本 ik 分词导致的内存膨胀问题</li><li>修复复制表中含向量索引时，升级阶段执行 upgrade_health_checker 脚本失败的问题</li><li>优化向量 follow 同步机制，修复切主后可能触发的大量补数据问题</li><li>优化 JSON_OVERLAPS 表达式与向量过滤器组合场景下非主键大账号耗时长的问题</li><li>修复 HNSW_BQ 配合 BETWEEN 查询时 SQL 查询结果与暴力搜索结果不一致的问题</li><li>修复前缀索引与语义索引共存时前过滤器 pre_filter 查询遗漏数据的问题</li></ul><h2 id="OceanBase-V4-3-5-CE-BP6：关键缺陷修复"><a href="#OceanBase-V4-3-5-CE-BP6：关键缺陷修复" class="headerlink" title="OceanBase V4.3.5_CE_BP6：关键缺陷修复"></a>OceanBase V4.3.5_CE_BP6：关键缺陷修复</h2><ul><li>修复指定 Hint 多值索引查询报错 1235 不支持的问题</li><li>修复了重建向量索引时可能发生的 coredump 问题</li><li>修复了 HNSW 索引在 LATENCY_FIRST 模式下查询报 -7605 错误及 IVF 索引内存爆的问题</li><li>修复了向量索引 adapter 双重释放导致异常的问题、IVF 缓存管理器内存泄漏的问题</li><li>修复了 HNSW 索引并行补全数据时数据丢失的问题</li><li>修复了向量索引 DDL 与后台任务缺少互斥逻辑导致 DDL 挂起的问题</li></ul><h2 id="OBD：安装部署工具新增支持-seekdb-的安装部署"><a href="#OBD：安装部署工具新增支持-seekdb-的安装部署" class="headerlink" title="OBD：安装部署工具新增支持 seekdb 的安装部署"></a>OBD：安装部署工具新增支持 seekdb 的安装部署</h2><p>支持 seekdb 的安装部署、主备库搭建、主备库运维。</p><h2 id="OMS-V4-2-13-CE：新增多数据源支持"><a href="#OMS-V4-2-13-CE：新增多数据源支持" class="headerlink" title="OMS V4.2.13-CE：新增多数据源支持"></a>OMS V4.2.13-CE：新增多数据源支持</h2><p>新增 ES、MongoDB、ClickHouse 等数据源，支持 OceanBase 开启 TLS。</p><table><thead><tr><th>数据源</th><th>结构迁移</th><th>全量数据迁移</th><th>增量同步</th><th>全量校验</th><th>反向增量</th></tr></thead><tbody><tr><td>MySQL -&gt; OB-CE</td><td>支持</td><td>支持</td><td>支持</td><td>支持</td><td>支持</td></tr><tr><td>OB-CE -&gt; OB-CE</td><td>支持</td><td>支持</td><td>支持</td><td>支持</td><td>支持</td></tr><tr><td>TiDB -&gt; OB-CE</td><td>支持</td><td>支持</td><td>支持</td><td>支持</td><td>支持</td></tr><tr><td>PostgreSQL -&gt; OB-CE</td><td>支持</td><td>支持</td><td>支持</td><td>支持</td><td>支持</td></tr><tr><td>HBase -&gt; OB-CE</td><td>支持</td><td>支持</td><td>支持</td><td>暂不支持</td><td>暂不支持</td></tr><tr><td>Elasticsearch -&gt; OB-CE</td><td>不支持</td><td>支持</td><td>支持</td><td>不支持</td><td>不支持</td></tr><tr><td>MongoDB -&gt; OB-CE</td><td>不支持</td><td>支持</td><td>支持</td><td>不支持</td><td>不支持</td></tr><tr><td>ClickHouse -&gt; OB-CE</td><td>不支持</td><td>支持</td><td>不支持</td><td>不支持</td><td>不支持</td></tr></tbody></table><h2 id="obdiag-4-3-0：新增智能诊断-Agent-命令"><a href="#obdiag-4-3-0：新增智能诊断-Agent-命令" class="headerlink" title="obdiag 4.3.0：新增智能诊断 Agent 命令"></a>obdiag 4.3.0：新增智能诊断 Agent 命令</h2><p>新增智能诊断 Agent 命令（obdiag agent），基于 Pydantic-AI 与 MCP，支持自然语言描述诊断需求。新增 obdiag tool sql_syntax 命令。集群巡检 max_workers 默认调整为 6，新增 task_timeout_seconds（默认 60 秒）。</p><h2 id="生态产品认证进展：新增-11-款兼容产品"><a href="#生态产品认证进展：新增-11-款兼容产品" class="headerlink" title="生态产品认证进展：新增 11 款兼容产品"></a>生态产品认证进展：新增 11 款兼容产品</h2><p>涵盖北京中睿天下、武汉众智数字、北京信软同创等企业。</p><h2 id="社区动态"><a href="#社区动态" class="headerlink" title="社区动态"></a>社区动态</h2><ol><li>4 月 25 日深圳 Meetup 圆满收官——Agent 时代的”存算演进”</li><li>社区免费课程 Easy “Data x AI” 已更新 12 节课</li><li><strong>5 月 30 日上海 Meetup</strong>——OceanBase × LangChain</li></ol><p><img src="/img/oceanbase-community-monthly-2026-05/02.png" alt="上海 OceanBase × LangChain Meetup 活动海报" loading="lazy" decoding="async"></p><p><img src="/img/oceanbase-community-monthly-2026-05/03.jpg" alt="OceanBase 社区活动与课程动态配图" loading="lazy" decoding="async"></p><p>参考资料：</p><ul><li>[1] PowerMem v1.0.0: <a href="https://open.oceanbase.com/blog/26389521168">https://open.oceanbase.com/blog/26389521168</a></li><li>[2] 部署 seekdb: <a href="https://www.oceanbase.com/docs/common-obd-cn-1000000005623804">https://www.oceanbase.com/docs/common-obd-cn-1000000005623804</a></li><li>[5] 智能诊断 Agent: <a href="https://www.oceanbase.com/docs/common-obdiag-cn-1000000005726803">https://www.oceanbase.com/docs/common-obdiag-cn-1000000005726803</a></li><li>[12] 城市行回顾: <a href="https://open.oceanbase.com/blog/27232841472">https://open.oceanbase.com/blog/27232841472</a></li><li>[13] Easy Data x AI: <a href="https://open.oceanbase.com/course/760">https://open.oceanbase.com/course/760</a></li></ul>]]>
    </content>
    <id>https://ilongda.com/2026/2026-05-21-oceanbase-community-monthly-2026-05/</id>
    <link href="https://ilongda.com/2026/2026-05-21-oceanbase-community-monthly-2026-05/"/>
    <published>2026-05-21T13:06:17.000Z</published>
    <summary>OceanBase 社区 2026 年 5 月月报：PowerMem v1.0.0 接入 pyseekdb 支持嵌入式向量存储，OMS V4.2.13-CE 新增 ES、MongoDB、ClickHouse 数据源，obdiag 4.3.0 上线基于 MCP 的智能诊断 Agent，并带来内核缺陷修复与社区动态。</summary>
    <title>OceanBase 社区月报：PowerMem、OMS、obdiag 全面更新</title>
    <updated>2026-05-21T13:06:17.000Z</updated>
  </entry>
</feed>
