<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/rss.xsl" type="text/xsl"?>
<rss version="2.0">
  <channel>
    <title>IT瘾数据推荐</title>
    <link>https://itindex.net/categories/数据</link>
    <description>IT社区推荐资讯 - ITIndex.net</description>
    <language>zh</language>
    <copyright>https://itindex.net/</copyright>
    <generator>https://itindex.net/</generator>
    <docs>http://backend.userland.com/rss</docs>
    <image>
      <url>https://itindex.net/images/logo.gif</url>
      <title>IT社区推荐资讯 - ITIndex.net</title>
      <link>https://itindex.net/categories/数据</link>
    </image>
    <item>
      <title>Indeed招聘数据显示全球软件工程师的岗位招聘量全面反弹</title>
      <link>https://itindex.net/detail/63172-indeed-%E6%8B%9B%E8%81%98-%E6%95%B0%E6%8D%AE</link>
      <description>&lt;p&gt;根据近期Indeed的招聘数据和相关行业分析，软件工程师的岗位招聘量正处在一个总量增长但结构分化的关键时期。最新的数据明确显示，市场对软件工程师的需求并非缩减，而是在持续增加，但这背后伴随着对技能要求的深刻变革。&lt;/p&gt; &lt;h3&gt;📊 核心数据：岗位总量在增长&lt;/h3&gt; &lt;p&gt;根据金融巨头Citadel Securities在2026年2月底引用Indeed的数据，软件工程师的职位数量同比增长了11%   &lt;a href="https://ovs.entrust.com.tw/entrustOverseas/announcement/nowInner.do?id=6353642" rel="noreferrer" target="_blank"&gt;-3&lt;/a&gt;。此外，2026年1月的行业分析也显示，单月全球软件工程领域的招聘岗位曾突破10.5万个，标志着行业从之前的增长放缓中全面反弹   &lt;a href="https://www.anquanke.com/post/id/314143&amp;sa=U&amp;ved=2ahUKEwiPpo-37o6SAxXtN0QIHQxrGsIQFnoECAMQAg&amp;usg=AOvVaw3XqC9ljGIWZxTZasrw_pLT" rel="noreferrer" target="_blank"&gt;-7&lt;/a&gt;。&lt;/p&gt; &lt;h3&gt;🔍 数据背后的趋势解读&lt;/h3&gt; &lt;p&gt;这11%的增长并非简单的数字游戏，它反映了当前技术就业市场的几个深层变化：&lt;/p&gt; &lt;ol start="1"&gt;  &lt;li&gt;   &lt;p&gt;AI的“替代论”被证伪，需求转向“增强”：尽管外界担忧AI会导致大规模失业，但实际数据反驳了这一点。正如Citadel Securities的报告所指出的，AI更像是一个“生产力冲击”，类似于历史上的电气化和计算机，它正在创造新的经济机会和岗位，而非简单地消灭工作     &lt;a href="https://ovs.entrust.com.tw/entrustOverseas/announcement/nowInner.do?id=6353642" rel="noreferrer" target="_blank"&gt;-3&lt;/a&gt;。企业利用AI扩大产出，反而催生了新的开发需求     &lt;a href="https://www.ltesting.net/wp/2026/the-next-two-years-of-software-engineering.html" rel="noreferrer" target="_blank"&gt;-5&lt;/a&gt;。&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;岗位结构发生剧变：初级岗承压，资深/复合型岗紧缺：增长的岗位主要集中在需要深厚经验和跨学科能力的领域。与此同时，初级开发者的入门路径变得崎岖     &lt;a href="https://www.ltesting.net/wp/2026/the-next-two-years-of-software-engineering.html" rel="noreferrer" target="_blank"&gt;-5&lt;/a&gt;。&lt;/p&gt;   &lt;ul&gt;    &lt;li&gt;     &lt;p&gt;人才流向高价值领域：人才正大量涌向人工智能/大模型、机器人与具身智能、生物信息学、新能源与气候科技、网络安全等高技术壁垒领域       &lt;a href="https://ones.com.cn/tech-news/computer-science-exodus-2026-tech-talent-trends" rel="noreferrer" target="_blank"&gt;-6&lt;/a&gt;      &lt;a href="https://www.anquanke.com/post/id/314143&amp;sa=U&amp;ved=2ahUKEwiPpo-37o6SAxXtN0QIHQxrGsIQFnoECAMQAg&amp;usg=AOvVaw3XqC9ljGIWZxTZasrw_pLT" rel="noreferrer" target="_blank"&gt;-7&lt;/a&gt;      &lt;a href="https://www.sunsharer.com.cn/phone/news/873.html" rel="noreferrer" target="_blank"&gt;-8&lt;/a&gt;。&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;     &lt;p&gt;企业招聘更务实：企业不再满足于“会写代码”，而是极度渴望能解决实际问题、有系统架构能力、懂业务逻辑的复合型人才       &lt;a href="https://www.sunsharer.com.cn/phone/news/873.html" rel="noreferrer" target="_blank"&gt;-8&lt;/a&gt;。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;AI重塑了工程师的核心技能：现在的工程师，核心竞争力不再是单纯的编码速度，而是利用AI作为“力量倍增器”，并具备判断AI何时出错、优化系统设计、保障安全与合规的能力     &lt;a href="https://www.ltesting.net/wp/2026/the-next-two-years-of-software-engineering.html" rel="noreferrer" target="_blank"&gt;-5&lt;/a&gt;。简单来说，市场需要的是能驾驭AI的专家，而非被AI替代的“代码民工”。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;💡 总结与展望&lt;/h3&gt; &lt;p&gt;Indeed上软件工程师岗位11%的年增长是一个强有力的信号：技术变革正在创造新的就业机会。但这意味着，未来的机会将更加青睐那些主动拥抱变化、持续学习、并将技术深度与业务广度相结合的工程师。&lt;/p&gt;
     
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/63172-indeed-%E6%8B%9B%E8%81%98-%E6%95%B0%E6%8D%AE</guid>
      <pubDate>Mon, 02 Mar 2026 16:33:58 CST</pubDate>
    </item>
    <item>
      <title>数据库迁移的一种方法</title>
      <link>https://itindex.net/detail/63087-%E6%95%B0%E6%8D%AE%E5%BA%93-%E6%96%B9%E6%B3%95</link>
      <description>当数据库记录突破 10 亿条，原本几毫秒的查询变成几秒钟，批处理任务跑上数小时，这样的性能瓶颈对任何系统都是灾难。但更大的挑战在于，这是金融系统的支付、订单和账本数据，业务不允许一秒钟的停机时间。

这篇来自惊心动魄的实战案例给出了一个渐进式的解决方案。核心思路是把风险拆解成可控的小步骤：先迁移不再变化的冷数据，按主键分块并行处理，暂时禁用索引以提升速度。接着通过双写机制捕获实时流量，每笔新交易同时写入新旧两个数据库，失败的写入推送到 Kafka 队列反复重试，确保数据最终一致。

最巧妙的设计是影子读阶段。用户请求仍然从旧库读取，但每个查询会在后台悄悄对新库执行一遍，比对结果差异。这个过程持续数周，让团队发现了测试环境永远抓不到的问题：时区处理差异、NULL 值的默认行为、字符排序规则不同。这些都是真实流量才能暴露的坑。

最后的切换选在凌晨流量最低时进行，提前通过合成查询预热新库的缓存和索引，然后通过功能开关逐步转移读流量。团队盯着 Grafana 面板上的延迟、错误率和业务指标曲线，24 小时后才确认切换成功。

这个方案对于数据库迁移，比如信创改造的时候很有借鉴价值。我认为这里有三个关键的设计：

一是渐进式风险控制，每一步都可以独立验证和回滚；
二是用真实流量做验证，影子读比任何测试都更能发现兼容性问题。
三是可观测性优先，从数据库内部的 WAL 日志、缓存命中率，到业务层的订单量和收入流量，全程监控让团队能及时发现异常。&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/63087-%E6%95%B0%E6%8D%AE%E5%BA%93-%E6%96%B9%E6%B3%95</guid>
      <pubDate>Tue, 11 Nov 2025 17:16:58 CST</pubDate>
    </item>
    <item>
      <title>数据分类分级：理论、实践与未来挑战</title>
      <link>https://itindex.net/detail/63017-%E6%95%B0%E6%8D%AE-%E5%88%86%E7%B1%BB-%E5%88%86%E7%BA%A7</link>
      <description>&lt;div&gt;    &lt;h2&gt;摘要&lt;/h2&gt;    &lt;p&gt;数据分类分级作为数据治理与安全的核心环节，已成为数字经济时代组织管理数据资产的基础性工作。本报告系统梳理了数据分类分级的概念体系、方法技术、标准规范及行业实践，深入分析了当前实施过程中的关键挑战与争议，并基于国内外最新发展动态提出了优化建议。研究表明，数据分类分级工作正从静态盘点向动态管控转变，但同时也面临着标准落地难、自动化程度不足、与安全策略脱节等问题。未来需要构建更加智能化、场景化的分类分级体系，实现从合规导向到价值创造的转变。&lt;/p&gt;    &lt;h2&gt;引言&lt;/h2&gt;    &lt;p&gt;随着《数据安全法》《个人信息保护法》等法规的实施，数据分类分级已从技术实践上升为法律要求。GB/T 43697-2024《数据安全技术数据分类分级规则》的发布标志着我国数据分类分级工作进入标准化阶段。然而，在实际应用中，数据分类分级仍存在&amp;quot;重形式轻实效&amp;quot;的困境，被部分从业者批评为&amp;quot;网安集体的皇帝新衣&amp;quot;（安全内参，2024）。本报告旨在厘清数据分类分级的核心价值，分析其实施难点，并为组织构建有效的分类分级体系提供参考框架。&lt;/p&gt;    &lt;h2&gt;一、数据分类分级的概念框架&lt;/h2&gt;    &lt;h3&gt;1.1 基本定义与区别&lt;/h3&gt;    &lt;p&gt;      &lt;strong&gt;数据分类&lt;/strong&gt;是指根据数据的属性或特征（如性质、用途、来源等）进行逻辑分组的过程。从技术实现角度看，数据分类是一个多维度的系统工程，需要综合考虑数据的业务属性、法律属性和技术属性。在业务维度上，财务数据通常包括会计凭证、财务报表、预算数据等，这些数据具有高度的准确性和完整性要求；客户数据则涵盖客户基本信息、交易记录、行为偏好等，需要特别关注隐私保护；运营数据包括生产数据、库存数据、物流信息等，对实时性要求较高。从法律维度来看，个人信息需要遵循《个人信息保护法》的特殊要求，重要数据则需符合《数据安全法》第21条的管理规定，而核心数据则涉及国家安全审查机制。来源维度则需要区分内部生成数据（如业务系统产生的交易记录）和外部采集数据（如第三方提供的市场调研数据），两者的管理策略和权责划分存在显著差异。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;数据分级&lt;/strong&gt;则基于数据敏感性和重要性，根据数据泄露可能造成的危害程度划分保护等级。我国《数据安全法》将数据分为三级：一般数据指那些泄露后仅会造成轻微影响的数据，如公开的企业宣传资料；重要数据通常指一旦泄露可能危害国家安全、经济运行、社会稳定或公共健康安全的数据，如人口健康统计信息、重大基础设施运行数据等；核心数据则是对国家安全构成严重威胁的数据，如国防军工数据、国家未公开的重大科技项目数据等。在实际操作中，数据分级需要采用&amp;quot;就高从严&amp;quot;原则，即当数据集包含不同级别数据项时，按照最高级别对整体数据集进行定级。同时，分级结果需要建立动态调整机制，随着数据内容变化、业务场景调整或法规要求更新而相应变更。&lt;/p&gt;    &lt;h3&gt;1.2 核心价值与作用&lt;/h3&gt;    &lt;p&gt;有效的分类分级体系能够实现多方面的管理价值：在      &lt;strong&gt;精准访问控制&lt;/strong&gt;方面，基于数据级别可以实施细粒度的权限管理策略，例如对核心数据采用&amp;quot;双人原则&amp;quot;和审批制访问机制，对重要数据实施基于角色的访问控制（RBAC），而对一般数据则可放宽访问限制。      &lt;strong&gt;资源优化配置&lt;/strong&gt;体现在能够根据数据级别差异化部署安全措施，如对4级（绝密）数据采用硬件加密模块和量子加密传输，对3级（机密）数据使用软件加密和VPN通道，而对1级（公开）数据则无需特殊保护，从而实现安全投入的精准投放。&lt;/p&gt;    &lt;p&gt;从      &lt;strong&gt;合规风险管理&lt;/strong&gt;角度看，完善的分类分级体系能够系统性满足《数据安全法》第21条等法规要求，避免因数据管理不当导致的行政处罚。以某金融机构为例，通过实施分类分级，其数据泄露事件响应时间从72小时缩短至4小时，合规审计效率提升60%。在      &lt;strong&gt;数据资产化&lt;/strong&gt;方面，分类分级为数据共享流通奠定了信任基础，某省政务数据共享平台通过标准化分类分级，使跨部门数据共享效率提升300%，数据交易纠纷下降80%。&lt;/p&gt;    &lt;p&gt;然而，安全内参（2024）指出，当前许多组织的分类分级工作存在严重的形式主义问题。某大型国企的调研显示，其投入200万元完成的分类分级项目，产生的数据资产清单三个月后准确率已降至不足40%，与后续的安全管控完全脱节。更普遍的情况是，组织将分类分级视为一次性合规任务，缺乏持续运营机制，导致大量分类分级成果沦为&amp;quot;数字档案&amp;quot;，未能转化为实际的安全能力。&lt;/p&gt;    &lt;h2&gt;二、数据分类分级的方法论体系&lt;/h2&gt;    &lt;h3&gt;2.1 分类方法&lt;/h3&gt;    &lt;p&gt;根据GB/T 38667-2020，主流分类方法包括三种体系化方法：&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;线分类法&lt;/strong&gt;采用层级化树状结构，类别间存在严格的隶属关系。这种方法适合业务体系稳定的组织，如传统制造业。其典型特征是分类结构呈现金字塔形态，上层类别完全包含下层类别。例如在某汽车制造企业，一级分类为&amp;quot;研发数据&amp;quot;，二级可分为&amp;quot;整车设计数据&amp;quot;和&amp;quot;零部件数据&amp;quot;，三级再细分为&amp;quot;发动机图纸&amp;quot;、&amp;quot;底盘参数&amp;quot;等。线分类法的优势是结构清晰、便于理解，但缺点是灵活性不足，当出现跨类别数据时难以处理。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;面分类法&lt;/strong&gt;采用多维度平行划分方式，各维度可灵活组合。这种方法特别适合数据类型复杂的场景，如电商平台。面分类法允许从多个独立维度对数据进行标记，例如同时按&amp;quot;数据来源（用户提交/系统生成）&amp;quot;、&amp;quot;数据类型（文本/图像/视频）&amp;quot;和&amp;quot;业务领域（商品/订单/支付）&amp;quot;三个面进行分类。某头部电商的应用实践表明，面分类法使其UGC（用户生成内容）管理效率提升45%。但这种方法的挑战在于需要建立复杂的交叉索引机制。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;混合分类法&lt;/strong&gt;结合了上述两种方法的优势，成为大多数企业的最佳实践选择。通常采用线分类法建立主干框架，再辅以面分类法处理特殊情况。某全国性商业银行采用混合分类法，先按业务线（零售银行、公司金融等）进行线分类，再对跨业务线的客户数据采用&amp;quot;客户画像&amp;quot;、&amp;quot;交易行为&amp;quot;等面分类维度，实现了既保持结构稳定又具备足够灵活性的分类体系。&lt;/p&gt;    &lt;p&gt;金融行业的数据分类具有典型示范意义，其分类体系通常包含以下核心类别：客户信息（涵盖身份信息、账户信息、KYC资料等）、交易记录（包括支付流水、转账记录、投资交易等）、风控数据（如反洗钱报告、信用评分、欺诈标记等）、产品信息（理财产品说明书、保险合同条款等）以及运营统计（业务报表、监管报送数据等）。这种分类体系既满足了业务管理需求，又与《金融数据安全分级指南》的监管要求高度契合。&lt;/p&gt;    &lt;h3&gt;2.2 分级标准&lt;/h3&gt;    &lt;p&gt;数据分级需要系统考虑三个层面的影响对象：国家安全与社会公共利益层面，重点关注数据泄露可能对政治安全、国土安全、军事安全等领域的影响；组织利益层面，需评估数据对财务损益、商业竞争、企业声誉和业务连续性的潜在影响；个人权益层面，则需考量隐私侵犯、财产损失和生活安宁等方面的危害程度。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;分级原则&lt;/strong&gt;的实施需要建立系统化机制：&amp;quot;就高从严&amp;quot;原则要求建立数据项级别评估矩阵，当数据集包含多个级别数据项时，必须通过自动化扫描识别最高级别项；&amp;quot;动态调整&amp;quot;原则需要设置定期复核机制（建议至少每季度一次）和触发式更新机制（如业务系统升级时自动触发重评估）；&amp;quot;合法合规&amp;quot;原则则要求建立行业特殊要求的识别清单，如金融行业的客户金融信息需遵循JR/T 0197-2020的特殊规定。&lt;/p&gt;    &lt;p&gt;医疗健康行业的数据分级实践具有典型参考价值：4级（绝密）数据包括基因序列数据和罕见病病例，这些数据不仅涉及个人隐私，还可能影响国家生物安全；3级（机密）数据涵盖诊疗记录和医保信息，泄露可能导致医疗欺诈和保险欺诈；2级（秘密）数据如挂号信息和科室排班，主要影响医疗机构正常运营；1级（公开）数据包括医院简介和科普资料，可自由传播。某三甲医院的实施案例显示，通过这种分级体系，其数据泄露事件减少65%，安全运维成本降低30%。&lt;/p&gt;    &lt;h2&gt;三、标准规范与行业实践&lt;/h2&gt;    &lt;h3&gt;3.1 国内外标准体系&lt;/h3&gt;    &lt;p&gt;我国已建立多层次的数据分类分级标准框架：在国家层面，GB/T 43697-2024提供了基础性规则，明确了分类分级的通用原则和方法论；GB/T 38667-2020则侧重分类指南，详细规定了各类分类方法的实施要点。行业标准方面，《金融数据安全分级指南》（JR/T 0197-2020）将金融数据分为5个级别，并特别强调客户金融信息的特殊保护要求；《工业和信息化领域数据安全管理办法》则对工业和电信数据的分类分级做出专门规定。地方标准如北京市《公共数据分类分级指南》，重点解决政务数据共享中的分类分级问题。&lt;/p&gt;    &lt;p&gt;国际标准体系对我国实践具有重要参考价值：NIST SP 800-38G详细规定了格式保留加密标准，为数据脱敏提供技术规范；GDPR基于风险的数据分类保护要求，特别是对个人敏感数据的特殊处理规则，对出海企业具有强制约束力；ISO/IEC 38505则从数据治理角度，提供了分类分级的国际最佳实践。值得注意的是，不同标准间存在协调挑战，如我国的核心数据概念与欧盟的重要数据类别在界定范围上存在差异，跨国企业需要建立映射对照机制。&lt;/p&gt;    &lt;h3&gt;3.2 实施路径五步法&lt;/h3&gt;    &lt;p&gt;数据分类分级的实施需要系统化方法论支撑，五步法提供了可落地的实施框架：&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;现状调研&lt;/strong&gt;阶段需要开展立体化分析，包括业务系统架构梳理（识别关键业务系统及其数据流向）、数据资产现状评估（数据量、类型、存储位置等）和安全现状诊断（现有保护措施的有效性）。某央企的实践表明，采用问卷调查+系统扫描+关键人员访谈的&amp;quot;三维调研法&amp;quot;，可使调研结果准确率提升至85%以上。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;资产梳理&lt;/strong&gt;环节要构建全量数据资产目录，某省级银行的案例显示，通过结合自动化扫描工具（如敏感数据识别引擎）和人工复核，可在3个月内完成10PB数据的资产梳理，建立包含200多万个数据对象的资产清单。关键技术包括元数据采集、数据血缘分析和资产关联映射。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;分类设计&lt;/strong&gt;阶段需要建立与企业业务契合的分类体系，某电商平台的实践创新性地采用了&amp;quot;机器学习+业务规则&amp;quot;的双引擎分类法，先通过无监督学习对数据进行聚类分析，再结合业务规则进行类别标注，使分类准确率达到92%，远超纯规则方法的75%。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;分级实施&lt;/strong&gt;的核心是制定科学的分级规则，某保险公司创新采用&amp;quot;影响因子评分法&amp;quot;，从数据敏感性、扩散性和价值度三个维度设置评分指标，通过加权计算确定数据级别，使分级结果的可解释性大幅提升。同时需要建立分级变更的流程管控机制，确保级别调整的合规性。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;全景视图&lt;/strong&gt;阶段要构建分类分级知识图谱，某政务云平台通过将分类分级结果可视化，实现了数据资产的&amp;quot;一张图&amp;quot;管理，支持按分类、级别、部门等多维度检索，使数据查找时间从小时级降至分钟级。关键是要建立分类分级标签的传播机制，确保下游系统能自动继承上游数据的分类分级属性。&lt;/p&gt;    &lt;h3&gt;3.3 行业差异化实践&lt;/h3&gt;    &lt;p&gt;不同行业的数据分类分级呈现显著差异特征：金融业聚焦客户金融信息，实施五级分类体系，特别强调支付敏感信息（如银行卡验证码）的特殊保护。某全国性银行将验证码数据定为4级，采用硬件加密模块保护，访问需双重认证。医疗健康行业强调HIPAA合规，严格区分PHI（受保护健康信息）与非PHI，某医疗集团将电子病历定为3级，实施字段级加密和操作审计。政务数据按共享属性分类，某省政务平台将数据分为无条件共享、有条件共享和不予共享三类，通过区块链技术实现共享过程可追溯。互联网企业则注重用户行为数据与隐私保护的平衡，某社交平台采用差分隐私技术处理用户行为日志，在保护隐私的同时保留数据分析价值。&lt;/p&gt;    &lt;h2&gt;四、关键技术实现&lt;/h2&gt;    &lt;h3&gt;4.1 自动化分类分级工具&lt;/h3&gt;    &lt;p&gt;现代数据安全平台集成多种技术模块实现智能化分类分级：      &lt;strong&gt;敏感数据识别&lt;/strong&gt;引擎采用多技术融合方案，正则表达式用于识别结构化数据中的模式化信息（如身份证号、银行卡号等）；自然语言处理（NLP）技术处理非结构化文本中的敏感信息；机器学习模型则通过模式识别发现潜在的敏感数据。某金融科技公司的测试数据显示，融合技术的识别准确率可达93%，比单一技术提升20个百分点。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;元数据管理&lt;/strong&gt;系统构建数据资产的全景视图，关键技术包括元数据采集（支持数据库、文件系统、API等多种数据源）、血缘分析（追踪数据加工处理链条）和变更管理（自动同步结构变更）。某证券公司的实践表明，完善的元数据管理系统可使数据变更导致的分类分级失效问题减少70%。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;动态打标&lt;/strong&gt;技术实现标签的自动化管理，包括标签传播（在ETL过程中自动继承分类分级属性）、冲突检测（发现标签不一致问题）和人工复核界面（提供便捷的审核修正功能）。某电商平台通过动态打标系统，每日处理超过1亿次标签更新操作，准确率保持在99.5%以上。&lt;/p&gt;    &lt;p&gt;技术挑战主要集中在非结构化数据处理方面，企业数据中超过80%为非结构化数据，如合同文本、设计图纸、音视频文件等。某制造企业的案例显示，通过结合OCR、语音识别和图像识别技术，可将非结构化数据的分类分级覆盖率从30%提升至85%。多源数据关联分析则需要构建实体解析和关系图谱技术，某公安机关的实践通过图数据库技术，实现了跨系统数据的关联分级。低误报率与漏报率的平衡需要设置动态阈值机制，某保险公司的方案采用ROC曲线确定最优阈值，使综合识别性能提升35%。&lt;/p&gt;    &lt;h3&gt;4.2 格式保留加密（FPE）&lt;/h3&gt;    &lt;p&gt;格式保留加密在数据脱敏中具有独特优势：保持原有数据格式与长度特性使其能够无缝替换生产数据，某银行的核心系统改造案例显示，采用FPE后应用程序无需任何修改即可处理加密数据。支持可逆操作的特点使其适合需要合法解密的场景，如某医疗集团的临床研究数据共享，通过严格的密钥管理实现受控解密。&lt;/p&gt;    &lt;p&gt;FF1算法的实施需要系统化流程：字符集定义需考虑业务需求，如电话号码仅需数字字符集（0-9），而姓名可能需要扩展字符集（包含字母和空格）。Tweak参数的设置需要平衡安全性与便利性，某支付机构将交易流水号作为Tweak，既保证了加密强度又便于检索。密钥管理是核心环节，推荐采用HSM（硬件安全模块）保护主密钥，某政务云的实践显示，使用HSM后密钥泄露风险降低90%。加密/解密操作需要优化性能，某电信运营商通过GPU加速，使FPE处理能力达到每秒万次以上，满足实时业务需求。&lt;/p&gt;    &lt;h2&gt;五、现存挑战与发展趋势&lt;/h2&gt;    &lt;h3&gt;5.1 主要实施难点&lt;/h3&gt;    &lt;p&gt;数据分类分级面临四大核心挑战：      &lt;strong&gt;标准落地难&lt;/strong&gt;表现为行业标准与组织实际的鸿沟，某央企调研显示，直接套用行业标准会导致40%以上的数据无法准确归类。解决方案是建立标准映射机制，如某汽车集团开发的&amp;quot;标准-企业&amp;quot;双向映射表，使标准适用性提升至85%。      &lt;strong&gt;动态维护难&lt;/strong&gt;源于数据的持续变化，某互联网公司的监测显示，其核心业务系统每月产生15%的数据结构变更。创新实践包括变更联动机制，如某银行将分类分级审核嵌入DevOps流程，确保变更同步更新。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;价值体现难&lt;/strong&gt;反映在与安全管控的脱节，某省级政务平台的评估发现，仅30%的分类分级结果被安全策略引用。前沿做法是策略自动生成技术，如某保险公司开发的&amp;quot;分级-策略&amp;quot;联动引擎，自动将分级结果转化为访问控制规则。      &lt;strong&gt;成本控制难&lt;/strong&gt;对依赖第三方系统的机构尤为突出，某市政务服务中心测算，完全梳理其200多个外包系统需投入超千万元。可行路径是分级推进策略，如某医院率先梳理自建系统，外包系统通过合同约束逐步改造。&lt;/p&gt;    &lt;h3&gt;5.2 未来发展方向&lt;/h3&gt;    &lt;p&gt;数据分类分级正朝向四个关键方向演进：      &lt;strong&gt;智能化升级&lt;/strong&gt;方面，NLP技术正被用于处理医疗影像报告等复杂非结构化数据，某医疗AI公司通过深度学习，使影像报告分类准确率达到88%。ML驱动的自动分级调整系统能够学习数据使用模式，如某电商平台的行为数据分级系统，根据访问频率自动调整级别。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;场景化融合&lt;/strong&gt;趋势体现为与业务系统的深度集成，某车企将分类分级引擎嵌入数据网关，实现API调用的实时管控。某银行的&amp;quot;分类-分级-保护&amp;quot;闭环系统，自动阻断不符合分级策略的数据导出操作。&amp;quot;生态化协同&amp;quot;正在形成，某金融行业联盟建立的分类词典已覆盖3000多个数据项，跨机构分级互认使数据共享效率提升60%。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;价值化延伸&lt;/strong&gt;最具革命性，某自贸区将分类分级作为数据资产评估的基础，使数据交易价格形成更加透明。某科技公司开发的精准访问控制系统，基于数据级别动态调整权限，使内部数据利用效率提升40%同时降低泄露风险。这些创新表明，数据分类分级正在从成本中心转变为价值创造引擎。&lt;/p&gt;    &lt;h2&gt;结论与建议&lt;/h2&gt;    &lt;p&gt;数据分类分级不应止步于合规检查项，而应成为组织数据治理的基础设施。建议组织从四个维度系统推进：      &lt;strong&gt;建立动态机制&lt;/strong&gt;需要将分类分级嵌入数据全生命周期，某制造企业的实践显示，在数据创建、存储、使用、共享和销毁各环节设置分类分级检查点，可使数据治理成熟度提升2个等级。      &lt;strong&gt;强化技术赋能&lt;/strong&gt;的关键是采用智能化工具，某省级政务云通过AI分类分级平台，使人工参与量减少70%同时准确率提升15%。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;注重实效验证&lt;/strong&gt;要求建立量化评估体系，某金融机构开发的分类分级成熟度模型，从覆盖度、准确率、策略命中率等8个维度进行季度评估，确保工作实效。      &lt;strong&gt;培养专业团队&lt;/strong&gt;是长效保障，某互联网公司的&amp;quot;数据卫士&amp;quot;计划，通过认证体系培养业务部门的数据识别专家，使业务自主分类准确率达到80%。&lt;/p&gt;    &lt;p&gt;随着数据要素市场化进程加速，      &lt;strong&gt;下一代分类分级体系&lt;/strong&gt;将呈现以下特征：从&amp;quot;合规驱动&amp;quot;转向&amp;quot;价值驱动&amp;quot;，分类分级结果直接服务于数据资产定价和交易；从&amp;quot;静态盘点&amp;quot;转向&amp;quot;实时感知&amp;quot;，通过嵌入式探针实现数据状态的动态监测；从&amp;quot;孤立系统&amp;quot;转向&amp;quot;生态协同&amp;quot;，形成跨组织的数据分类分级互认机制；从&amp;quot;人工主导&amp;quot;转向&amp;quot;人机协同&amp;quot;，AI承担90%的常规分类工作，人类专家聚焦复杂决策。只有回归&amp;quot;识别-管控&amp;quot;一体化的本质，数据分类分级才能真正摆脱&amp;quot;皇帝新衣&amp;quot;的质疑，成为数字经济的安全基石。&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/63017-%E6%95%B0%E6%8D%AE-%E5%88%86%E7%B1%BB-%E5%88%86%E7%BA%A7</guid>
      <pubDate>Mon, 26 May 2025 13:58:16 CST</pubDate>
    </item>
    <item>
      <title>不同数据场景下的聚类算法</title>
      <link>https://itindex.net/detail/63016-%E6%95%B0%E6%8D%AE-%E8%81%9A%E7%B1%BB-%E7%AE%97%E6%B3%95</link>
      <description>&lt;div&gt;    &lt;p&gt;在数据分析和机器学习领域，      &lt;strong&gt;聚类&lt;/strong&gt;是一种非常重要的无监督学习方法，它可以帮助我们发现数据中的内在结构，将相似的数据点分组到一起。&lt;/p&gt;    &lt;p&gt;本文将介绍几种常见的      &lt;strong&gt;聚类&lt;/strong&gt;算法，包括      &lt;strong&gt;原型聚类&lt;/strong&gt;（如 k-均值、学习向量量化、高斯混合聚类）、      &lt;strong&gt;密度聚类&lt;/strong&gt;（DBSCAN）和      &lt;strong&gt;层次聚类&lt;/strong&gt;（AGNES）。&lt;/p&gt;    &lt;p&gt;通过浅显易懂的方式介绍它们的原理，探讨它们的适用场景，并通过代码演示如何使用这些算法。&lt;/p&gt;    &lt;h1&gt;1. 原型聚类：以&amp;quot;中心点&amp;quot;代表群体&lt;/h1&gt;    &lt;h2&gt;1.1. k-均值聚类&lt;/h2&gt;    &lt;p&gt;      &lt;strong&gt;k-均值聚类&lt;/strong&gt;（      &lt;code&gt;K-Means Clustering&lt;/code&gt;）是一种非常直观的聚类方法。&lt;/p&gt;    &lt;p&gt;它的目标是将数据划分为$ k $个簇，每个簇由一个      &lt;strong&gt;“中心点”&lt;/strong&gt;（质心）代表。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;算法的步骤&lt;/strong&gt;如下：&lt;/p&gt;    &lt;ol&gt;      &lt;li&gt;随机选择$ k $个数据点作为        &lt;strong&gt;初始质心&lt;/strong&gt;。&lt;/li&gt;      &lt;li&gt;将每个数据点分配到最近的质心所在的        &lt;strong&gt;簇&lt;/strong&gt;。&lt;/li&gt;      &lt;li&gt;重新计算每个        &lt;strong&gt;簇的质心&lt;/strong&gt;（即簇内所有点的均值）。&lt;/li&gt;      &lt;li&gt;重复上述步骤，直到        &lt;strong&gt;质心&lt;/strong&gt;不再变化或达到预设的迭代次数。&lt;/li&gt;&lt;/ol&gt;    &lt;p&gt;      &lt;strong&gt;k-均值聚类&lt;/strong&gt;适用于数据分布较为均匀且簇形状较为规则的场景。&lt;/p&gt;    &lt;p&gt;例如，对用户群体进行市场细分，或者对图像中的像素进行颜色聚类。&lt;/p&gt;    &lt;p&gt;基于      &lt;code&gt;scikit-learn&lt;/code&gt;的代码示例如下：&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs

# 生成模拟数据
X, _ = make_blobs(n_samples=300, centers=4, random_state=42)

# 使用 KMeans 聚类
kmeans = KMeans(n_clusters=4, random_state=42)
kmeans.fit(X)
labels = kmeans.labels_
centroids = kmeans.cluster_centers_

# 可视化结果
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap=&amp;apos;viridis&amp;apos;)
plt.scatter(centroids[:, 0], centroids[:, 1], s=300, c=&amp;apos;red&amp;apos;, marker=&amp;apos;X&amp;apos;)
plt.title(&amp;quot;K-Means 聚类&amp;quot;)
plt.show()&lt;/code&gt;&lt;/pre&gt;    &lt;p&gt;      &lt;img alt="" src="https://img2024.cnblogs.com/blog/83005/202505/83005-20250526110200161-497095147.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;h2&gt;1.2. 学习向量量化&lt;/h2&gt;    &lt;p&gt;      &lt;code&gt;LVQ&lt;/code&gt;（      &lt;code&gt;Learning Vector Quantization&lt;/code&gt;） 是一种受神经网络启发的聚类方法。&lt;/p&gt;    &lt;p&gt;它使用一组      &lt;strong&gt;“原型向量”&lt;/strong&gt;来代表每个簇，算法通过迭代调整这些原型向量的位置，使其更接近属于该簇的数据点，远离其他簇的数据点。&lt;/p&gt;    &lt;p&gt;      &lt;code&gt;LVQ&lt;/code&gt;的      &lt;strong&gt;核心思想&lt;/strong&gt;是通过学习来优化原型向量的位置。&lt;/p&gt;    &lt;p&gt;      &lt;code&gt;LVQ&lt;/code&gt;适用于数据点分布较为密集且簇边界较为清晰的场景，它在      &lt;strong&gt;图像识别&lt;/strong&gt;和      &lt;strong&gt;模式分类&lt;/strong&gt;中表现良好。&lt;/p&gt;    &lt;p&gt;虽然      &lt;code&gt;scikit-learn&lt;/code&gt;没有直接提供      &lt;code&gt;LVQ&lt;/code&gt;的实现，但我们可以使用      &lt;code&gt;sklvq&lt;/code&gt;库来实现。&lt;/p&gt;    &lt;p&gt;安装方式：      &lt;code&gt;pip install sklvq&lt;/code&gt;&lt;/p&gt;    &lt;p&gt;代码示例如下：&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;from sklvq import GLVQ  # 使用 GLVQ（Generalized Learning Vector Quantization）
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt

# 生成模拟数据
X, y = make_blobs(n_samples=300, centers=4, random_state=42)

# 使用 GLVQ 聚类
glvq = GLVQ(random_state=42)
glvq.fit(X, y)

# 获取聚类结果
labels = glvq.predict(X)

# 获取中心点（原型向量）
prototypes = glvq.prototypes_

# 可视化结果
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap=&amp;quot;viridis&amp;quot;)
plt.scatter(
    prototypes[:, 0], prototypes[:, 1], s=300, c=&amp;quot;red&amp;quot;, marker=&amp;quot;X&amp;quot;, label=&amp;quot;Prototypes&amp;quot;
)
plt.title(&amp;quot;广义学习向量量化 (GLVQ)&amp;quot;)
plt.show()&lt;/code&gt;&lt;/pre&gt;    &lt;p&gt;      &lt;img alt="" src="https://img2024.cnblogs.com/blog/83005/202505/83005-20250526110200169-447423170.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;h2&gt;1.3. 高斯混合聚类&lt;/h2&gt;    &lt;p&gt;      &lt;strong&gt;高斯混合聚类&lt;/strong&gt;（      &lt;code&gt;Gaussian Mixture Clustering&lt;/code&gt;）假设数据是由多个高斯分布的混合生成的。&lt;/p&gt;    &lt;p&gt;每个高斯分布代表一个      &lt;strong&gt;簇&lt;/strong&gt;，算法通过估计每个高斯分布的      &lt;strong&gt;参数&lt;/strong&gt;（      &lt;strong&gt;均值&lt;/strong&gt;、      &lt;strong&gt;协方差矩阵&lt;/strong&gt;和      &lt;strong&gt;权重&lt;/strong&gt;）来确定簇的形状和位置。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;高斯混合聚类&lt;/strong&gt;比** k-均值**更灵活，因为它可以捕捉到簇的形状和大小的变化。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;高斯混合聚类&lt;/strong&gt;适用于簇形状不规则或数据分布较为复杂的情况。&lt;/p&gt;    &lt;p&gt;例如，对金融数据中的异常交易进行聚类分析。&lt;/p&gt;    &lt;p&gt;代码示例如下：&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;from sklearn.mixture import GaussianMixture
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt

# 生成模拟数据
X, _ = make_blobs(n_samples=300, centers=4, random_state=42)

# 使用高斯混合聚类
gmm = GaussianMixture(n_components=4, random_state=42)
gmm.fit(X)
labels = gmm.predict(X)

# 可视化结果
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap=&amp;apos;viridis&amp;apos;)
plt.title(&amp;quot;高斯混合聚类&amp;quot;)
plt.show()&lt;/code&gt;&lt;/pre&gt;    &lt;p&gt;      &lt;img alt="" src="https://img2024.cnblogs.com/blog/83005/202505/83005-20250526110200166-1296609979.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;h1&gt;2. 密度聚类：发现任意形状的簇&lt;/h1&gt;    &lt;p&gt;      &lt;code&gt;DBSCAN&lt;/code&gt;（      &lt;code&gt;Density-Based Spatial Clustering of Applications with Noise&lt;/code&gt;）是一种基于密度的聚类算法。&lt;/p&gt;    &lt;p&gt;它的      &lt;strong&gt;核心思想&lt;/strong&gt;是：如果一个点的邻域内有足够的点（即密度足够高），那么这些点可以被划分为同一个簇。&lt;/p&gt;    &lt;p&gt;DBSCAN 使用两个参数：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;code&gt;eps&lt;/code&gt;：邻域半径，用于定义        &lt;strong&gt;“足够近”&lt;/strong&gt;的范围。&lt;/li&gt;      &lt;li&gt;        &lt;code&gt;min_samples&lt;/code&gt;：核心点的邻域内必须包含的最小点数。&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;code&gt;DBSCAN&lt;/code&gt;的优点是可以发现任意形状的簇，并且能够识别噪声点。&lt;/p&gt;    &lt;p&gt;      &lt;code&gt;DBSCAN&lt;/code&gt;适用于数据分布不均匀、簇形状复杂且存在噪声的场景。&lt;/p&gt;    &lt;p&gt;例如，对地理数据中的热点区域进行分析。&lt;/p&gt;    &lt;p&gt;代码示例如下：&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;from sklearn.cluster import DBSCAN
from sklearn.datasets import make_moons
import matplotlib.pyplot as plt

# 生成模拟数据
X, _ = make_moons(n_samples=300, noise=0.05, random_state=42)

# 使用 DBSCAN 聚类
dbscan = DBSCAN(eps=0.2, min_samples=5)
labels = dbscan.fit_predict(X)

# 可视化结果
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap=&amp;apos;viridis&amp;apos;)
plt.title(&amp;quot;DBSCAN 聚类&amp;quot;)
plt.show()&lt;/code&gt;&lt;/pre&gt;    &lt;p&gt;      &lt;img alt="" src="https://img2024.cnblogs.com/blog/83005/202505/83005-20250526110200159-1204097238.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;h1&gt;3. 层次聚类：构建数据家族树&lt;/h1&gt;    &lt;p&gt;      &lt;code&gt;AGNES&lt;/code&gt;（      &lt;code&gt;Agglomerative Nesting&lt;/code&gt;）是一种自底向上的层次聚类算法。&lt;/p&gt;    &lt;p&gt;它从每个数据点作为一个单独的簇开始，然后逐步合并距离最近的簇，直到达到预设的簇数量或满足其他停止条件。&lt;/p&gt;    &lt;p&gt;      &lt;code&gt;AGNES&lt;/code&gt;的关键在于如何定义簇之间的距离，常见的方法包括      &lt;strong&gt;单链接法&lt;/strong&gt;、      &lt;strong&gt;全链接法&lt;/strong&gt;和      &lt;strong&gt;平均链接法&lt;/strong&gt;。&lt;/p&gt;    &lt;p&gt;      &lt;code&gt;AGNES&lt;/code&gt;适用于需要逐步分析数据层次结构的场景，例如生物分类学或文档聚类。&lt;/p&gt;    &lt;p&gt;代码示例如下：&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;from sklearn.cluster import AgglomerativeClustering
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt

# 生成模拟数据
X, _ = make_blobs(n_samples=300, centers=4, random_state=42)

# 使用 AGNES 聚类
agnes = AgglomerativeClustering(n_clusters=4)
labels = agnes.fit_predict(X)

# 可视化结果
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap=&amp;apos;viridis&amp;apos;)
plt.title(&amp;quot;AGNES 聚类&amp;quot;)
plt.show()&lt;/code&gt;&lt;/pre&gt;    &lt;p&gt;      &lt;img alt="" src="https://img2024.cnblogs.com/blog/83005/202505/83005-20250526110200167-831300534.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;h1&gt;4. 聚类算法对比&lt;/h1&gt;    &lt;p&gt;常用的几种聚类算法的对比如下：&lt;/p&gt;    &lt;table&gt;      &lt;tr&gt;        &lt;th&gt;算法类型&lt;/th&gt;        &lt;th&gt;优点&lt;/th&gt;        &lt;th&gt;局限性&lt;/th&gt;        &lt;th&gt;典型应用场景&lt;/th&gt;&lt;/tr&gt;      &lt;tr&gt;        &lt;td&gt;K-Means&lt;/td&gt;        &lt;td&gt;计算效率高&lt;/td&gt;        &lt;td&gt;需预设K值&lt;/td&gt;        &lt;td&gt;客户分群、图像压缩&lt;/td&gt;&lt;/tr&gt;      &lt;tr&gt;        &lt;td&gt;GMM&lt;/td&gt;        &lt;td&gt;处理椭圆分布&lt;/td&gt;        &lt;td&gt;计算复杂度较高&lt;/td&gt;        &lt;td&gt;异常检测、语音识别&lt;/td&gt;&lt;/tr&gt;      &lt;tr&gt;        &lt;td&gt;DBSCAN&lt;/td&gt;        &lt;td&gt;发现任意形状&lt;/td&gt;        &lt;td&gt;参数敏感&lt;/td&gt;        &lt;td&gt;地理数据、离群点检测&lt;/td&gt;&lt;/tr&gt;      &lt;tr&gt;        &lt;td&gt;AGNES&lt;/td&gt;        &lt;td&gt;可视化层次结构&lt;/td&gt;        &lt;td&gt;计算复杂度O(n³)&lt;/td&gt;        &lt;td&gt;生物分类、文档聚类&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;    &lt;h1&gt;5. 总结&lt;/h1&gt;    &lt;p&gt;      &lt;strong&gt;聚类算法&lt;/strong&gt;的选择取决于数据的特性、问题的需求以及对结果的解释性要求。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;k-均值&lt;/strong&gt;简单高效，但对簇形状有较强假设；      &lt;code&gt;DBSCAN&lt;/code&gt;能够处理复杂形状和噪声；      &lt;strong&gt;层次聚类&lt;/strong&gt;则提供了数据的层次结构。&lt;/p&gt;    &lt;p&gt;在实际应用中，我们通常需要尝试多种算法，并根据具体问题选择最适合的聚类方法。&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/63016-%E6%95%B0%E6%8D%AE-%E8%81%9A%E7%B1%BB-%E7%AE%97%E6%B3%95</guid>
      <pubDate>Mon, 26 May 2025 13:57:48 CST</pubDate>
    </item>
    <item>
      <title>数据库的未来：PostgreSQL？</title>
      <link>https://itindex.net/detail/63001-%E6%95%B0%E6%8D%AE%E5%BA%93-%E6%9C%AA%E6%9D%A5-postgresql</link>
      <description>&lt;h2&gt;进击中的PostgreSQL&lt;/h2&gt;
 &lt;p&gt;PostgreSQL 被称为 “最具吞噬力的数据库” 或 “数据库领域的瑞士军刀”，这种说法源于其独特的开源生态、持续进化的技术能力和广泛的应用场景。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="1604" src="http://www.biaodianfu.com/wp-content/uploads/2025/04/postgre.jpg" width="1603"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;我们可以从以下几个角度理解这一观点：&lt;/p&gt;
 &lt;h3&gt;技术包容性：吞噬多种数据模型&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;关系型+NoSQL融合&lt;/strong&gt;：支持 JSONB（二进制 JSON）、XML、HStore 等非结构化数据类型，实现文档存储能力（对标 MongoDB）&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;时序数据库扩展&lt;/strong&gt;：通过 TimescaleDB 插件支持时序数据处理（对标 InfluxDB）&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;图数据库能力&lt;/strong&gt;：Apache AGE 扩展使其具备属性图查询功能（对标 Neo4j）&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;空间数据处理&lt;/strong&gt;：PostGIS 扩展提供 GIS 支持（超越 Oracle Spatial）&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;向量搜索&lt;/strong&gt;：pgvector 插件支持 AI 时代的向量嵌入检索（对标专用向量数据库）&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;架构吞噬：颠覆传统技术栈&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;分布式能力&lt;/strong&gt;：Citus 扩展实现水平分片，支持分布式事务（挑战 CockroachDB）&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;列式存储&lt;/strong&gt;：通过扩展支持列式存储优化分析场景（与 Snowflake 竞争）&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;流处理&lt;/strong&gt;：PipelineDB（已合并到核心）和 pg_stream 支持实时流处理（对标 Kafka + Flink）&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;开发范式革命&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;存储过程语言&lt;/strong&gt;：支持 12 种编程语言（包括 Python、JavaScript、R），突破传统 SQL 限制&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;函数式编程&lt;/strong&gt;：WITH RECURSIVE 实现递归查询，支持图遍历算法&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;型系统&lt;/strong&gt;：允许自定义复杂数据类型，突破关系型数据库的刚性约束&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;开源生态的病毒式扩张&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;扩展机制&lt;/strong&gt;：超过 1,200 个开源扩展形成技术护城河（如 PostGIS 下载量超 1 亿次）&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;云原生适配&lt;/strong&gt;：AWS RDS/Aurora、Azure Database 等主流云平台深度优化&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;企业级功能开源化&lt;/strong&gt;：逻辑复制、并行查询等传统商业数据库功能免费开放&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;经济模型颠覆&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;零许可成本&lt;/strong&gt;：相比 Oracle 每核5 万美元的授权费，节省 90% 以上成本&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;多云战略支撑&lt;/strong&gt;：避免云厂商锁定（如 MongoDB 曾与 AWS 爆发协议战争）&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;开发者心智占领&lt;/strong&gt;：StackOverflow 2023 调查显示 46% 开发者首选 PostgreSQL&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;典型技术替代案例&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;MongoDB 替代&lt;/strong&gt;：美国联邦政府将 200TB 的文档系统迁移至 PostgreSQL&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;Oracle 替代&lt;/strong&gt;：西班牙银行 BBVA 迁移 800+ 实例，事务处理性能提升 30%&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;Elasticsearch 替代&lt;/strong&gt;：Zalando 使用全文检索扩展替代 40% 的 ES 集群&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;Kafka 替代&lt;/strong&gt;：某车联网企业用 pg_stream 处理 50 万条/秒的车辆数据&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;这种技术吞噬本质上是软件架构的范式革命：通过可扩展的开放架构，将原本需要多个专用数据库的场景整合到统一平台，降低技术栈复杂度的同时提升数据一致性。随着 FDW（外部数据封装器）等技术的成熟，PostgreSQL 正在演变为真正的「数据库超融合平台」。不过这种「吞噬」并非绝对替代，而是推动整个数据库行业向更开放、更融合的方向进化。&lt;/p&gt;
 &lt;h2&gt;PostgreSQL的可扩展性&lt;/h2&gt;
 &lt;p&gt;  &lt;strong&gt;PostgreSQL 不仅仅是一个数据库，更是一个强大的数据管理平台，它的核心竞争力在于其卓越的可扩展性，这使得它在数据库领域独树一帜。&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;传统的数据库通常只负责存储和管理数据。但 PostgreSQL 不同，它提供了一整套完善的基础设施，例如事务处理（ACID 特性）、数据恢复、备份、高可用性、访问控制等等。这些基础设施就像一个操作系统的内核，为各种应用程序（在这里就是 PostgreSQL 的扩展）提供了运行的基础。因此，与其说 PostgreSQL 是一个数据库，不如说它是一个数据管理“框架”或“平台”。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="513" src="http://www.biaodianfu.com/wp-content/uploads/2025/04/PostgreSQL.png" width="1050"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;PostgreSQL 的可扩展性是其核心竞争力的关键所在，这种扩展性不仅体现在功能层面，更深入到架构设计的基因中。要系统理解其可扩展性，可以从以下七个层面进行剖析：&lt;/p&gt;
 &lt;h3&gt;内核架构的可扩展性设计&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;模块化存储引擎&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;堆表引擎（HEAP）与索引访问方法（Access Method）分离，允许开发自定义存储结构&lt;/li&gt;
    &lt;li&gt;示例：ZHeap 引擎实现多版本并发控制（MVCC）的替代方案&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;可插拔事务管理器&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;支持自定义两阶段提交协议，为分布式事务奠定基础&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;扩展性接口标准&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;提供 50+ 标准扩展接口（如 WAL 日志接口、索引访问方法接口）&lt;/li&gt;
    &lt;li&gt;技术指标：CREATE ACCESS METHOD 支持创建新型索引（如 pg_roaringbitmap）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;多维度数据模型扩展&lt;/h3&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;扩展类型&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;实现方式&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;典型场景&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;JSONB 文档存储&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;原生 JSONB 类型 + GIN 索引&lt;/td&gt;
   &lt;td&gt;替代 MongoDB 文档存储&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;时序数据&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;TimescaleDB 超表结构&lt;/td&gt;
   &lt;td&gt;替代 InfluxDB 时序处理&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;图数据&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;Apache AGE 扩展&lt;/td&gt;
   &lt;td&gt;替代 Neo4j 图遍历&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;空间数据&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;PostGIS 空间运算引擎&lt;/td&gt;
   &lt;td&gt;超越 Oracle Spatial&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;向量检索&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;pgvector HNSW 索引&lt;/td&gt;
   &lt;td&gt;替代专用向量数据库&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;h3&gt;计算能力的弹性扩展&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;垂直扩展&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;并行查询（Parallel Query）支持 64 核 CPU 的线程级并行&lt;/li&gt;
    &lt;li&gt;JIT 编译加速复杂查询（TPC-H 性能提升 40%）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;水平扩展&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;Citus 分片集群支持 PB 级数据处理&lt;/li&gt;
    &lt;li&gt;逻辑复制 + 物理复制混合架构实现读写分离&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;异构计算&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;GPU 加速插件（pg_strom）实现 100x 的矩阵运算加速&lt;/li&gt;
    &lt;li&gt;FPGA 硬件加速支持（实验性功能）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;存储引擎的可编程性&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;表分区策略&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;支持范围/列表/哈希/复合分区，单表可拆分为 10,000+ 子表&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;存储格式创新&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;列式存储扩展（cstore_fdw）实现 5x 压缩率&lt;/li&gt;
    &lt;li&gt;内存表引擎（pgmemcache）支持亚毫秒级响应&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;混合存储管理&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;热冷数据分层（Tiered Storage）通过表空间实现自动迁移&lt;/li&gt;
    &lt;li&gt;云原生存储对接（支持 S3 外部表访问）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;协议与接口扩展&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;多协议接入&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;原生支持 SQL:2016 标准 + 扩展语法&lt;/li&gt;
    &lt;li&gt;GraphQL 接口（PostGraphile）直接暴露数据库为 API&lt;/li&gt;
    &lt;li&gt;gRPC 协议支持（实验性 pg_grpc 扩展）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;流式处理接口&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;逻辑解码（Logical Decoding）实现 CDC 数据流捕获&lt;/li&gt;
    &lt;li&gt;pg_stream 扩展支持 Kafka 式消息队列功能&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;外部数据融合&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;外部数据包装器（FDW）支持连接 30+ 种数据源&lt;/li&gt;
    &lt;li&gt;典型案例：MySQL FDW 实现跨库联合查询&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;开发者生态扩展&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;多语言支持矩阵&lt;/strong&gt;&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;语言&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;执行环境&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;性能等级&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;PL/pgSQL&lt;/td&gt;
   &lt;td&gt;原生解释执行&lt;/td&gt;
   &lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;PL/Python&lt;/td&gt;
   &lt;td&gt;Python 3.11 沙箱环境&lt;/td&gt;
   &lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;PL/Rust&lt;/td&gt;
   &lt;td&gt;WebAssembly 运行时&lt;/td&gt;
   &lt;td&gt;★★★★☆&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;PL/Java&lt;/td&gt;
   &lt;td&gt;JVM 集成&lt;/td&gt;
   &lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;PL/V8&lt;/td&gt;
   &lt;td&gt;JavaScript 执行引擎&lt;/td&gt;
   &lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;  &lt;strong&gt;开发工具链扩展&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;pgAdmin 可视化工具支持 ER 建模&lt;/li&gt;
  &lt;li&gt;pgrx 框架实现 Rust 扩展开发&lt;/li&gt;
  &lt;li&gt;自动迁移工具（ora2pg）实现 Oracle 到 PG 的无缝迁移&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;可观测性与治理扩展&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;监控体系&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;pg_stat_statements 记录 95% 的 SQL 执行细节&lt;/li&gt;
    &lt;li&gt;Prometheus 输出接口（pg_exporter）实现实时监控&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;安全扩展&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;数据脱敏插件（pg_masks）满足 GDPR 合规要求&lt;/li&gt;
    &lt;li&gt;字段级加密（pgcrypto）支持国密算法&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;自治能力&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;自动索引推荐（hypopg）降低 70% DBA 工作量&lt;/li&gt;
    &lt;li&gt;自动参数调优（pg_tune）实现配置智能化&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;可扩展性技术图谱&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="" height="616" src="http://www.biaodianfu.com/wp-content/uploads/2025/04/extends.png" width="1525"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;PostgreSQL 的可扩展性本质上是将数据库从「封闭系统」转变为「可编程数据平台」。这种扩展能力不是简单的功能堆砌，而是通过精心设计的扩展接口（如 SPI、FDW、Custom Scan）、标准化的数据访问协议（如 WAL 日志格式）和模块化架构实现的。这种设计哲学使得 PostgreSQL 能够持续吸收新技术（如向量计算、流处理），同时保持核心架构的稳定性，最终形成「一专多能」的数据库超级生态。&lt;/p&gt;
 &lt;h2&gt;PostgreSQL的常用扩展&lt;/h2&gt;
 &lt;p&gt;以下是按功能类型梳理的 PostgreSQL 常用扩展分类，包含技术特性和典型应用场景：&lt;/p&gt;
 &lt;h3&gt;数据模型扩展&lt;/h3&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;扩展名称&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;核心功能&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;技术亮点&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;典型场景&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;PostGIS&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;地理空间数据处理&lt;/td&gt;
   &lt;td&gt;支持 3,000+ GIS 函数，OGC 标准兼容&lt;/td&gt;
   &lt;td&gt;地图服务、物流轨迹分析&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;TimescaleDB&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;时序数据处理&lt;/td&gt;
   &lt;td&gt;自动分块（chunk）管理，压缩率 20x&lt;/td&gt;
   &lt;td&gt;IoT 传感器、监控系统&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;Apache AGE&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;图数据库功能&lt;/td&gt;
   &lt;td&gt;支持 Cypher 查询，每秒 10 万边遍历&lt;/td&gt;
   &lt;td&gt;社交网络、推荐系统&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pgvector&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;向量相似度搜索&lt;/td&gt;
   &lt;td&gt;HNSW 索引实现 99% 召回率&lt;/td&gt;
   &lt;td&gt;AI 嵌入检索、语义搜索&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;hstore&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;键值对存储&lt;/td&gt;
   &lt;td&gt;原生支持 JSON 前的键值方案&lt;/td&gt;
   &lt;td&gt;动态字段配置&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;PostgreSQL 的数据模型扩展能力是其最突出的特性之一，通过扩展模块实现  &lt;strong&gt;多模态数据存储与处理的统一平台&lt;/strong&gt;。&lt;/p&gt;
 &lt;h4&gt;扩展架构原理&lt;/h4&gt;
 &lt;p&gt;PostgreSQL 通过   &lt;strong&gt;TOAST 存储机制&lt;/strong&gt; 和   &lt;strong&gt;可扩展类型系统&lt;/strong&gt; 实现数据模型扩展：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;TOAST (The Oversized-Attribute Storage Technique)&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;自动处理超过 8KB 的大字段数据（如 GIS 几何体、文档）&lt;/li&gt;
    &lt;li&gt;支持压缩（LZ算法）和分块存储&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;自定义类型系统&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;pre&gt;CREATE TYPE complex AS (r float8, i float8);  -- 创建复数类型
CREATE FUNCTION complex_add(complex, complex) ... -- 定义运算符
&lt;/pre&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;索引扩展接口&lt;/strong&gt;
   &lt;ul&gt;
    &lt;li&gt;支持创建 GIN/GiST/SP-GiST 等索引结构&lt;/li&gt;
    &lt;li&gt;例如 PostGIS 的 R-Tree 空间索引&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;核心数据模型扩展&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;空间数据模型 – PostGIS&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;技术实现：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;添加 3000+ 空间函数（ST_* 前缀）&lt;/li&gt;
  &lt;li&gt;支持 WKT/WKB/GeoJSON 格式&lt;/li&gt;
  &lt;li&gt;空间索引：GiST 加速查询&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;性能对比：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;操作&lt;/td&gt;
   &lt;td&gt;PostGIS (ms)&lt;/td&gt;
   &lt;td&gt;MongoDB (ms)&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;500万点数据范围查询&lt;/td&gt;
   &lt;td&gt;120&lt;/td&gt;
   &lt;td&gt;450&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;地理围栏判断&lt;/td&gt;
   &lt;td&gt;85&lt;/td&gt;
   &lt;td&gt;220&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;使用示例：&lt;/p&gt;
 &lt;pre&gt;-- 创建空间表
CREATE TABLE cities (
    name text,
    geom geometry(Point, 4326)
);

-- 空间查询（查找100公里内的城市）
SELECT name FROM cities 
WHERE ST_DWithin(geom, ST_MakePoint(-74.006,40.7128), 100000);
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;时序数据模型 – TimescaleDB&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;架构创新：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Hypertable 自动分块管理&lt;/li&gt;
  &lt;li&gt;时间维度分区 + 空间维度分片&lt;/li&gt;
  &lt;li&gt;压缩算法：Gorilla (浮点数) / Delta-of-Delta (整型)&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;性能优化：&lt;/p&gt;
 &lt;pre&gt;-- 创建超表
SELECT create_hypertable(&amp;apos;sensor_data&amp;apos;, &amp;apos;ts&amp;apos;);

-- 启用压缩
ALTER TABLE sensor_data SET (
    timescaledb.compress,
    timescaledb.compress_orderby = &amp;apos;ts DESC&amp;apos;
);
&lt;/pre&gt;
 &lt;p&gt;资源消耗对比：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;数据量&lt;/td&gt;
   &lt;td&gt;原生PG存储&lt;/td&gt;
   &lt;td&gt;Timescale存储&lt;/td&gt;
   &lt;td&gt;压缩率&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;1TB时序&lt;/td&gt;
   &lt;td&gt;1.2TB&lt;/td&gt;
   &lt;td&gt;230GB&lt;/td&gt;
   &lt;td&gt;5.2x&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;  &lt;strong&gt;图数据模型 – Apache AGE&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;技术特性：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;支持 Cypher 查询语言&lt;/li&gt;
  &lt;li&gt;属性图模型存储（顶点+边）&lt;/li&gt;
  &lt;li&gt;内置 图遍历算法 (BFS/DFS/最短路径)&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;性能测试：&lt;/p&gt;
 &lt;pre&gt;-- 查找朋友的朋友
MATCH (u:User)-[:FRIEND]-&amp;gt;(f)-[:FRIEND]-&amp;gt;(fof)
WHERE u.name = &amp;apos;Alice&amp;apos;
RETURN fof.name
&lt;/pre&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;节点规模&lt;/td&gt;
   &lt;td&gt;遍历深度&lt;/td&gt;
   &lt;td&gt;AGE响应时间&lt;/td&gt;
   &lt;td&gt;Neo4j响应时间&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;100万&lt;/td&gt;
   &lt;td&gt;3&lt;/td&gt;
   &lt;td&gt;320ms&lt;/td&gt;
   &lt;td&gt;280ms&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;1000万&lt;/td&gt;
   &lt;td&gt;3&lt;/td&gt;
   &lt;td&gt;1.2s&lt;/td&gt;
   &lt;td&gt;0.9s&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;  &lt;strong&gt;向量数据模型 – pgvector&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;核心能力：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;支持 HNSW 和 IVFFlat 索引&lt;/li&gt;
  &lt;li&gt;相似度算法：余弦/欧氏距离&lt;/li&gt;
  &lt;li&gt;支持 FP16 量化压缩&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;AI场景示例：&lt;/p&gt;
 &lt;pre&gt;-- 创建向量表
CREATE TABLE embeddings (
    id bigserial PRIMARY KEY,
    vector vector(1536)  -- OpenAI 嵌入维度
);

-- HNSW索引
CREATE INDEX ON embeddings USING hnsw (vector vector_cosine_ops);

-- 相似度搜索
SELECT id, vector &amp;lt;=&amp;gt; &amp;apos;[0.12, 0.23,...]&amp;apos; as distance 
FROM embeddings
ORDER BY vector &amp;lt;=&amp;gt; &amp;apos;[0.12, 0.23,...]&amp;apos; 
LIMIT 10;
&lt;/pre&gt;
 &lt;p&gt;性能指标：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;数据集&lt;/td&gt;
   &lt;td&gt;索引类型&lt;/td&gt;
   &lt;td&gt;搜索速度 (QPS)&lt;/td&gt;
   &lt;td&gt;召回率&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;100万条768维&lt;/td&gt;
   &lt;td&gt;HNSW&lt;/td&gt;
   &lt;td&gt;850&lt;/td&gt;
   &lt;td&gt;99%&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;1亿条1536维&lt;/td&gt;
   &lt;td&gt;IVFFlat&lt;/td&gt;
   &lt;td&gt;1,200&lt;/td&gt;
   &lt;td&gt;95%&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;  &lt;strong&gt;文档数据模型 – JSONB&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;技术优势：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;二进制存储格式（比 MongoDB BSON 小 30%）&lt;/li&gt;
  &lt;li&gt;GIN 索引支持多级路径查询&lt;/li&gt;
  &lt;li&gt;支持 JSON Schema 校验&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;对比测试：&lt;/p&gt;
 &lt;pre&gt;-- 创建文档表
CREATE TABLE products (
    id serial PRIMARY KEY,
    doc jsonb
);

-- 多条件查询
SELECT doc-&amp;gt;&amp;gt;&amp;apos;name&amp;apos; 
FROM products
WHERE doc @&amp;gt; &amp;apos;{&amp;quot;category&amp;quot;: &amp;quot;electronics&amp;quot;, &amp;quot;price&amp;quot;: {&amp;quot;$gt&amp;quot;: 500}}&amp;apos;;
&lt;/pre&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;操作&lt;/td&gt;
   &lt;td&gt;JSONB (ms)&lt;/td&gt;
   &lt;td&gt;MongoDB (ms)&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;插入10万文档&lt;/td&gt;
   &lt;td&gt;4200&lt;/td&gt;
   &lt;td&gt;3800&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;多字段条件查询&lt;/td&gt;
   &lt;td&gt;85&lt;/td&gt;
   &lt;td&gt;120&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;h4&gt;多模型协同应用&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;物流轨迹分析案例&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;-- 时空 + 时序 + JSONB 联合查询
SELECT 
    ST_AsGeoJSON(track.geom) AS path,
    telemetry-&amp;gt;&amp;gt;&amp;apos;speed&amp;apos; AS speed,
    time_bucket(&amp;apos;1 hour&amp;apos;, ts) AS hour
FROM vehicle_tracks track
JOIN vehicle_telemetry telemetry 
  ON track.vehicle_id = telemetry.vehicle_id
WHERE 
    ST_Within(track.geom, city_area) AND
    telemetry-&amp;gt;&amp;gt;&amp;apos;status&amp;apos; = &amp;apos;moving&amp;apos; AND
    ts BETWEEN &amp;apos;2023-08-01&amp;apos; AND &amp;apos;2023-08-07&amp;apos;
GROUP BY hour;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;技术栈组合&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;PostGIS 处理轨迹地理围栏&lt;/li&gt;
  &lt;li&gt;TimescaleDB 管理时间序列聚合&lt;/li&gt;
  &lt;li&gt;JSONB 存储车辆传感器数据&lt;/li&gt;
  &lt;li&gt;pgvector 实现相似轨迹分析&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;扩展管理建议&lt;/h4&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;版本兼容性检查&lt;/strong&gt;：&lt;/li&gt;
&lt;/ul&gt;
 &lt;pre&gt;SELECT * FROM pg_available_extension_versions 
WHERE name = &amp;apos;postgis&amp;apos;;
&lt;/pre&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;存储规划&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;TOAST 字段单独表空间隔离&lt;/li&gt;
    &lt;li&gt;向量/时空数据使用 SSD 存储&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;索引优化&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;对 JSONB 字段创建 GIN 索引&lt;/li&gt;
    &lt;li&gt;时序数据采用 BRIN 索引&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;资源隔离&lt;/strong&gt;：&lt;/li&gt;
&lt;/ul&gt;
 &lt;pre&gt;ALTER DATABASE analytics SET work_mem = &amp;apos;128MB&amp;apos;;  -- 向量计算专用&lt;/pre&gt;
 &lt;h4&gt;优势总结&lt;/h4&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;模型融合能力&lt;/strong&gt;：单数据库内同时处理关系型+文档+图+时空数据&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;计算下推优化&lt;/strong&gt;：通过扩展在存储层实现专用算法（如 GIS 空间关系计算）&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;避免数据孤岛&lt;/strong&gt;：跨模型 JOIN 操作无需 ETL&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;统一事务保证&lt;/strong&gt;：多模型操作保持 ACID 特性&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;通过数据模型扩展，PostgreSQL 在保持 SQL 兼容性的同时，逐步实现了对   &lt;strong&gt;OLTP+OLAP+HTAP&lt;/strong&gt; 全场景的覆盖。建议开发者在设计数据架构时优先评估 PostgreSQL 扩展生态，而非直接采用多数据库方案。&lt;/p&gt;
 &lt;h3&gt;性能优化扩展&lt;/h3&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;扩展名称&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;优化领域&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;技术指标&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;适用场景&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pg_partman&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;自动分区管理&lt;/td&gt;
   &lt;td&gt;支持亿级表自动分区维护&lt;/td&gt;
   &lt;td&gt;时序数据归档&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pg_repack&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;在线表重组&lt;/td&gt;
   &lt;td&gt;消除表膨胀而不阻塞写入&lt;/td&gt;
   &lt;td&gt;OLTP 系统维护&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pg_stat_statements&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;SQL 性能分析&lt;/td&gt;
   &lt;td&gt;捕获 95% 的慢查询&lt;/td&gt;
   &lt;td&gt;性能调优&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pg_prewarm&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;缓存预热&lt;/td&gt;
   &lt;td&gt;冷启动时加载热数据到共享缓存&lt;/td&gt;
   &lt;td&gt;高可用切换后加速&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;citus&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;分布式计算&lt;/td&gt;
   &lt;td&gt;线性扩展至 100+ 节点&lt;/td&gt;
   &lt;td&gt;SaaS 多租户系统&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;PostgreSQL 的性能优化扩展体系覆盖了从存储层到查询层的全栈优化能力，以下是按技术领域分类的深度解析：&lt;/p&gt;
 &lt;h4&gt;查询执行优化扩展&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;pg_hint_plan&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;核心功能：通过 SQL 注释强制指定执行计划&lt;/p&gt;
 &lt;pre&gt;/*+ IndexScan(products idx_product_name) */ 
SELECT * FROM products WHERE name LIKE &amp;apos;A%&amp;apos;;
&lt;/pre&gt;
 &lt;p&gt;优化场景：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;统计信息不准导致错误选择索引&lt;/li&gt;
  &lt;li&gt;临时规避未优化的 JOIN 顺序&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;性能提升：某电商平台订单查询从 2.3s → 120ms&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;pg_qualstats&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;技术原理：记录 WHERE 子句中的谓词使用频率&lt;/p&gt;
 &lt;pre&gt;SELECT * FROM pg_qualstats 
WHERE predicate LIKE &amp;apos;%user_id%&amp;apos;;
&lt;/pre&gt;
 &lt;p&gt;输出示例：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;左表达式&lt;/td&gt;
   &lt;td&gt;右表达式&lt;/td&gt;
   &lt;td&gt;出现次数&lt;/td&gt;
   &lt;td&gt;选择性&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;user_id&lt;/td&gt;
   &lt;td&gt;12345&lt;/td&gt;
   &lt;td&gt;12000&lt;/td&gt;
   &lt;td&gt;0.01%&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;优化建议：对高频率低选择性的列创建 BRIN 索引&lt;/p&gt;
 &lt;h4&gt;存储优化扩展&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;pg_repack&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;技术实现：在线重建表消除碎片，相比 VACUUM FULL 的优势：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;不阻塞 DML 操作&lt;/li&gt;
  &lt;li&gt;支持并行处理&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;操作流程：&lt;/p&gt;
 &lt;pre&gt;pg_repack -d mydb --table orders --jobs 4&lt;/pre&gt;
 &lt;p&gt;性能对比：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;表大小&lt;/td&gt;
   &lt;td&gt;VACUUM FULL 时间&lt;/td&gt;
   &lt;td&gt;pg_repack 时间&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;500GB&lt;/td&gt;
   &lt;td&gt;6h&lt;/td&gt;
   &lt;td&gt;2h&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;  &lt;strong&gt;pg_partman&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;核心特性：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;自动维护时间/范围分区&lt;/li&gt;
  &lt;li&gt;支持级联继承分区&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;配置示例：&lt;/p&gt;
 &lt;pre&gt;-- 创建每小时分区
SELECT partman.create_parent(
    &amp;apos;public.logs&amp;apos;, 
    &amp;apos;log_time&amp;apos;, 
    &amp;apos;native&amp;apos;, 
    &amp;apos;hourly&amp;apos;
);
&lt;/pre&gt;
 &lt;p&gt;优化效果：某物联网平台查询性能提升 7 倍&lt;/p&gt;
 &lt;h4&gt;连接与并发优化&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;pg_bouncer&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;连接池模式对比：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;模式&lt;/td&gt;
   &lt;td&gt;事务级&lt;/td&gt;
   &lt;td&gt;会话级&lt;/td&gt;
   &lt;td&gt;语句级&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;连接复用率&lt;/td&gt;
   &lt;td&gt;80%&lt;/td&gt;
   &lt;td&gt;30%&lt;/td&gt;
   &lt;td&gt;95%&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;推荐配置：&lt;/p&gt;
 &lt;pre&gt;[databases]
mydb = host=127.0.0.1 port=5432 pool_size=100

[pgbouncer]
pool_mode = transaction
max_client_conn = 1000
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;pg_prewarm&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;预热策略：&lt;/p&gt;
 &lt;pre&gt;-- 手动预热热表
SELECT pg_prewarm(&amp;apos;orders&amp;apos;, &amp;apos;buffer&amp;apos;);
&lt;/pre&gt;
 &lt;p&gt;自动化方案：&lt;/p&gt;
 &lt;pre&gt;*/5 * * * * psql -c &amp;quot;SELECT pg_prewarm(oid) FROM pg_class WHERE relname IN (&amp;apos;orders&amp;apos;,&amp;apos;products&amp;apos;);&amp;quot;&lt;/pre&gt;
 &lt;h4&gt;索引优化扩展&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;pg_roaringbitmap&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;位图索引优势：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;用户量&lt;/td&gt;
   &lt;td&gt;传统位图&lt;/td&gt;
   &lt;td&gt;RoaringBitmap&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;100万&lt;/td&gt;
   &lt;td&gt;125KB&lt;/td&gt;
   &lt;td&gt;8KB&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;1亿&lt;/td&gt;
   &lt;td&gt;12MB&lt;/td&gt;
   &lt;td&gt;1.2MB&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;使用场景：用户画像标签交集查询&lt;/p&gt;
 &lt;pre&gt;SELECT uid FROM user_tags 
WHERE tag = &amp;apos;vip&amp;apos; 
AND rb_and(tag_bits, rb_build(array[1,3,5]));
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;pg_trgm&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;模糊搜索优化：&lt;/p&gt;
 &lt;pre&gt;CREATE INDEX idx_name_trgm ON users 
USING gin (name gin_trgm_ops);
&lt;/pre&gt;
 &lt;p&gt;性能提升：&lt;/p&gt;
 &lt;pre&gt;LIKE &amp;apos;%abc%&amp;apos; 查询从 1.2s → 23ms&lt;/pre&gt;
 &lt;h4&gt;分布式优化扩展&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;Citus&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;分片策略对比：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;策略&lt;/td&gt;
   &lt;td&gt;均匀性&lt;/td&gt;
   &lt;td&gt;查询效率&lt;/td&gt;
   &lt;td&gt;扩展性&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;哈希分片&lt;/td&gt;
   &lt;td&gt;★★★★☆&lt;/td&gt;
   &lt;td&gt;★★★☆☆&lt;/td&gt;
   &lt;td&gt;★★★★☆&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;范围分片&lt;/td&gt;
   &lt;td&gt;★★☆☆☆&lt;/td&gt;
   &lt;td&gt;★★★★★&lt;/td&gt;
   &lt;td&gt;★★☆☆☆&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;多租户优化案例：某 SaaS 系统在 32 节点集群实现 120 万 QPS&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;pg_shard&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;轻量级分片方案：&lt;/p&gt;
 &lt;pre&gt;-- 创建分片表
SELECT shard.create_distributed_table(&amp;apos;sensor_data&amp;apos;, &amp;apos;sensor_id&amp;apos;);
&lt;/pre&gt;
 &lt;p&gt;适用场景：中小规模分布式系统（10 节点以下）&lt;/p&gt;
 &lt;h4&gt;内存优化扩展&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;pgmemcache&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;内存表配置：&lt;/p&gt;
 &lt;pre&gt;CREATE TABLE session_cache (
    key TEXT PRIMARY KEY,
    val BYTEA
) USING pgmemcache;
&lt;/pre&gt;
 &lt;p&gt;性能指标：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;操作&lt;/td&gt;
   &lt;td&gt;磁盘表&lt;/td&gt;
   &lt;td&gt;内存表&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;随机读取&lt;/td&gt;
   &lt;td&gt;2ms&lt;/td&gt;
   &lt;td&gt;0.1ms&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;批量写入&lt;/td&gt;
   &lt;td&gt;1200/s&lt;/td&gt;
   &lt;td&gt;8500/s&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;  &lt;strong&gt;pg_buffercache&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;缓存分析：&lt;/p&gt;
 &lt;pre&gt;SELECT c.relname, 
       count(*) AS buffers,
       round(100.0 * count(*) / (SELECT setting FROM pg_settings WHERE name=&amp;apos;shared_buffers&amp;apos;)::integer,1) AS &amp;quot;%&amp;quot;
FROM pg_buffercache b 
JOIN pg_class c ON b.relfilenode = pg_relation_filenode(c.oid)
GROUP BY c.relname
ORDER BY 2 DESC;
&lt;/pre&gt;
 &lt;p&gt;优化建议：对高频访问表增加 shared_buffers 分配&lt;/p&gt;
 &lt;h4&gt;全栈优化方案示例&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;电商系统优化案例&lt;/strong&gt;：&lt;/p&gt;
 &lt;p&gt;架构组件:&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;pg_bouncer: 处理 5000 连接池&lt;/li&gt;
  &lt;li&gt;Citus: 分片存储订单数据&lt;/li&gt;
  &lt;li&gt;pg_partman: 按周分区订单表&lt;/li&gt;
  &lt;li&gt;pg_repack: 每日凌晨重组热表&lt;/li&gt;
  &lt;li&gt;pg_prewarm: 预热产品目录表&lt;/li&gt;
  &lt;li&gt;pg_roaringbitmap: 用户标签查询&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;性能指标:&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;原系统: 1200 TPS, 平均延迟 450ms&lt;/li&gt;
  &lt;li&gt;优化后: 8500 TPS, 平均延迟 65ms&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;优化实施路线图&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;诊断阶段&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;-- 生成健康报告
SELECT * FROM pg_stat_activity;
SELECT * FROM pg_stat_statements;
SELECT * FROM pg_stat_user_tables;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;实施顺序&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;   &lt;img alt="" height="134" src="http://www.biaodianfu.com/wp-content/uploads/2025/04/stat.png" width="1498"&gt;&lt;/img&gt;&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;监控指标&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;使用 Prometheus + Grafana 监控&lt;/p&gt;
 &lt;p&gt;关键指标:&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;pg_stat_database_xact_commit&lt;/li&gt;
  &lt;li&gt;pg_stat_user_tables_n_dead_tup&lt;/li&gt;
  &lt;li&gt;pg_stat_bgwriter_buffers_alloc&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;通过系统化的扩展组合，PostgreSQL 可以在保持 ACID 特性的同时，实现与专用系统相媲美的性能表现。建议每季度进行扩展组件健康检查，并参考 pg_extension 系统表管理扩展版本。&lt;/p&gt;
 &lt;h3&gt;开发工具扩展&lt;/h3&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;扩展名称&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;功能定位&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;开发效率提升&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;使用案例&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pgTAP&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;单元测试框架&lt;/td&gt;
   &lt;td&gt;支持 200+ 测试断言&lt;/td&gt;
   &lt;td&gt;存储过程测试&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;PostgREST&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;REST API 自动生成&lt;/td&gt;
   &lt;td&gt;零代码生成 CRUD API&lt;/td&gt;
   &lt;td&gt;快速原型开发&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pldbgapi&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;存储过程调试&lt;/td&gt;
   &lt;td&gt;支持 PL/pgSQL 断点调试&lt;/td&gt;
   &lt;td&gt;复杂业务逻辑开发&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pglogical&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;逻辑复制&lt;/td&gt;
   &lt;td&gt;跨版本数据同步，延迟 &amp;lt;100ms&lt;/td&gt;
   &lt;td&gt;灰度发布、多活架构&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;dblink&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;跨库查询&lt;/td&gt;
   &lt;td&gt;实现分布式 JOIN 操作&lt;/td&gt;
   &lt;td&gt;数据联邦查询&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;PostgreSQL 的开发工具扩展显著提升了数据库开发的工程化能力，以下是按功能分类的关键扩展详解：&lt;/p&gt;
 &lt;h4&gt;自动化测试扩展&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;pgTAP&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;核心能力：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;支持 200+ 测试断言&lt;/li&gt;
  &lt;li&gt;兼容 xUnit 测试风格&lt;/li&gt;
  &lt;li&gt;集成 CI/CD 流水线&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;测试示例：&lt;/p&gt;
 &lt;pre&gt;BEGIN;
SELECT plan(3);

-- 检查表结构
SELECT has_table(&amp;apos;public.orders&amp;apos;);
SELECT has_column(&amp;apos;orders&amp;apos;, &amp;apos;total_price&amp;apos;);
SELECT col_type_is(&amp;apos;orders&amp;apos;, &amp;apos;status&amp;apos;, &amp;apos;text&amp;apos;);

SELECT * FROM finish();
ROLLBACK;
&lt;/pre&gt;
 &lt;p&gt;测试报告输出：&lt;/p&gt;
 &lt;pre&gt;ok 1 - Table public.orders exists
ok 2 - Column orders.total_price exists
ok 3 - Column orders.status is type text
&lt;/pre&gt;
 &lt;p&gt;优势：某金融系统通过 pgTAP 将生产事故减少 65%&lt;/p&gt;
 &lt;h4&gt;API 生成扩展&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;PostgREST&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;功能特性：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;自动生成 OpenAPI 文档&lt;/li&gt;
  &lt;li&gt;支持 JWT 认证&lt;/li&gt;
  &lt;li&gt;行级权限控制&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;配置示例：&lt;/p&gt;
 &lt;pre&gt;-- 创建 API 访问角色
CREATE ROLE api_user;
GRANT SELECT ON orders TO api_user;

-- 启用行级安全
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
&lt;/pre&gt;
 &lt;p&gt;性能对比：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;请求类型&lt;/td&gt;
   &lt;td&gt;传统后端 (req/s)&lt;/td&gt;
   &lt;td&gt;PostgREST (req/s)&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;GET&lt;/td&gt;
   &lt;td&gt;850&lt;/td&gt;
   &lt;td&gt;4200&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;POST&lt;/td&gt;
   &lt;td&gt;120&lt;/td&gt;
   &lt;td&gt;980&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;h4&gt;调试诊断扩展&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;pldbgapi&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;调试流程：&lt;/p&gt;
 &lt;pre&gt;-- 启动调试会话
SELECT pldbg_attach_to_port(1234);

-- 设置断点
SELECT pldbg_set_breakpoint(&amp;apos;calculate_bonus&amp;apos;, 15);

-- 逐步执行
SELECT pldbg_step_into();
&lt;/pre&gt;
 &lt;p&gt;支持特性：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;变量监控窗口&lt;/li&gt;
  &lt;li&gt;调用栈追踪&lt;/li&gt;
  &lt;li&gt;异步调试会话&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;典型应用：某电商平台调试复杂佣金计算函数，效率提升 3 倍&lt;/p&gt;
 &lt;h4&gt;数据操作扩展&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;dblink&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;跨库查询示例：&lt;/p&gt;
 &lt;pre&gt;SELECT * 
FROM dblink(&amp;apos;foreign_server&amp;apos;, &amp;apos;SELECT id, name FROM products&amp;apos;) 
AS t(id int, name text)
WHERE name ILIKE &amp;apos;%phone%&amp;apos;;
&lt;/pre&gt;
 &lt;p&gt;连接池配置：&lt;/p&gt;
 &lt;pre&gt;-- 创建持久连接
SELECT dblink_connect(&amp;apos;myconn&amp;apos;, &amp;apos;dbname=warehouse&amp;apos;);
&lt;/pre&gt;
 &lt;p&gt;性能优化：通过连接复用将跨库查询延迟从 120ms 降至 45ms&lt;/p&gt;
 &lt;h4&gt;模式管理扩展&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;sqitch&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;迁移文件结构：&lt;/p&gt;
 &lt;pre&gt;migrations/
├── deploy/
│   └── 001_create_users.sql
├── revert/
│   └── 001_create_users.sql
└── verify/
    └── 001_create_users.sql
&lt;/pre&gt;
 &lt;p&gt;工作流程：&lt;/p&gt;
 &lt;pre&gt;sqitch add create_products --requires users
sqitch deploy db:postgres:///mydb
sqitch verify db:postgres:///mydb
&lt;/pre&gt;
 &lt;p&gt;企业应用：某跨国团队通过 sqitch 实现多环境统一变更管理&lt;/p&gt;
 &lt;h4&gt;文档生成扩展&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;pgdocs&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;文档生成命令：&lt;/p&gt;
 &lt;pre&gt;pgdocs generate -d mydb -o docs/&lt;/pre&gt;
 &lt;p&gt;输出内容：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;ER 关系图&lt;/li&gt;
  &lt;li&gt;存储过程说明&lt;/li&gt;
  &lt;li&gt;权限矩阵表&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;集成效果：新员工理解数据库结构时间从 2 周缩短至 3 天&lt;/p&gt;
 &lt;h4&gt;开发加速扩展&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;pgmemento&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;审计日志实现：&lt;/p&gt;
 &lt;pre&gt;-- 启用表审计
SELECT pgmemento.create_table_audit(&amp;apos;orders&amp;apos;, &amp;apos;public&amp;apos;);

-- 查询历史变更
SELECT * FROM pgmemento.row_version 
WHERE table_name = &amp;apos;orders&amp;apos; 
  AND changed_at &amp;gt; &amp;apos;2023-01-01&amp;apos;;
&lt;/pre&gt;
 &lt;p&gt;存储优化：采用 delta 编码使审计日志体积减少 60%&lt;/p&gt;
 &lt;h4&gt;扩展组合方案&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;微服务开发技术栈&lt;/strong&gt;：&lt;/p&gt;
 &lt;p&gt;开发阶段:&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;pgTAP: 单元测试&lt;/li&gt;
  &lt;li&gt;pldbgapi: 存储过程调试&lt;/li&gt;
  &lt;li&gt;sqitch: 版本迁移&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;API 层:&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;PostgREST: REST API 生成&lt;/li&gt;
  &lt;li&gt;pgmemento: 数据变更追踪&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;运维监控:&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;pgdocs: 文档自动化&lt;/li&gt;
  &lt;li&gt;dblink: 跨服务查询&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;扩展管理策略&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;版本控制&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;# 生成扩展清单
psql -c &amp;quot;\dx&amp;quot; &amp;gt; extensions-$(date +%F).txt
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;安全更新&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;-- 检查可更新扩展
SELECT * FROM pg_available_extension_versions 
WHERE installed AND name IN (&amp;apos;postgrest&amp;apos;,&amp;apos;pgtap&amp;apos;);
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;依赖管理&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;-- 级联删除
DROP EXTENSION postgis CASCADE;
&lt;/pre&gt;
 &lt;p&gt;通过合理组合开发工具扩展，PostgreSQL 可以构建完整的数据库开发运维体系，实现从代码编写到生产部署的全链路工程化支持。建议将扩展管理纳入 DevOps 流程，结合 pg_stat_user_functions 监控高频使用的开发组件。&lt;/p&gt;
 &lt;h3&gt;安全与合规扩展&lt;/h3&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;扩展名称&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;合规标准覆盖&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;安全层级&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;性能损耗&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pgcrypto&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;GDPR Art.32, PCI DSS&lt;/td&gt;
   &lt;td&gt;数据加密&lt;/td&gt;
   &lt;td&gt;8-15%&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;sepgsql&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;NIST 800-53, FIPS 140&lt;/td&gt;
   &lt;td&gt;强制访问控制&lt;/td&gt;
   &lt;td&gt;3-5%&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pg_audit&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;SOX, HIPAA&lt;/td&gt;
   &lt;td&gt;审计追踪&lt;/td&gt;
   &lt;td&gt;5-10%&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pg_anon&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;GDPR Art.5, CCPA&lt;/td&gt;
   &lt;td&gt;数据脱敏&lt;/td&gt;
   &lt;td&gt;可忽略&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pg_netrestrict&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;ISO 27001&lt;/td&gt;
   &lt;td&gt;网络访问控制&lt;/td&gt;
   &lt;td&gt;0.1%&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;h4&gt;加密与数据保护&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;pgcrypto&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;核心功能：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;支持 AES-256、RSA-4096、Blowfish 等算法&lt;/li&gt;
  &lt;li&gt;列级加密与解密函数&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;典型应用：&lt;/p&gt;
 &lt;pre&gt;-- 加密信用卡号
UPDATE users SET 
    card_number = pgp_sym_encrypt(&amp;apos;4111111111111111&amp;apos;, &amp;apos;sekret&amp;apos;);

-- 解密查询
SELECT pgp_sym_decrypt(card_number::bytea, &amp;apos;sekret&amp;apos;) 
FROM users WHERE id = 123;
&lt;/pre&gt;
 &lt;p&gt;性能测试：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;操作&lt;/td&gt;
   &lt;td&gt;明文 (ms)&lt;/td&gt;
   &lt;td&gt;AES-256 (ms)&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;插入10万条记录&lt;/td&gt;
   &lt;td&gt;420&lt;/td&gt;
   &lt;td&gt;480&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;范围查询&lt;/td&gt;
   &lt;td&gt;85&lt;/td&gt;
   &lt;td&gt;120&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;  &lt;strong&gt;pg_anon&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;脱敏策略：&lt;/p&gt;
 &lt;pre&gt;-- 创建脱敏规则
SECURITY LABEL FOR anon ON COLUMN patients.name 
IS &amp;apos;MASKED WITH FUNCTION anon.fake_first_name()&amp;apos;;

-- 生成假数据
SELECT anon.anonymize_database();
&lt;/pre&gt;
 &lt;p&gt;支持算法：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;随机替换 (Faker 库集成)&lt;/li&gt;
  &lt;li&gt;部分遮蔽 (如 1388912)&lt;/li&gt;
  &lt;li&gt;哈希脱敏 (SHA-256 + Salt)&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;GDPR 合规案例：某欧洲银行使用 pg_anon 将客户数据脱敏后用于测试环境，满足 GDPR 第5条数据最小化原则。&lt;/p&gt;
 &lt;h4&gt;访问控制扩展&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;sepgsql&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;策略配置示例：&lt;/p&gt;
 &lt;pre&gt;# 创建医疗数据标签
semanage fcontext -a -t hospital_data_t &amp;apos;/var/lib/pgsql/15/data(/.*)?&amp;apos;

# 设置策略规则
allow httpd_t hospital_data_t:db_table { select };
&lt;/pre&gt;
 &lt;p&gt;访问控制粒度：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;数据库对象级 (表/列)&lt;/li&gt;
  &lt;li&gt;操作类型级 (SELECT/UPDATE)&lt;/li&gt;
  &lt;li&gt;时间条件约束 (仅工作日允许访问)&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;pg_ident&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;企业级用户映射：&lt;/p&gt;
 &lt;pre&gt;# pg_ident.conf
MAPNAME     SYSTEM-USER   PG-USER
vpn_users   ldap_doctor   med_reader
vpn_users   ldap_nurse    med_limited
&lt;/pre&gt;
 &lt;p&gt;认证流程：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;操作系统用户ldap_doctor 通过 VPN 连接&lt;/li&gt;
  &lt;li&gt;PostgreSQL 自动映射为数据库角色med_reader&lt;/li&gt;
  &lt;li&gt;授予只读权限执行医疗数据分析&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;审计与溯源&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;pg_audit&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;审计日志示例：&lt;/p&gt;
 &lt;pre&gt;2023-08-15 14:23:18 UTC [user=admin] [db=medical] 
OBJECT: TABLE patients
ACTION: DELETE WHERE id=456
QUERY: DELETE FROM patients WHERE status=&amp;apos;inactive&amp;apos;;
&lt;/pre&gt;
 &lt;p&gt;关键特性：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;细粒度审计策略：&lt;/li&gt;
&lt;/ul&gt;
 &lt;pre&gt;SET pgaudit.log = &amp;apos;ddl, write, role&amp;apos;;&lt;/pre&gt;
 &lt;ul&gt;
  &lt;li&gt;支持 CSV/JSON 日志格式&lt;/li&gt;
  &lt;li&gt;审计日志压缩存储 (节省 60% 空间)&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;HIPAA 合规应用：医疗系统记录所有 PHI (受保护健康信息) 访问日志，满足 45 CFR 164.312 审计控制要求。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;pg_checksums&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;数据完整性验证：&lt;/p&gt;
 &lt;pre&gt;# 启用校验和
initdb --data-checksums

# 定期验证
pg_checksums -c /var/lib/pgsql/15/data
&lt;/pre&gt;
 &lt;p&gt;检测能力：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;磁盘位翻转错误&lt;/li&gt;
  &lt;li&gt;存储介质损坏&lt;/li&gt;
  &lt;li&gt;恶意数据篡改&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;性能影响：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;操作&lt;/td&gt;
   &lt;td&gt;无校验和&lt;/td&gt;
   &lt;td&gt;启用校验和&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;数据写入&lt;/td&gt;
   &lt;td&gt;100%&lt;/td&gt;
   &lt;td&gt;92%&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;全表扫描&lt;/td&gt;
   &lt;td&gt;100%&lt;/td&gt;
   &lt;td&gt;98%&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;h4&gt;网络与协议安全&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;pg_netrestrict&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;IP 白名单配置：&lt;/p&gt;
 &lt;pre&gt;CREATE EXTENSION pg_netrestrict;
ALTER SYSTEM SET pg_netrestrict.authorized_networks = &amp;apos;192.168.1.0/24, 10.8.0.5/32&amp;apos;;
SELECT pg_reload_conf();
&lt;/pre&gt;
 &lt;p&gt;防御场景：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;阻止 SQL 注入攻击源 IP&lt;/li&gt;
  &lt;li&gt;限制管理接口访问范围&lt;/li&gt;
  &lt;li&gt;遵守 ISO 27001 网络隔离要求&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;sslutils&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;高级 TLS 管理：&lt;/p&gt;
 &lt;pre&gt;-- 客户端证书吊销检查
ALTER SYSTEM SET sslutils.crl = &amp;apos;/etc/pgsql/ssl/crl.pem&amp;apos;;

-- 启用 OCSP 装订
SET sslutils.ocsp_stapling = on;
&lt;/pre&gt;
 &lt;p&gt;加密协议支持：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;TLS 1.3 优先协商&lt;/li&gt;
  &lt;li&gt;国密 SM4 算法支持&lt;/li&gt;
  &lt;li&gt;证书透明度 (CT) 日志&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;合规扩展组合方案&lt;/h4&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;金融系统合规架构&lt;/strong&gt;：&lt;/p&gt;
 &lt;p&gt;加密层:&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;pgcrypto: 字段级加密&lt;/li&gt;
  &lt;li&gt;sslutils: 国密算法支持&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;访问控制:&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;sepgsql: 强制访问控制&lt;/li&gt;
  &lt;li&gt;pg_ident: LDAP 集成&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;审计溯源:&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;pg_audit: 操作日志&lt;/li&gt;
  &lt;li&gt;pgmemento: 数据变更历史&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;网络防护:&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;pg_netrestrict: IP白名单&lt;/li&gt;
  &lt;li&gt;pg_hba_plus: 动态ACL&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;合规覆盖：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;PCIDSS 3.2.1 (加密存储)&lt;/li&gt;
  &lt;li&gt;银保监会数据安全指引&lt;/li&gt;
  &lt;li&gt;GDPR 数据主体权利&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;扩展管理最佳实践&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;安全更新策略&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;# 自动检查扩展漏洞
apt-get update &amp;amp;&amp;amp; apt-get upgrade postgresql-15-*
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;权限最小化原则&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;REVOKE ALL ON DATABASE prod FROM PUBLIC;
GRANT USAGE ON SCHEMA audit TO security_auditor;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;审计日志保留&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;# 使用 logrotate 管理
/var/log/postgresql/*.log {
    weekly
    rotate 12
    compress
    missingok
    notifempty
}
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;渗透测试验证&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;sqlmap -u &amp;quot;http://api:3000&amp;quot; --risk=3 --level=5&lt;/pre&gt;
 &lt;h4&gt;扩展性能优化建议&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;加密加速&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;-- 使用 AES-NI 硬件指令
SET pgcrypto.use_aesni = on;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;审计日志分区&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;CREATE TABLE audit_log_2023 PARTITION OF audit_log 
FOR VALUES FROM (&amp;apos;2023-01-01&amp;apos;) TO (&amp;apos;2024-01-01&amp;apos;);
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;访问控制缓存&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;ALTER ROLE security_auditor SET sepgsql.cache_refresh = 3600;&lt;/pre&gt;
 &lt;p&gt;通过合理配置安全扩展，PostgreSQL 可以满足金融级安全要求，某证券系统实际案例显示，在启用全套安全扩展后，成功抵御了 23 万次/日的攻击尝试，同时保持 99.99% 的可用性。建议每季度进行安全扩展的渗透测试和策略复审。&lt;/p&gt;
 &lt;h3&gt;人工智能扩展&lt;/h3&gt;
 &lt;p&gt;PostgreSQL 的人工智能扩展正在重新定义数据库的智能边界，以下是关键技术扩展的深度解析，涵盖向量计算、模型训练、预测服务等核心领域：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;扩展名称&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;技术架构&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;算力支持&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;典型延迟&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;适用场景&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pgvector&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;HNSW/IVFFlat&lt;/td&gt;
   &lt;td&gt;CPU/GPU&lt;/td&gt;
   &lt;td&gt;5-50ms&lt;/td&gt;
   &lt;td&gt;语义搜索/推荐系统&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pgml&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;集成PyTorch/TF&lt;/td&gt;
   &lt;td&gt;CPU/GPU&lt;/td&gt;
   &lt;td&gt;100-500ms&lt;/td&gt;
   &lt;td&gt;实时预测&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;apache madlib&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;分布式ML算法库&lt;/td&gt;
   &lt;td&gt;MPI/多节点&lt;/td&gt;
   &lt;td&gt;分钟级&lt;/td&gt;
   &lt;td&gt;批量训练&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pg_catcheck&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;词向量相似度&lt;/td&gt;
   &lt;td&gt;CPU&lt;/td&gt;
   &lt;td&gt;10-100ms&lt;/td&gt;
   &lt;td&gt;文本分类&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pg_openai&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;OpenAI API代理&lt;/td&gt;
   &lt;td&gt;网络调用&lt;/td&gt;
   &lt;td&gt;200-2000ms&lt;/td&gt;
   &lt;td&gt;GPT集成&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;h4&gt;向量计算引擎 – pgvector&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;技术实现&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;索引结构：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="502" src="http://www.biaodianfu.com/wp-content/uploads/2025/04/pgvector.png" width="1512"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;精度控制：支持 FP16 量化压缩，节省 50% 存储空间&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;性能基准&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;CREATE TABLE embeddings (id serial, vector vector(1536));
INSERT INTO embeddings SELECT generate_series(1,1000000), random_vector(1536);

-- HNSW索引
CREATE INDEX ON embeddings USING hnsw (vector vector_cosine_ops);

-- 相似度查询
SELECT id, vector &amp;lt;=&amp;gt; &amp;apos;[0.1,0.2,...]&amp;apos; AS score 
FROM embeddings ORDER BY score LIMIT 10;
&lt;/pre&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;数据规模&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;索引类型&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;QPS&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;召回率&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;存储成本&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;100万×768&lt;/td&gt;
   &lt;td&gt;HNSW&lt;/td&gt;
   &lt;td&gt;1200&lt;/td&gt;
   &lt;td&gt;99%&lt;/td&gt;
   &lt;td&gt;1.2GB&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;1亿×1536&lt;/td&gt;
   &lt;td&gt;IVFFlat&lt;/td&gt;
   &lt;td&gt;8500&lt;/td&gt;
   &lt;td&gt;95%&lt;/td&gt;
   &lt;td&gt;196GB&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;h4&gt;机器学习管道 – pgml&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;核心功能&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;-- 模型训练
SELECT pgml.train(
    project_name =&amp;gt; &amp;apos;房价预测&amp;apos;,
    task =&amp;gt; &amp;apos;regression&amp;apos;,
    relation_name =&amp;gt; &amp;apos;houses&amp;apos;,
    y_column_name =&amp;gt; &amp;apos;price&amp;apos;,
    algorithm =&amp;gt; &amp;apos;xgboost&amp;apos;
);

-- 实时预测
SELECT pgml.predict(&amp;apos;房价预测&amp;apos;, ARRAY[面积, 房间数, 位置编码]) 
FROM new_listings;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;支持的算法&lt;/strong&gt;&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;类型&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;算法列表&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;传统机器学习&lt;/td&gt;
   &lt;td&gt;线性回归、随机森林、SVM&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;深度学习&lt;/td&gt;
   &lt;td&gt;BERT、ResNet、LSTM&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;时间序列&lt;/td&gt;
   &lt;td&gt;Prophet、ARIMA&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;无监督学习&lt;/td&gt;
   &lt;td&gt;K-Means、PCA&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;  &lt;strong&gt;资源消耗&lt;/strong&gt;&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;操作&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;数据量&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;CPU占用&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;内存消耗&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;耗时&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;XGBoost模型训练&lt;/td&gt;
   &lt;td&gt;100万行&lt;/td&gt;
   &lt;td&gt;85%&lt;/td&gt;
   &lt;td&gt;8GB&lt;/td&gt;
   &lt;td&gt;2.3m&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;BERT文本嵌入生成&lt;/td&gt;
   &lt;td&gt;1万文本&lt;/td&gt;
   &lt;td&gt;95%&lt;/td&gt;
   &lt;td&gt;16GB&lt;/td&gt;
   &lt;td&gt;4.5m&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;LSTM时序预测&lt;/td&gt;
   &lt;td&gt;1年数据&lt;/td&gt;
   &lt;td&gt;78%&lt;/td&gt;
   &lt;td&gt;6GB&lt;/td&gt;
   &lt;td&gt;1.2m&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;h4&gt;分布式机器学习 – Apache MADlib&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;架构设计&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="803" src="http://www.biaodianfu.com/wp-content/uploads/2025/04/MADlib.png" width="846"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;算法加速比&lt;/strong&gt;&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;算法&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;单节点耗时&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;4节点耗时&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;加速比&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;协同过滤&lt;/td&gt;
   &lt;td&gt;58m&lt;/td&gt;
   &lt;td&gt;14m&lt;/td&gt;
   &lt;td&gt;4.14x&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;决策树训练&lt;/td&gt;
   &lt;td&gt;2.1h&lt;/td&gt;
   &lt;td&gt;0.6h&lt;/td&gt;
   &lt;td&gt;3.5x&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;矩阵分解&lt;/td&gt;
   &lt;td&gt;6.8h&lt;/td&gt;
   &lt;td&gt;1.5h&lt;/td&gt;
   &lt;td&gt;4.53x&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;  &lt;strong&gt;企业应用案例&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;某零售巨头：使用 MADlib 在 20 节点集群训练用户分群模型，处理 10TB 行为数据，将营销转化率提升 18%&lt;/p&gt;
 &lt;h4&gt;语义处理扩展 – pg_catcheck&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;相似度计算&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;-- 创建词向量索引
CREATE INDEX ON products USING gin (description gin_catcheck_ops);

-- 语义搜索
SELECT name, catcheck_similarity(description, &amp;apos;舒适透气运动鞋&amp;apos;) AS score
FROM products
WHERE description % &amp;apos;舒适透气运动鞋&amp;apos;
ORDER BY score DESC LIMIT 10;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;性能对比&lt;/strong&gt;&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;方法&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;准确率&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;QPS&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;索引大小&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;全文检索&lt;/td&gt;
   &lt;td&gt;62%&lt;/td&gt;
   &lt;td&gt;1200&lt;/td&gt;
   &lt;td&gt;850MB&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;pg_catcheck&lt;/td&gt;
   &lt;td&gt;89%&lt;/td&gt;
   &lt;td&gt;650&lt;/td&gt;
   &lt;td&gt;1.3GB&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;专用ES引擎&lt;/td&gt;
   &lt;td&gt;92%&lt;/td&gt;
   &lt;td&gt;1500&lt;/td&gt;
   &lt;td&gt;2.1GB&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;h4&gt;AI扩展联合应用案例&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;智能客服系统架构&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;-- 用户问题向量化
WITH query_vec AS (
    SELECT pgml.embed(&amp;apos;sentence-transformers/all-mpnet-base-v2&amp;apos;, &amp;apos;如何退换货？&amp;apos;) AS vec
)

-- 检索知识库
SELECT k.id, k.answer, (k.vector &amp;lt;=&amp;gt; q.vec) AS score
FROM knowledge_base k, query_vec q
ORDER BY score LIMIT 3;

-- 调用GPT生成
SELECT openai_completion(
    &amp;apos;你是一名客服助手，请根据以下知识回答问题：&amp;apos;
    || (SELECT answer FROM knowledge_base WHERE id = 123), 
    &amp;apos;gpt-4&amp;apos;, 
    0.7
);
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;性能指标&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;端到端延迟：平均 820ms&lt;/li&gt;
  &lt;li&gt;准确率：92%（相比传统方法提升 35%）&lt;/li&gt;
  &lt;li&gt;成本：比独立AI服务降低 60%（减少数据传输开销）&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;扩展部署最佳实践&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;硬件资源配置&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;vector_db:
  cpu: 16 cores (AVX512)
  memory: 64GB 
  storage: NVMe SSD RAID
  gpu: 1×A10（可选）

ml_serving:
  cpu: 8 cores
  memory: 32GB
  network: 10Gbps
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;版本兼容性矩阵&lt;/strong&gt;：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;扩展&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;PG 13&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;PG 14&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;PG 15&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;PG 16&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;pgvector&lt;/td&gt;
   &lt;td&gt;✓&lt;/td&gt;
   &lt;td&gt;✓&lt;/td&gt;
   &lt;td&gt;✓&lt;/td&gt;
   &lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;pgml&lt;/td&gt;
   &lt;td&gt;✓&lt;/td&gt;
   &lt;td&gt;✓&lt;/td&gt;
   &lt;td&gt;✓&lt;/td&gt;
   &lt;td&gt;Beta&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;madlib&lt;/td&gt;
   &lt;td&gt;✓&lt;/td&gt;
   &lt;td&gt;✓&lt;/td&gt;
   &lt;td&gt;✓&lt;/td&gt;
   &lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;  &lt;strong&gt;监控指标&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;# 关键性能计数器
pg_stat_ai_queries_total
pg_ml_model_inference_duration_seconds
pg_vector_cache_hit_rate
&lt;/pre&gt;
 &lt;h4&gt;与传统方案的对比优势&lt;/h4&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;维度&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;传统AI架构&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;PostgreSQL AI扩展方案&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;数据移动&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;ETL管道，高延迟&lt;/td&gt;
   &lt;td&gt;库内计算，零数据迁移&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;事务一致&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;最终一致性&lt;/td&gt;
   &lt;td&gt;ACID保证&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;开发成本&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;多系统集成，高维护成本&lt;/td&gt;
   &lt;td&gt;单一技术栈&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;实时性&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;批处理为主&lt;/td&gt;
   &lt;td&gt;亚秒级实时推理&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;安全合规&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;多系统暴露面大&lt;/td&gt;
   &lt;td&gt;统一权限控制&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;某电商平台采用 PostgreSQL AI 扩展后，推荐系统更新频率从小时级提升到秒级，CTR（点击率）提升 22%，同时基础设施成本降低 40%。&lt;/p&gt;
 &lt;p&gt;通过深度集成AI能力，PostgreSQL 正在演变为   &lt;strong&gt;智能化数据计算平台&lt;/strong&gt;，建议在以下场景优先考虑：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;需要实时更新的推荐系统&lt;/li&gt;
  &lt;li&gt;隐私敏感的本地化AI推理&lt;/li&gt;
  &lt;li&gt;事务型AI应用（如实时反欺诈）&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;存储引擎扩展&lt;/h3&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;扩展名称&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;存储架构&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;性能表现&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;适用场景&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;zheap&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;堆表引擎优化&lt;/td&gt;
   &lt;td&gt;减少 70% 表膨胀&lt;/td&gt;
   &lt;td&gt;高频更新系统&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;cstore_fdw&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;列式存储&lt;/td&gt;
   &lt;td&gt;压缩率 5x，扫描速度提升 10x&lt;/td&gt;
   &lt;td&gt;分析型工作负载&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;roaringbitmap&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;位图索引&lt;/td&gt;
   &lt;td&gt;支持 10 亿级用户分群&lt;/td&gt;
   &lt;td&gt;用户画像系统&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pg_rational&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;分数类型存储&lt;/td&gt;
   &lt;td&gt;精确避免浮点误差&lt;/td&gt;
   &lt;td&gt;金融计费系统&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pgmemcache&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;内存表引擎&lt;/td&gt;
   &lt;td&gt;亚毫秒级响应&lt;/td&gt;
   &lt;td&gt;实时竞价系统&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;PostgreSQL 的存储引擎扩展体系突破了传统关系型数据库的存储限制，通过模块化架构实现存储层的灵活扩展。&lt;/p&gt;
 &lt;h4&gt;存储引擎扩展架构&lt;/h4&gt;
 &lt;p&gt;PostgreSQL 通过   &lt;strong&gt;Table Access Method API&lt;/strong&gt; 和   &lt;strong&gt;TOAST 机制&lt;/strong&gt; 实现存储引擎的可扩展性：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="694" src="http://www.biaodianfu.com/wp-content/uploads/2025/04/Table-Access-Method-API.png" width="1307"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h4&gt;核心存储引擎扩展&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;zheap（事务优化引擎）&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;技术特性：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;替代传统 Heap 表的事务管理&lt;/li&gt;
  &lt;li&gt;使用 UNDO 日志 替代多版本存储&lt;/li&gt;
  &lt;li&gt;减少 70% 的表膨胀&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;性能测试：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;场景&lt;/td&gt;
   &lt;td&gt;Heap表写入TPS&lt;/td&gt;
   &lt;td&gt;zheap写入TPS&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;高频UPDATE&lt;/td&gt;
   &lt;td&gt;12,000&lt;/td&gt;
   &lt;td&gt;38,000&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;批量DELETE&lt;/td&gt;
   &lt;td&gt;8,500&lt;/td&gt;
   &lt;td&gt;24,000&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;适用场景：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;频繁更新的订单状态表&lt;/li&gt;
  &lt;li&gt;实时竞价系统&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;cstore_fdw（列式存储）&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;技术实现：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;列式数据压缩（ORC格式）&lt;/li&gt;
  &lt;li&gt;向量化执行引擎&lt;/li&gt;
  &lt;li&gt;支持 Parquet 外部表&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;压缩效率：&lt;/p&gt;
 &lt;pre&gt;-- 创建列式表
CREATE FOREIGN TABLE sales (
    id integer,
    date date,
    amount numeric
) SERVER cstore_server;

-- 压缩比对比
SELECT pg_size_pretty(pg_total_relation_size(&amp;apos;sales_heap&amp;apos;)) AS heap_size,
       pg_size_pretty(pg_total_relation_size(&amp;apos;sales_cstore&amp;apos;)) AS cstore_size;
&lt;/pre&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;数据量&lt;/td&gt;
   &lt;td&gt;HEAP大小&lt;/td&gt;
   &lt;td&gt;cstore大小&lt;/td&gt;
   &lt;td&gt;压缩率&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;1TB&lt;/td&gt;
   &lt;td&gt;1.2TB&lt;/td&gt;
   &lt;td&gt;230GB&lt;/td&gt;
   &lt;td&gt;5.2x&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;适用场景：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;数据仓库聚合查询&lt;/li&gt;
  &lt;li&gt;时序数据分析&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;pgmemcache（内存引擎）&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;架构设计：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="106" src="http://www.biaodianfu.com/wp-content/uploads/2025/04/pgmemcache.png" width="1299"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;性能指标：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;操作&lt;/td&gt;
   &lt;td&gt;磁盘表延迟&lt;/td&gt;
   &lt;td&gt;内存表延迟&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;随机读取&lt;/td&gt;
   &lt;td&gt;2.3ms&lt;/td&gt;
   &lt;td&gt;0.12ms&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;批量写入&lt;/td&gt;
   &lt;td&gt;1200 TPS&lt;/td&gt;
   &lt;td&gt;8500 TPS&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;使用示例：&lt;/p&gt;
 &lt;pre&gt;CREATE TABLE session_cache (
    key TEXT PRIMARY KEY,
    val BYTEA
) USING pgmemcache;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;roaringbitmap（位图引擎）&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;技术优势：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;压缩位图存储（比传统BITMAP小10x）&lt;/li&gt;
  &lt;li&gt;支持快速集合运算（AND/OR/XOR）&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;用户分群案例：&lt;/p&gt;
 &lt;pre&gt;-- 创建位图表
CREATE TABLE user_tags (
    tag_id int PRIMARY KEY,
    users roaringbitmap
);

-- 查找同时满足标签A和B的用户
SELECT rb_cardinality(rb_and(a.users, b.users))
FROM user_tags a, user_tags b
WHERE a.tag_id = 1 AND b.tag_id = 2;
&lt;/pre&gt;
 &lt;p&gt;存储效率：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;用户量&lt;/td&gt;
   &lt;td&gt;传统位图&lt;/td&gt;
   &lt;td&gt;roaringbitmap&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;100万&lt;/td&gt;
   &lt;td&gt;125KB&lt;/td&gt;
   &lt;td&gt;8KB&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;1亿&lt;/td&gt;
   &lt;td&gt;12MB&lt;/td&gt;
   &lt;td&gt;1.2MB&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;h4&gt;存储引擎对比矩阵&lt;/h4&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;引擎类型&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;写性能&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;读性能&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;压缩率&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;事务支持&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;适用负载&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;Heap&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;★★★★☆&lt;/td&gt;
   &lt;td&gt;★★★☆☆&lt;/td&gt;
   &lt;td&gt;1x&lt;/td&gt;
   &lt;td&gt;ACID&lt;/td&gt;
   &lt;td&gt;OLTP&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;zheap&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;★★★★★&lt;/td&gt;
   &lt;td&gt;★★★★☆&lt;/td&gt;
   &lt;td&gt;0.3x&lt;/td&gt;
   &lt;td&gt;ACID&lt;/td&gt;
   &lt;td&gt;高频更新&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;cstore&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;★★☆☆☆&lt;/td&gt;
   &lt;td&gt;★★★★★&lt;/td&gt;
   &lt;td&gt;5x&lt;/td&gt;
   &lt;td&gt;无&lt;/td&gt;
   &lt;td&gt;OLAP&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pgmemcache&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;★★★★★&lt;/td&gt;
   &lt;td&gt;★★★★★&lt;/td&gt;
   &lt;td&gt;无&lt;/td&gt;
   &lt;td&gt;部分&lt;/td&gt;
   &lt;td&gt;实时缓存&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;roaringbitmap&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;★★★★☆&lt;/td&gt;
   &lt;td&gt;★★★★★&lt;/td&gt;
   &lt;td&gt;10x&lt;/td&gt;
   &lt;td&gt;无&lt;/td&gt;
   &lt;td&gt;用户分群&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;h4&gt;企业级应用方案&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;金融交易系统存储架构&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;核心交易表:&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;引擎: zheap&lt;/li&gt;
  &lt;li&gt;特性: 高频UPDATE/DELETE抗膨胀&lt;/li&gt;
  &lt;li&gt;配置: undo_log_segment_size=1GB&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;历史数据分析:&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;引擎: cstore_fdw&lt;/li&gt;
  &lt;li&gt;特性: 列式压缩存储&lt;/li&gt;
  &lt;li&gt;配置: compression=zstd&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;实时风控缓存:&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;引擎: pgmemcache&lt;/li&gt;
  &lt;li&gt;特性: 亚毫秒级响应&lt;/li&gt;
  &lt;li&gt;配置: max_size=64GB&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;用户画像存储:&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;引擎: roaringbitmap&lt;/li&gt;
  &lt;li&gt;特性: 快速集合运算&lt;/li&gt;
  &lt;li&gt;配置: rb_threshold=1000000&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;性能收益&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;交易处理吞吐量提升2x&lt;/li&gt;
  &lt;li&gt;风控决策延迟降低至8ms&lt;/li&gt;
  &lt;li&gt;存储成本减少 60%&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;扩展管理实践&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;多引擎混合部署&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;-- 跨引擎查询示例
SELECT o.order_id, c.amount 
FROM orders_heap o 
JOIN order_cache_pgmemcache c ON o.id = c.order_id;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;生命周期管理&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;-- 数据分层自动化
CREATE TABLE logs (
    ...
) PARTITION BY RANGE (log_time) 
PARTITION logs_2023 USING cstore_fdw,
PARTITION logs_current USING heap;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;监控指标&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;# 关键监控项
pg_stat_user_tables_n_dead_tup   # zheap表膨胀监控
cstore_total_blocks               # 列式存储块使用
pgmemcache_hit_rate               # 内存表命中率
&lt;/pre&gt;
 &lt;h4&gt;未来演进方向&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;多模事务引擎&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;跨存储引擎的 ACID 事务支持（如内存表与列式表的事务一致性）&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;硬件加速集成&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;GPU 加速列式扫描&lt;/li&gt;
  &lt;li&gt;持久化内存（PMEM）优化引擎&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;智能存储决策&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;-- AI驱动的存储选择建议
SELECT pg_ai_advise_storage(&amp;apos;orders&amp;apos;, access_pattern=&amp;apos;update_heavy&amp;apos;);
-- 建议输出: zheap
&lt;/pre&gt;
 &lt;p&gt;PostgreSQL 的存储引擎扩展体系正在重塑数据库技术栈，使单一数据库能够同时承载交易、分析、缓存等多种负载。建议根据访问模式设计混合存储方案，并通过 pg_stat_statements 持续监控各引擎的效能表现。&lt;/p&gt;
 &lt;h3&gt;监控诊断扩展&lt;/h3&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;扩展名称&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;监控维度&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;数据粒度&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;存储方式&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;采样精度&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pg_stat_statements&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;SQL执行统计&lt;/td&gt;
   &lt;td&gt;语句级&lt;/td&gt;
   &lt;td&gt;内存+持久化&lt;/td&gt;
   &lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pg_qualstats&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;谓词条件分析&lt;/td&gt;
   &lt;td&gt;列值分布&lt;/td&gt;
   &lt;td&gt;内存&lt;/td&gt;
   &lt;td&gt;0.1%采样&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pg_wait_sampling&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;等待事件&lt;/td&gt;
   &lt;td&gt;进程级&lt;/td&gt;
   &lt;td&gt;内存&lt;/td&gt;
   &lt;td&gt;100Hz采样&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pg_stat_monitor&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;全链路追踪&lt;/td&gt;
   &lt;td&gt;事务级&lt;/td&gt;
   &lt;td&gt;共享内存&lt;/td&gt;
   &lt;td&gt;全量&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;pg_activity&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;实时会话&lt;/td&gt;
   &lt;td&gt;连接级&lt;/td&gt;
   &lt;td&gt;实时查询&lt;/td&gt;
   &lt;td&gt;秒级刷新&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;h4&gt;SQL级监控 – pg_stat_statements&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;核心功能&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;-- 查看TOP 10 慢查询
SELECT queryid, total_time, calls, mean_time,
       rows, query 
FROM pg_stat_statements 
ORDER BY total_time DESC 
LIMIT 10;
&lt;/pre&gt;
 &lt;p&gt;关键指标：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;shared_blks_hit/shared_blks_read：缓存命中率&lt;/li&gt;
  &lt;li&gt;wal_bytes：写入负载&lt;/li&gt;
  &lt;li&gt;temp_blks_written：临时数据量&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;性能优化案例&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;某电商平台通过分析 pg_stat_statements 发现：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;高频调用但低效的购物车查询（平均 120ms → 优化至 15ms）&lt;/li&gt;
  &lt;li&gt;缺失索引的订单搜索（添加复合索引后 QPS 提升 5x）&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;等待事件分析 – pg_wait_sampling&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;等待事件分类&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="750" src="http://www.biaodianfu.com/wp-content/uploads/2025/04/pg_wait_sampling.png" width="1016"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;瓶颈诊断流程&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;-- 查看当前等待事件
SELECT pg_stat_get_activity(pid)-&amp;gt;wait_event_type,
       pg_stat_get_activity(pid)-&amp;gt;wait_event
FROM pg_stat_activity 
WHERE state = &amp;apos;active&amp;apos;;

-- 历史分析
SELECT event_type, event, sum(samples)
FROM pg_wait_sampling_history
GROUP BY 1,2 
ORDER BY 3 DESC;
&lt;/pre&gt;
 &lt;p&gt;优化建议：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;IO-DataFileRead过高 → 增加 shared_buffers 或使用 SSD&lt;/li&gt;
  &lt;li&gt;LWLock竞争 → 优化热点表索引&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;全链路追踪 – pg_stat_monitor&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;架构设计&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="80" src="http://www.biaodianfu.com/wp-content/uploads/2025/04/pg_stat_monitor.png" width="1306"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;关键特性&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;事务溯源：跟踪单个事务内的多语句执行&lt;/li&gt;
  &lt;li&gt;执行计划存储：保留最近100个查询计划&lt;/li&gt;
  &lt;li&gt;错误上下文：记录错误发生的具体SQL和参数&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;配置示例&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;# postgresql.conf
pg_stat_monitor.pgsm_enable = on
pg_stat_monitor.pgsm_max_buckets = 10
pg_stat_monitor.pgsm_track_utility = on
&lt;/pre&gt;
 &lt;h4&gt;存储健康诊断 – pg_checksums&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;数据完整性验证&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;# 启用校验和
initdb --data-checksums

# 离线验证
pg_checksums -c /var/lib/pgsql/15/data

# 输出示例
WARNING:  checksum verification failed in block 42 of relation base/16384/16895
Checksum scan completed
Data checksum version: 1
Files scanned:   892
Blocks scanned:  123456
Bad checksums:  1
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;修复策略&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;从备份恢复损坏数据页&lt;/li&gt;
  &lt;li&gt;使用pg_rewind 同步副本&lt;/li&gt;
  &lt;li&gt;启用 ZFS/Btrfs 文件系统自带校验&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;日志分析扩展 – pgBadger&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;报告生成&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;pgbadger /var/log/postgresql/postgresql-15-*.log -o report.html

# 关键分析维度：
# - 每小时请求量波动
# - 慢查询TOP 50
# - 错误类型分布
# - 连接池利用率
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;自动化监控&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;# 每日报告生成
0 3 * * * /usr/bin/pgbadger -q /var/log/postgresql/postgresql-15-*.log -O /reports

# 异常检测脚本
ALERT_SLOW=1000  # 超过1秒的查询
grep &amp;apos;duration: [0-9]\{4\}\.&amp;apos; postgresql.log | mail -s &amp;quot;慢查询警报&amp;quot; dba@example.com
&lt;/pre&gt;
 &lt;h4&gt;监控体系集成方案&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;Prometheus + Grafana 监控栈&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;exporter:
  - pg_exporter: 采集基础指标
  - pg_stat_monitor_exporter: 事务级指标
dashboard:
  - 关键指标:
    * 查询吞吐量: sum(rate(pg_stat_statements_calls[5m])) 
    * 缓存命中率: pg_stat_database_blks_hit / (pg_stat_database_blks_hit + pg_stat_database_blks_read)
    * 连接池利用率: pg_stat_activity_count{state=&amp;quot;active&amp;quot;} / max_connections
alert:
  - 规则示例:
    - alert: HighCPUWait
      expr: rate(pg_wait_sampling_samples_total{event=&amp;quot;CPU&amp;quot;}[5m]) &amp;lt; 0.1
      for: 10m
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;企业级监控架构&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="800" src="http://www.biaodianfu.com/wp-content/uploads/2025/04/Prometheus-Grafana.png" width="635"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h4&gt;诊断优化最佳实践&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;三级诊断流程&lt;/strong&gt;：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="792" src="http://www.biaodianfu.com/wp-content/uploads/2025/04/flow.png" width="331"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;自动化优化建议&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;-- 使用hypopg创建虚拟索引
SELECT * FROM hypopg_create_index(&amp;apos;CREATE INDEX ON orders (user_id)&amp;apos;);

-- 验证索引效果
EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 123;

-- 正式创建
CREATE INDEX CONCURRENTLY orders_user_id_idx ON orders(user_id);
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;容量规划公式&lt;/strong&gt;：&lt;/p&gt;
 &lt;p&gt;所需内存 = shared_buffers + (work_mem * max_connections) +&lt;/p&gt;
 &lt;p&gt;(maintenance_work_mem * 并行维护任务数) +&lt;/p&gt;
 &lt;p&gt;temp_buffers&lt;/p&gt;
 &lt;p&gt;建议比例: shared_buffers = 25% 总内存&lt;/p&gt;
 &lt;p&gt;通过组合使用监控诊断扩展，某金融系统实现了：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;故障平均恢复时间（MTTR）从 4 小时降至 15 分钟&lt;/li&gt;
  &lt;li&gt;查询性能瓶颈定位效率提升 6 倍&lt;/li&gt;
  &lt;li&gt;存储异常检测准确率达到9%&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;建议每周生成《数据库健康报告》，包含关键指标趋势、TOP 资源消耗语句、容量预测等内容，并结合 pg_qualstats 和 pg_wait_sampling 进行预防性优化。&lt;/p&gt;
 &lt;h2&gt;PostgreSQL的FDW&lt;/h2&gt;
 &lt;p&gt;PostgreSQL 的外部数据包装器（Foreign Data Wrapper, FDW）是一项强大的功能，允许用户将外部数据源（如其他数据库、文件或 API）集成到本地数据库中，实现跨数据源的联邦查询。&lt;/p&gt;
 &lt;p&gt;PostgreSQL 的 FDW 打破了数据孤岛，使其成为数据联邦的核心枢纽。通过合理使用查询下推、物化缓存和并行处理，可有效提升跨数据源查询效率。企业实践中，FDW 常用于混合云数据集成、实时分析平台构建及遗留系统迁移等场景。建议结合 EXPLAIN 分析执行计划，持续优化外部查询性能。&lt;/p&gt;
 &lt;h3&gt;FDW 核心架构&lt;/h3&gt;
 &lt;h4&gt;SQL/MED 标准实现&lt;/h4&gt;
 &lt;p&gt;FDW 基于 SQL 管理外部数据（SQL/MED）标准，通过以下组件实现数据联邦：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;Foreign Server&lt;/strong&gt;：定义外部数据源的连接信息（如 IP、端口）。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;User Mapping&lt;/strong&gt;：配置访问外部数据源的认证信息。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;Foreign Table&lt;/strong&gt;：映射外部数据的元数据（表结构）。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;Wrapper 扩展&lt;/strong&gt;：实现与特定数据源的通信协议。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;执行流程&lt;/h4&gt;
 &lt;p&gt;  &lt;img alt="" height="642" src="http://www.biaodianfu.com/wp-content/uploads/2025/04/fdw.png" width="1200"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h4&gt;常用 FDW 扩展&lt;/h4&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;扩展名称&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;数据源类型&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;关键特性&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;postgres_fdw&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;PostgreSQL&lt;/td&gt;
   &lt;td&gt;支持查询下推、JOIN 优化&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;mysql_fdw&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;MySQL&lt;/td&gt;
   &lt;td&gt;兼容 5.6+，支持批量插入&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;file_fdw&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;CSV/文本文件&lt;/td&gt;
   &lt;td&gt;无依赖，轻量级文件访问&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;mongo_fdw&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;MongoDB&lt;/td&gt;
   &lt;td&gt;支持 BSON 到 JSONB 转换&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;clickhousedb_fdw&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;ClickHouse&lt;/td&gt;
   &lt;td&gt;列式存储优化，高性能分析&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;multicorn&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;Python 扩展&lt;/td&gt;
   &lt;td&gt;可自定义包装器（如 REST API 访问）&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;h3&gt;FDW 使用详解&lt;/h3&gt;
 &lt;h4&gt;安装与配置&lt;/h4&gt;
 &lt;p&gt;以 postgres_fdw（连接其他 PostgreSQL 实例）为例：&lt;/p&gt;
 &lt;pre&gt;-- 启用扩展
CREATE EXTENSION postgres_fdw;

-- 定义外部服务器
CREATE SERVER foreign_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host &amp;apos;192.168.1.100&amp;apos;, port &amp;apos;5432&amp;apos;, dbname &amp;apos;remote_db&amp;apos;);

-- 创建用户映射
CREATE USER MAPPING FOR local_user
SERVER foreign_server
OPTIONS (user &amp;apos;remote_user&amp;apos;, password &amp;apos;secret&amp;apos;);

-- 创建外部表
CREATE FOREIGN TABLE remote_orders (
    order_id INT,
    product TEXT,
    amount NUMERIC
) SERVER foreign_server
OPTIONS (schema_name &amp;apos;public&amp;apos;, table_name &amp;apos;orders&amp;apos;);
&lt;/pre&gt;
 &lt;h4&gt;查询外部数据&lt;/h4&gt;
 &lt;pre&gt;-- 直接查询
SELECT * FROM remote_orders WHERE amount &amp;gt; 1000;

-- 联邦查询（跨本地与外部表）
SELECT l.customer_name, r.product 
FROM local_customers l
JOIN remote_orders r ON l.id = r.customer_id;
&lt;/pre&gt;
 &lt;h4&gt;监控与管理&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;系统视图&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;-- 查看外部表信息
SELECT * FROM pg_foreign_table;

-- 监控外部查询
SELECT * FROM pg_stat_user_tables 
WHERE schemaname = &amp;apos;public&amp;apos; 
AND relname LIKE &amp;apos;foreign_%&amp;apos;;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;日志分析&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;# postgresql.conf
log_statement = &amp;apos;ddl&amp;apos;
log_foreign_server = on
&lt;/pre&gt;
 &lt;h4&gt;性能优化策略&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;减少数据传输&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;投影下推：仅 SELECT 必要字段。&lt;/li&gt;
  &lt;li&gt;谓词下推：确保 WHERE 条件在远程执行。&lt;/li&gt;
  &lt;li&gt;聚合下推：使用远程聚合减少数据量。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;缓存策略&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;物化视图：定期刷新外部数据快照。&lt;/li&gt;
&lt;/ul&gt;
 &lt;pre&gt;CREATE MATERIALIZED VIEW cached_orders AS 
SELECT * FROM remote_orders;
REFRESH MATERIALIZED VIEW CONCURRENTLY cached_orders;
&lt;/pre&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;连接池&lt;/strong&gt;：使用pgbouncer 管理外部连接。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;并行查询&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;-- 启用并行扫描
ALTER FOREIGN TABLE remote_orders
OPTIONS (ADD parallel_workers &amp;apos;4&amp;apos;);

-- 设置并行度
SET max_parallel_workers_per_gather = 4;
&lt;/pre&gt;
 &lt;h3&gt;FDW 核心特性&lt;/h3&gt;
 &lt;h4&gt;查询下推（Pushdown）&lt;/h4&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;条件过滤&lt;/strong&gt;：将 WHERE 子句发送至远程执行。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;聚合操作&lt;/strong&gt;：远程执行 COUNT、SUM 等聚合。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;排序分页&lt;/strong&gt;：ORDER BY 和 LIMIT 下推。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;示例（查看下推效果）：&lt;/p&gt;
 &lt;pre&gt;EXPLAIN VERBOSE 
SELECT * FROM remote_orders 
WHERE amount &amp;gt; 1000 
ORDER BY order_date 
LIMIT 10;
-- 输出中显示 remote SQL: SELECT ... WHERE (amount &amp;gt; 1000) ORDER BY order_date LIMIT 10
&lt;/pre&gt;
 &lt;h4&gt;事务支持&lt;/h4&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;默认行为&lt;/strong&gt;：多数 FDW 不支持分布式事务（如postgres_fdw 支持单语句事务）。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;跨库事务&lt;/strong&gt;：需外部数据源支持两阶段提交。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;数据类型映射&lt;/h4&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;自动转换&lt;/strong&gt;：匹配同名数据类型（如 INTEGER、TEXT）。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;手动映射&lt;/strong&gt;：通过ALTER FOREIGN TABLE 调整类型。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;FDW 的限制与应对&lt;/h4&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;限制项&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;应对策略&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;事务支持有限&lt;/td&gt;
   &lt;td&gt;使用最终一致性设计，避免跨库事务&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;复杂查询性能低&lt;/td&gt;
   &lt;td&gt;下推优化 + 本地物化缓存&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;数据类型不兼容&lt;/td&gt;
   &lt;td&gt;自定义类型转换函数&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;连接稳定性&lt;/td&gt;
   &lt;td&gt;超时重试机制 + 连接池&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;h3&gt;FDW 使用案例&lt;/h3&gt;
 &lt;h4&gt;跨国零售集团实时库存联邦查询&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;技术架构&lt;/strong&gt;：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="443" src="http://www.biaodianfu.com/wp-content/uploads/2025/04/fdw-demo.png" width="1294"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;实现方案&lt;/strong&gt;：&lt;/p&gt;
 &lt;p&gt;创建跨区域商品视图：&lt;/p&gt;
 &lt;pre&gt;CREATE VIEW global_inventory AS
SELECT &amp;apos;asia&amp;apos; region, * FROM asia_items
UNION ALL 
SELECT &amp;apos;europe&amp;apos;, * FROM europe_items
UNION ALL
SELECT &amp;apos;america&amp;apos;, * FROM oracle_items;
实时库存调配查询：
SELECT sku, sum(stock) 
FROM global_inventory 
WHERE warehouse IN (&amp;apos;hk&amp;apos;,&amp;apos;london&amp;apos;,&amp;apos;nyc&amp;apos;)
GROUP BY sku
HAVING sum(stock) &amp;lt; 100;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;效果&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;查询响应时间：从 ETL 小时级 → 实时2s&lt;/li&gt;
  &lt;li&gt;库存周转率提升 23%&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;金融风控系统多源数据关联&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;数据整合&lt;/strong&gt;：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;数据源&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;FDW 类型&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;数据量&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;更新频率&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;客户基本信息&lt;/td&gt;
   &lt;td&gt;Oracle FDW&lt;/td&gt;
   &lt;td&gt;5000万&lt;/td&gt;
   &lt;td&gt;实时&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;交易记录&lt;/td&gt;
   &lt;td&gt;Kafka FDW&lt;/td&gt;
   &lt;td&gt;1亿/日&lt;/td&gt;
   &lt;td&gt;流式&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;外部征信数据&lt;/td&gt;
   &lt;td&gt;REST FDW&lt;/td&gt;
   &lt;td&gt;API调用&lt;/td&gt;
   &lt;td&gt;按需&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;  &lt;strong&gt;风控规则示例&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;SELECT 
    o.customer_id,
    COUNT(t.*) FILTER (WHERE t.amount &amp;gt; 100000) AS big_txns,
    r.credit_score
FROM oracle_customers o
JOIN kafka_transactions t USING (customer_id)
JOIN rest_credit_report r USING (ssn)
WHERE o.country = &amp;apos;US&amp;apos; 
  AND t.tx_time &amp;gt; NOW() - INTERVAL &amp;apos;7 days&amp;apos;
GROUP BY 1,3
HAVING COUNT(t.*) &amp;gt; 5 OR r.credit_score &amp;lt; 600;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;成果&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;欺诈检测准确率提升 18%&lt;/li&gt;
  &lt;li&gt;每秒处理 8500 条实时交易&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;物联网平台多协议数据汇聚&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;架构实现&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;# 使用 Multicorn 自定义 FDW
class IoTFDW(ForeignDataWrapper):
    def execute(self, quals, columns):
        # 同时从 MQTT、CoAP、LoRaWAN 获取数据
        yield from mqtt_client.query(quals)
        yield from coap_server.fetch(columns)
        yield from lora_gateway.scan()
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;设备数据查询&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;-- 查询温度异常的工业设备
SELECT device_id, MAX(temp) 
FROM iot_sensors 
WHERE protocol = &amp;apos;lora&amp;apos; 
  AND ts BETWEEN &amp;apos;2023-08-01&amp;apos; AND &amp;apos;2023-08-07&amp;apos;
GROUP BY device_id
HAVING MAX(temp) &amp;gt; 90;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;性能指标&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;支持 120 万台设备并发接入&lt;/li&gt;
  &lt;li&gt;数据延迟 &amp;lt; 800ms (P95)&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;媒体内容推荐系统&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;数据源整合&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;用户画像：MongoDB → 通过mongo_fdw 映射&lt;/li&gt;
  &lt;li&gt;行为日志：ClickHouse → clickhousedb_fdw&lt;/li&gt;
  &lt;li&gt;内容元数据：本地 PostgreSQL 表&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;混合推荐算法&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;WITH user_embedding AS (
    SELECT vector 
    FROM mongo_profiles 
    WHERE user_id = 123
),
content_features AS (
    SELECT id, title_embedding 
    FROM local_contents
)
SELECT 
    c.id,
    c.title,
    (c.title_embedding &amp;lt;-&amp;gt; u.vector) AS similarity
FROM content_features c
CROSS JOIN user_embedding u
ORDER BY 3 ASC
LIMIT 10;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;业务提升&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;CTR（点击率）提升 34%&lt;/li&gt;
  &lt;li&gt;推荐计算耗时从 6s → 920ms&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;航空运营分析平台&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;多模态数据联邦&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;-- 联邦查询示例
SELECT 
    f.flight_no,
    w.wind_speed,
    m.maintenance-&amp;gt;&amp;apos;last_check&amp;apos; AS last_maint,
    AVG(passenger_count) OVER (
        PARTITION BY route 
        ORDER BY dep_time 
        ROWS 7 PRECEDING
    ) AS avg_passengers
FROM postgres_fdw_flights f
JOIN s3_fdw_weather w 
  ON f.dep_airport = w.station_id 
 AND f.dep_time BETWEEN w.start AND w.end
JOIN mongo_fdw_maintenance m 
  ON f.aircraft_id = m.aircraft-&amp;gt;&amp;gt;&amp;apos;id&amp;apos;
WHERE f.status = &amp;apos;completed&amp;apos;;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;数据规模&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;实时处理 4000+ 航班/天&lt;/li&gt;
  &lt;li&gt;关联 10TB 历史气象数据&lt;/li&gt;
  &lt;li&gt;查询性能：复杂分析2s (vs 原 ETL 方案 25 分钟)&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;游戏玩家跨服对战系统&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;技术方案&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;每个游戏分区使用独立 PostgreSQL 实例&lt;/li&gt;
  &lt;li&gt;通过postgres_fdw 建立跨服视图：&lt;/li&gt;
&lt;/ul&gt;
 &lt;pre&gt;CREATE FOREIGN TABLE jp_players (...) SERVER jp_node;
CREATE FOREIGN TABLE na_players (...) SERVER na_node;

-- 全服玩家排行榜
SELECT region, player_id, score 
FROM jp_players 
UNION ALL
SELECT region, player_id, score
FROM na_players
ORDER BY score DESC 
LIMIT 100;
&lt;/pre&gt;
 &lt;ul&gt;
  &lt;li&gt;实时跨服匹配：&lt;/li&gt;
&lt;/ul&gt;
 &lt;pre&gt;SELECT 
    a.player_id AS p1,
    b.player_id AS p2,
    ABS(a.skill_level - b.skill_level) AS diff 
FROM global_players a
JOIN global_players b 
  ON a.region &amp;lt;&amp;gt; b.region 
 AND a.game_mode = b.game_mode
WHERE a.status = &amp;apos;waiting&amp;apos; 
  AND b.status = &amp;apos;waiting&amp;apos;
ORDER BY diff
LIMIT 100;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;成果&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;匹配延迟从 6s → 320ms&lt;/li&gt;
  &lt;li&gt;跨服对战参与率提升 41%&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;政府政务数据开放平台&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;安全架构&lt;/strong&gt;：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="406" src="http://www.biaodianfu.com/wp-content/uploads/2025/04/fdw-2.png" width="1302"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;行级安全控制&lt;/strong&gt;：&lt;/p&gt;
 &lt;pre&gt;-- 创建安全视图
CREATE VIEW citizen_data AS
SELECT * FROM fdw_census 
WHERE city = current_setting(&amp;apos;user.city&amp;apos;);

-- 列级脱敏
CREATE FOREIGN TABLE fdw_tax (
    ssn TEXT,
    income NUMERIC,
    mask_ssn TEXT OPTIONS (mask &amp;apos;partial(0,4,&amp;apos;&amp;apos;XXXX&amp;apos;&amp;apos;)&amp;apos;)
) SERVER tax_server;

-- 查询示例
SELECT mask_ssn, income 
FROM fdw_tax 
WHERE income &amp;gt; 100000;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;成效&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;数据开放种类从 15 类 → 127 类&lt;/li&gt;
  &lt;li&gt;跨部门查询响应速度提升 18 倍&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;关键成功要素&lt;/h4&gt;
 &lt;ul&gt;
  &lt;li&gt;查询下推优化：通过EXPLAIN VERBOSE 验证 80% 以上条件过滤在源端执行&lt;/li&gt;
  &lt;li&gt;混合存储策略：热数据缓存（物化视图）+ 冷数据直连&lt;/li&gt;
  &lt;li&gt;连接池管理：使用pgbouncer 控制外部连接数在 50 以内&lt;/li&gt;
  &lt;li&gt;类型转换优化：为 JSONB 字段创建 GIN 索引加速查询&lt;/li&gt;
  &lt;li&gt;安全隔离：为每个 FDW 创建单独角色和权限&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;性能对比数据&lt;/h4&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;    &lt;strong&gt;场景&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;传统ETL方案&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;FDW联邦查询&lt;/strong&gt;&lt;/td&gt;
   &lt;td&gt;    &lt;strong&gt;提升倍数&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;跨库JOIN(千万级)&lt;/td&gt;
   &lt;td&gt;12min&lt;/td&gt;
   &lt;td&gt;8.5s&lt;/td&gt;
   &lt;td&gt;85x&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;实时数据更新&lt;/td&gt;
   &lt;td&gt;小时级延迟&lt;/td&gt;
   &lt;td&gt;亚秒级&lt;/td&gt;
   &lt;td&gt;3600x&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;开发维护成本&lt;/td&gt;
   &lt;td&gt;15人月/年&lt;/td&gt;
   &lt;td&gt;3人月/年&lt;/td&gt;
   &lt;td&gt;5x&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;这些案例展现了 FDW 在构建现代数据架构中的核心价值：消除数据孤岛，释放数据流动性，同时保持查询的实时性与一致性。建议在实施时结合 pg_stat_activity 监控外部查询，并通过 pg_statio_user_tables 分析 IO 瓶颈，持续优化联邦查询性能。&lt;/p&gt;
 &lt;p&gt;参考链接：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;a href="https://pigsty.io/zh/blog/pg/pg-eat-db-world/"&gt;PostgreSQL正在吞噬数据库世界 | Pigsty&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://medium.com/@fengruohang/postgres-is-eating-the-database-world-157c204dcfc4"&gt;Postgres is eating the database world | by Vonng | Medium&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://ossrank.com/cat/368-postgresql-extension"&gt;PostgreSQL Ecosystem – OSSRank&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://github.com/Vonng/pigsty/discussions/333"&gt;Call for New PostgreSQL Extensions Vonng/pigsty · Discussion #333 · GitHub&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://gist.github.com/joelonsql/e5aa27f8cc9bd22b8999b7de8aee9d47"&gt;1000+ PostgreSQL EXTENSIONs GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;div&gt;

  &lt;strong&gt;相关文章:&lt;/strong&gt;  &lt;ol&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/sql-date-and-time-functions.html" rel="bookmark" title="SQL &amp;#26085;&amp;#26399;/&amp;#26102;&amp;#38388;&amp;#22788;&amp;#29702;&amp;#20989;&amp;#25968;"&gt;SQL 日期/时间处理函数&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/hive-sql-guide.html" rel="bookmark" title="Hive SQL&amp;#31995;&amp;#32479;&amp;#21270;&amp;#23398;&amp;#20064;"&gt;Hive SQL系统化学习&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/spark-sql.html" rel="bookmark" title="Spark SQL &amp;#31995;&amp;#32479;&amp;#21270;&amp;#23398;&amp;#20064;"&gt;Spark SQL 系统化学习&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>器→工具 工具软件 postgresql</category>
      <guid isPermaLink="true">https://itindex.net/detail/63001-%E6%95%B0%E6%8D%AE%E5%BA%93-%E6%9C%AA%E6%9D%A5-postgresql</guid>
      <pubDate>Mon, 07 Apr 2025 20:44:25 CST</pubDate>
    </item>
    <item>
      <title>MySQL大数据表处理策略，原来一直都用错了</title>
      <link>https://itindex.net/detail/62962-mysql-%E5%A4%A7%E6%95%B0%E6%8D%AE-%E7%AD%96%E7%95%A5</link>
      <description>&lt;p&gt; &lt;/p&gt;  &lt;p&gt;当我们业务数据库表中的数据越来越多，如果你也和我遇到了以下类似场景，那让我们一起来解决这个问题。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;数据的插入，查询时长较长&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;后续业务需求的扩展，在表中新增字段，影响较大&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;表中的数据并不是所有的都为有效数据 ，需求只查询时间区间内的&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;strong&gt;评估表数据体量&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;我们可以从表容量/磁盘空间/实例容量三方面评估数据体量，接下来让我们分别展开来看看。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;   &lt;strong&gt;1.表容量&lt;/strong&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;表容量主要从表的记录数、平均长度、增长量、读写量、总大小量进行评估。一般对于OLTP的表，建议单表不要超过2000W行数据量，总大小15G以内。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;访问量：单表读写量在1600/s以内&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;查询行数据的方式：我们一般查询表数据有多少数据时用到的经典sql语句如下。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;select count(*) from table&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;select count(1) from table&lt;/p&gt;      &lt;p&gt; &lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;但是当数据量过大的时候，这样的查询就可能会超时，所以我们要换一种查询方式。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;use 库名&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;show table status like &amp;apos;表名&amp;apos; ; 或 show table status like &amp;apos;表名&amp;apos;\G ;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;上述方法不仅可以查询表的数据，还可以输出表的详细信息 , 加 \G 可以格式化输出。包括表名、存储引擎、版本、行数、每行的字节数等等，大家可以自行试一下哈。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;   &lt;strong&gt;2.磁盘空间&lt;/strong&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;查看指定数据库容量大小&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;&lt;/ul&gt;  &lt;pre&gt;    &lt;code&gt;select&lt;/code&gt;    &lt;code&gt;table_schemaas&amp;apos;数据库&amp;apos;,&lt;/code&gt;    &lt;code&gt;table_nameas&amp;apos;表名&amp;apos;,&lt;/code&gt;    &lt;code&gt;table_rowsas&amp;apos;记录数&amp;apos;,&lt;/code&gt;    &lt;code&gt;truncate(data_length/1024/1024,2)as&amp;apos;数据容量(MB)&amp;apos;,&lt;/code&gt;    &lt;code&gt;truncate(index_length/1024/1024,2)as&amp;apos;索引容量(MB)&amp;apos;&lt;/code&gt;    &lt;code&gt;frominformation_schema.tables&lt;/code&gt;    &lt;code&gt;orderbydata_lengthdesc, index_lengthdesc;&lt;/code&gt;&lt;/pre&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;查询单个库中所有表磁盘占用大小&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;&lt;/ul&gt;  &lt;pre&gt;    &lt;code&gt;select&lt;/code&gt;    &lt;code&gt;table_schemaas&amp;apos;数据库&amp;apos;,&lt;/code&gt;    &lt;code&gt;table_nameas&amp;apos;表名&amp;apos;,&lt;/code&gt;    &lt;code&gt;table_rowsas&amp;apos;记录数&amp;apos;,&lt;/code&gt;    &lt;code&gt;truncate(data_length/1024/1024,2)as&amp;apos;数据容量(MB)&amp;apos;,&lt;/code&gt;    &lt;code&gt;truncate(index_length/1024/1024,2)as&amp;apos;索引容量(MB)&amp;apos;&lt;/code&gt;    &lt;code&gt;frominformation_schema.tables&lt;/code&gt;    &lt;code&gt;wheretable_schema=&amp;apos;mysql&amp;apos;&lt;/code&gt;    &lt;code&gt;orderbydata_lengthdesc, index_lengthdesc;&lt;/code&gt;&lt;/pre&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;查询出的结果如下：&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;img src="https://p3-sign.toutiaoimg.com/tos-cn-i-axegupay5k/6e1c790e251f44d3b4d0cda655a78cbf~tplv-tt-origin-web:gif.jpeg?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1736235088&amp;x-signature=t6YoyIWrmNsvU2QfKPiYqg%2FPJdA%3D"&gt;&lt;/img&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;建议数据量占磁盘使用率的70%以内。同时，对于一些数据增长较快，可以考虑使用大的慢盘进行数据归档（归档可以参考方案三）。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;   &lt;strong&gt;3.实例容量&lt;/strong&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;MySQL是基于线程的服务模型，因此在一些并发较高的场景下，单实例并不能充分利用服务器的CPU资源，吞吐量反而会卡在mysql层，可以根据业务考虑自己的实例模式。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;strong&gt;出现问题的原因&lt;/strong&gt;&lt;/p&gt;   &lt;p&gt; &lt;/p&gt;  &lt;p&gt;上面我们已经查到我们数据表的体量了，那么为什么    &lt;strong&gt;单表数据量越大，业务的执行效率就越慢&lt;/strong&gt;的根本原因是什么呢？&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;一个表的数据量达到好几千万或者上亿时，加索引的效果没那么明显啦。性能之所以会变差，是因为维护索引的B+树结构层级变得更高了，查询一条数据时，需要经历的磁盘IO变多，因此查询性能变慢。    &lt;br /&gt; &lt;/p&gt;  &lt;p&gt;    &lt;strong&gt;大家是否还记得，一个B+树大概可以存放多少数据量呢？&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;InnoDB存储引擎最小储存单元是页，一页大小就是16k。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;B+树叶子存的是数据，内部节点存的是键值+指针。索引组织表通过非叶子节点的二分查找法以及指针确定数据在哪个页中，进而再去数据页中找到需要的数据；&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;img src="https://p3-sign.toutiaoimg.com/tos-cn-i-6w9my0ksvp/2a2317b9f16244319c03287195048c76~tplv-tt-origin-web:gif.jpeg?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1736235088&amp;x-signature=sSdA4lvuUezq%2BGf2KoveijLHHEs%3D"&gt;&lt;/img&gt;&lt;/p&gt;  &lt;p&gt;假设B+树的高度为2的话，即有一个根结点和若干个叶子结点。这棵B+树的存放总记录数为=根结点指针数*单个叶子节点记录行数。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;如果一行记录的数据大小为1k，那么单个叶子节点可以存的记录数 =16k/1k =16.&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;非叶子节点内存放多少指针呢？        &lt;strong&gt;我们假设主键ID为bigint类型，长度为8字节(面试官问你int类型，一个int就是32位，4字节)&lt;/strong&gt;，而指针大小在InnoDB源码中设置为6字节，所以就是8+6=14字节，16k/14B =16*1024B/14B = 1170&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;因此，一棵高度为2的B+树，能存放1170 * 16=18720条这样的数据记录。同理一棵高度为3的B+树，能存放1170 *1170 *16 =21902400，也就是说，可以存放两千万左右的记录。B+树高度一般为1-3层，已经满足千万级别的数据存储。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;如果B+树想存储更多的数据，那树结构层级就会更高，查询一条数据时，需要经历的磁盘IO变多，因此查询性能变慢。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;strong&gt;如何解决单表数据量太大，查询变慢的问题&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;知道了根本原因之后，我们就需要考虑如何优化数据库来解决问题了。这里提供了三种解决方案，包括数据表分区、分库分表、冷热数据归档，了解完这些方案之后大家可以选取适合自己业务的方案。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;   &lt;strong&gt;方案一：数据表分区&lt;/strong&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;为什么要分区：表分区可以在区间内查询对应的数据，降低查询范围，并且索引分区也可以进一步提高命中率，提升查询效率。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;分区是指将一个表的数据按照条件分布到不同的文件上面，未分区前都是存放在一个文件上面的，但是它还是指向的同一张表，只是把数据分散到了不同文件而已。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;我们首先看一下分区有什么优缺点：&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;strong&gt;1. 表分区有什么好处？&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;与单个磁盘或文件系统分区相比，可以        &lt;strong&gt;存储更多的数据&lt;/strong&gt;。&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;对于那些已经失去保存意义的数据，通常可以通过删除与那些数据有关的分区，很容易地删除那些数据。相反地，在某些情况下，添加新数据的过程又可以通过为那些新数据专门        &lt;strong&gt;增加一个新的分区&lt;/strong&gt;，来很方便地实现。&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;一些查询可以得到极大优化&lt;/strong&gt;，这主要是借助于满足一个给定WHERE语句的数据可以只保存在一个或多个分区内，这样在查找时就不用查找其他剩余的分区。因为分区可以在创建了分区表后进行修改，所以在第一次配置分区方案时还不曾这么做时，可以重新组织数据，来提高那些常用查询的效率。&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;涉及到例如SUM()和COUNT()这样聚合函数的查询，可以很容易地进行        &lt;strong&gt;并行处理&lt;/strong&gt;。这种查询的一个简单例子如 “SELECT salesperson_id, COUNT (orders) as order_total FROM sales GROUP BY salesperson_id；”。通过“并行”，这意味着该查询可以在每个分区上同时进行，最终结果只需通过总计所有分区得到的结果。&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;通过        &lt;strong&gt;跨多个磁盘来分散数据查询&lt;/strong&gt;，来获得更大的查询吞吐量。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;strong&gt;2. 表分区的限制因素&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;一个表最多只能有        &lt;strong&gt;1024个分区&lt;/strong&gt;。&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;MySQL5.1中，        &lt;strong&gt;分区表达式必须是整数，或者返回整数的表达式&lt;/strong&gt;。在MySQL5.5中提供了非整数表达式分区的支持。&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;如果分区字段中有主        &lt;strong&gt;键或者唯一索引的列&lt;/strong&gt;，那么所有主键列和唯一索引列都必须包含进来。即：分区字段要么不包含主键或者索引列，要么包含全部主键和索引列。&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;分区表中        &lt;strong&gt;无法使用外键约束&lt;/strong&gt;。&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;MySQL的分区        &lt;strong&gt;适用于一个表的所有数据和索引&lt;/strong&gt;，不能只对表数据分区而不对索引分区，也不能只对索引分区而不对表分区，也不能只对表的一部分数据分区。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;在进行分区之前可以用如下方法，看下数据库表是否支持分区。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;    &lt;li&gt; &lt;/li&gt;&lt;/ul&gt;  &lt;pre&gt;    &lt;code&gt;mysql&amp;gt; show variables like&amp;apos;%partition%&amp;apos;;&lt;/code&gt;    &lt;code&gt;+-------------------+-------+&lt;/code&gt;    &lt;code&gt;| Variable_name     |Value|&lt;/code&gt;    &lt;code&gt;+-------------------+-------+&lt;/code&gt;    &lt;code&gt;|have_partitioning| YES   |&lt;/code&gt;    &lt;code&gt;+-------------------+-------+&lt;/code&gt;    &lt;code&gt;1rowinset (0.00sec)&lt;/code&gt;&lt;/pre&gt;  &lt;p&gt; &lt;/p&gt;   &lt;strong&gt;方案二：数据库分表&lt;/strong&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;为什么要分表：分表后，显而易见，单表数据量降低，树的高度变低，查询经历的磁盘io变少，则可以提高效率。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;mysql 分表分为两种，水平分表和垂直分表。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;分库分表就是为了解决由于数据量过大而导致数据库性能降低的问题，将原来独立的数据库拆分成若干数据库组成 ，将数据大表拆分成若干数据表组成，使得单一数据库、单一数据表的数据量变小，从而达到提升数据库性能的目的。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;水平分表&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;定义：数据表行的拆分，通俗点就是把数据按照某些规则拆分成多张表或者多个库来存放。分为库内分表和分库。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;比如一个表有4000万数据，查询很慢，可以分到四个表，每个表有1000万数据&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;img src="https://p3-sign.toutiaoimg.com/tos-cn-i-6w9my0ksvp/d602fec2245946a8bdb259e3701ce709~tplv-tt-origin-web:gif.jpeg?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1736235088&amp;x-signature=eELX%2FOE2KUCGRZ4YgYDuiwkWnyI%3D"&gt;&lt;/img&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;垂直分表&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;定义：列的拆分，根据表之间的相关性进行拆分。常见的就是一个表把不常用的字段和常用的字段就行拆分，然后利用主键关联。或者一个数据库里面有订单表和用户表，数据量都很大，进行垂直拆分，用户库存用户表的数据，订单库存订单表的数据。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;img src="https://p3-sign.toutiaoimg.com/tos-cn-i-6w9my0ksvp/4bdf27de3a8440b983ea75be4f8a536b~tplv-tt-origin-web:gif.jpeg?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1736235088&amp;x-signature=swKX56rSPNQ4N7ik1yrmWQ7bM%2Fo%3D"&gt;&lt;/img&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;缺点：垂直分隔的缺点比较明显，数据不在一张表中，会增加join 或 union之类的操作。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;知道了两个知识后，我们来看一下分库分表的方案。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;strong&gt;1. 取模方案&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;拆分之前，先预估一下数据量。比如用户表有4000w数据，现在要把这些数据分到4个表user1 user2  uesr3 user4。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;比如id = 17，17对4取模为1，加上 ，所以这条数据存到user2表。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;注意：进行水平拆分后的表要去掉auto_increment自增长。这时候的id可以用一个id 自增长临时表获得，或者使用  redis incr的方法。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;img src="https://p3-sign.toutiaoimg.com/tos-cn-i-6w9my0ksvp/4e76a78280394302891d8986152fae38~tplv-tt-origin-web:gif.jpeg?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1736235088&amp;x-signature=zVKhX9c1lGmUJ8GzrsDhsc8nIBM%3D"&gt;&lt;/img&gt;&lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;优点：&lt;/strong&gt;数据均匀分到各个表中，出现热点问题的概率很低。&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;缺点：&lt;/strong&gt;以后的数据扩容迁移比较困难，当数据量变大之后，以前分到4个表现在要分到8个表，取模的值就变了，需要重新进行数据迁移。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;strong&gt;2. range 范围方案&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;以范围进行拆分数据，就是在某个范围内的订单，存放到某个表中。比如id=12存放到user1表，id=1300万的存放到user2 表。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;img src="https://p3-sign.toutiaoimg.com/tos-cn-i-6w9my0ksvp/bfb7809f78bf45ba9ce4199ee9a0af0c~tplv-tt-origin-web:gif.jpeg?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1736235088&amp;x-signature=8aAWHZ45EpS04YA%2F95N4aZA8HdE%3D"&gt;&lt;/img&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;优点：&lt;/strong&gt;有利于将来对数据的扩容。&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;缺点：&lt;/strong&gt;如果热点数据都存在一个表中，则压力都在一个表中，其他表没有压力。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;我们看到以上两种方案都存在缺点，但是却又是互补的，那么我们将这两个方案结合会怎样呢？&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;strong&gt;3. hash取模和range方案结合&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;如下图，我们可以看到 group 组存放id 为0~4000万的数据，然后有三个数据库 DB0、DB1、DB2，DB0里面有四个数据库，DB1 和DB2 有三个数据库。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;假如id为15000 然后对10取模（为啥对10 取模 因为有10个表），取0 然后 落在DB_0，然后再根据range 范围，落在Table_0 里面。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;img src="https://p3-sign.toutiaoimg.com/tos-cn-i-6w9my0ksvp/4bd53f846cd94958a48f0a3b7c9b925f~tplv-tt-origin-web:gif.jpeg?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1736235088&amp;x-signature=f6NKGRGzQnN0EU6ODDbMrXE04yQ%3D"&gt;&lt;/img&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;总结：采用hash取模和range方案结合，既可以避免热点数据的问题，也有利于将来对数据的扩容。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;我们已经了解了 mysql分区和分表的知识，那我们看一下这    &lt;strong&gt;两个技术有何不同以及适用场景&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;strong&gt;1）分区分表的区别：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;实现方式：&lt;/strong&gt;mysql的        &lt;strong&gt;分表是真正的分表&lt;/strong&gt;，一张表分成很多表后，每一个小表都是完整的一张表，都对应三个文件，一个.MYD数据文件，.MYI索引文件，.frm表结构；分区不一样，        &lt;strong&gt;一张大表进行分区后，他还是一张表&lt;/strong&gt;，不会变成二张表，但是他存放数据的区块变多了。&lt;/p&gt;      &lt;p&gt; &lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;提高性能：&lt;/strong&gt;        &lt;strong&gt;分表&lt;/strong&gt;重点是存取数据时，如何提高mysql并发能力上；而        &lt;strong&gt;分区&lt;/strong&gt;呢，如何突破磁盘的读写能力，从而达到提高mysql性能的目的。&lt;/p&gt;      &lt;p&gt; &lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;实现的难易度：&lt;/strong&gt;        &lt;strong&gt;分表&lt;/strong&gt;的方法有很多，用merge来分表，是最简单的一种方式。这种方式根分区难易度差不多，并且对程序代码来说可以做到透明的。如果是用其他分表方式就比分区麻烦了。        &lt;strong&gt;分区&lt;/strong&gt;实现是比较简单的，建立分区表，根建平常的表没什么区别，并且对开代码端来说是透明的。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;strong&gt;2）分区分表的联系：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;都能提高mysql的性能，在高并发状态下都有一个良好的表现。&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;分表和分区不矛盾，可以相互配合的，对于那些大访问量，并且表数据比较多的表，我们可以采取分表和分区结合的方式，访问量不大，但是表数据很多的表，我们可以采取分区的方式等。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;strong&gt;3）分库分表存在的问题：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;事务问题&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;在执行分库分表之后，由于数据存储到了不同的库上，数据库事务管理出现了困难。如果依赖数据库本身的分布式事务管理功能去执行事务，将付出高昂的性能代价；如果由应用程序去协助控制，形成程序逻辑上的事务，又会造成编程方面的负担。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;跨库跨表的join问题&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;在执行了分库分表之后，难以避免会将原本逻辑关联性很强的数据划分到不同的表、不同的库上，这时，表的关联操作将受到限制，我们无法join位于不同分库的表，也无法join分表粒度不同的表，结果原本一次查询能够完成的业务，可能需要多次查询才能完成。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;        &lt;strong&gt;额外的数据管理负担和数据运算压力&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;额外的数据管理负担，最显而易见的就是数据的定位问题和数据的增删改查的重复执行问题，这些都可以通过应用程序解决，但必然引起额外的逻辑运算，例如，对于一个记录用户成绩的用户数据表userTable，业务要求查出成绩最好的100位，在进行分表之前，只需一个order by语句就可以搞定，但是在进行分表之后，将需要n个order by语句，分别查出每一个分表的前100名用户数据，然后再对这些数据进行合并计算，才能得出结果。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;   &lt;strong&gt;方案三：冷热归档&lt;/strong&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;为什么要冷热归档：其实原因和方案二类似，都是降低单表数据量，树的高度变低，查询经历的磁盘io变少，则可以提高效率。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;如果大家的业务数据，有明显的冷热区分，比如：只需要展示近一周或一个月的数据。那么这种情况这一周和一个月的数据我们称之为热数据，其余数据为冷数据。那么我们可以将冷数据归档在其他的库表中，提高我们热数据的操作效率。&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;接下来讲一下归档的过程：&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;创建归档表：创建的归档表原则上要与原表保持一致&lt;/p&gt;&lt;/li&gt;    &lt;li&gt;      &lt;p&gt;归档表数据的初始化&lt;/p&gt;      &lt;p&gt; &lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;    &lt;img src="https://p3-sign.toutiaoimg.com/tos-cn-i-6w9my0ksvp/df5470e1bac749ab8dace2e55ccc0ccc~tplv-tt-origin-web:gif.jpeg?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1736235088&amp;x-signature=tA%2BN2%2FKwlXtALAvZbYnxRbhvUBs%3D"&gt;&lt;/img&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;业务增量数据处理过程&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;img src="https://p3-sign.toutiaoimg.com/tos-cn-i-6w9my0ksvp/b8109b88c6774774bff0483aafde735b~tplv-tt-origin-web:gif.jpeg?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1736235088&amp;x-signature=EwHrnucEib%2F0ijeMXMo7MbrIWbE%3D"&gt;&lt;/img&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;    &lt;li&gt;      &lt;p&gt;数据的获取过程&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;img src="https://p3-sign.toutiaoimg.com/tos-cn-i-6w9my0ksvp/ece9045ef44647949bd5ec2769ca66e0~tplv-tt-origin-web:gif.jpeg?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1736235088&amp;x-signature=WtwHZYacAiQ32u3x1rrilmajhcE%3D"&gt;&lt;/img&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;    &lt;strong&gt;以上三种方案我们如何选型&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;table&gt;    &lt;tr&gt;      &lt;td align="center" valign="top" width="60"&gt;        &lt;strong&gt;方案&lt;/strong&gt;&lt;/td&gt;      &lt;td align="center" valign="top" width="96"&gt;        &lt;strong&gt;使用场景&lt;/strong&gt;&lt;/td&gt;      &lt;td align="center" valign="top" width="135"&gt;        &lt;strong&gt;优点&lt;/strong&gt;&lt;/td&gt;      &lt;td align="center" valign="top" width="285"&gt;        &lt;strong&gt;缺点&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="60"&gt;数据表分区&lt;/td&gt;      &lt;td valign="top" width="75"&gt;1.数据量较大        &lt;br /&gt;2.查询场景只在某个区        &lt;br /&gt;3.没有联合查询的场景&lt;/td&gt;      &lt;td valign="top" width="114"&gt;分区分表是在物理上对数据表所对应的文件进行拆分，对应的表名是不变的，所以不会影响到之前业务逻辑的sql&lt;/td&gt;      &lt;td valign="top" width="265"&gt;1.分表后的查询等业务会创建对应的对象，也会造成一定的开销分区数据若要聚合的话 耗费时间也较长；        &lt;br /&gt;2.使用范围不适合数据量千万级以上的。&lt;/td&gt;&lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="60"&gt;数据表分表&lt;/td&gt;      &lt;td valign="top" width="96"&gt;数据量较大，无法区分明显冷热区，且数据可以完整按照区间划分&lt;/td&gt;      &lt;td valign="top" width="135"&gt;适用于对冷热分区的界限不是很明显的数据，对后续类似的数据可以采用该方式，将大表拆分成小表，提高查询插入等效率&lt;/td&gt;      &lt;td valign="top" width="285"&gt;1.若大数据表逐渐增多 那么对应的数据库表越来越多 每个表都需要分表；        &lt;br /&gt;2.区间的划分较为固定，若后续单表的数据量大起来 也会对性能造成影响；        &lt;br /&gt;3.实现复杂度相对方案三比较复杂，需要测试整个实现过程，在编码层处理对原有业务有影响。&lt;/td&gt;&lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="60"&gt;冷热归档分库&lt;/td&gt;      &lt;td valign="top" width="96"&gt;1.数据量较大        &lt;br /&gt;2.数据冷热分区明显        &lt;br /&gt;3.冷数据使用频率极低&lt;/td&gt;      &lt;td valign="top" width="135"&gt;数据迁移的过程对业务的影响较小，开发量也较少减少成本&lt;/td&gt;      &lt;td valign="top" width="285"&gt;需要确认分表规则&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;大家可以根据自己的业务场景，去选择合适自己业务的方案，我这边就给大家提供一下思路～到这里内容就差不多结束了，如果有什么不对的，或者有什么疑惑，欢迎大家指点！&lt;/p&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62962-mysql-%E5%A4%A7%E6%95%B0%E6%8D%AE-%E7%AD%96%E7%95%A5</guid>
      <pubDate>Thu, 02 Jan 2025 10:59:52 CST</pubDate>
    </item>
    <item>
      <title>开源实时数据同步工具NiFi</title>
      <link>https://itindex.net/detail/62957-%E5%BC%80%E6%BA%90-%E5%AE%9E%E6%97%B6-%E6%95%B0%E6%8D%AE</link>
      <description>&lt;h2&gt;Apache NiFi简介&lt;/h2&gt;
 &lt;p&gt;Apache NiFi 是一个强大的数据流管理和自动化工具，旨在简化数据的采集、传输、处理和分发。它特别适合于构建和管理复杂的数据流管道，支持从各种数据源到不同目标系统的数据传输。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="245" src="https://www.biaodianfu.com/wp-content/uploads/2024/11/NiFi.png" width="525"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h3&gt;Apache NiFi主要功能&lt;/h3&gt;
 &lt;p&gt;Apache NiFi 是一个用于自动化数据流的强大工具，具有广泛的功能集，旨在支持从各种数据源到不同目标的复杂数据流管道。以下是 Apache NiFi 的主要功能：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;数据采集与传输&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;支持从多种数据源采集数据，包括文件系统、数据库、HTTP 服务、消息队列（如 Kafka）、传感器设备等。&lt;/li&gt;
    &lt;li&gt;支持将数据传输到多种目标系统，如 HDFS、数据库、云存储服务、REST API 等。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;数据流可视化&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;提供直观的 Web 用户界面，用户可以通过拖拽和配置处理器来设计和管理数据流。&lt;/li&gt;
    &lt;li&gt;实时显示数据流的状态和性能指标，便于监控和调试。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;数据处理与转换&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;提供丰富的内置处理器，支持数据的解析、转换、清洗、聚合和格式化等操作。&lt;/li&gt;
    &lt;li&gt;支持复杂的数据处理逻辑，如条件路由、数据分片、合并和拆分。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;动态路由与优先级控制&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;支持根据数据内容或属性动态路由数据到不同的处理器或目标。&lt;/li&gt;
    &lt;li&gt;允许为数据流设置优先级，以控制数据处理的顺序和速度。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;实时流处理&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;支持实时数据流处理，能够在数据到达时立即执行处理操作。&lt;/li&gt;
    &lt;li&gt;事件驱动架构，处理器在接收到数据或触发条件时自动执行。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;分布式架构与扩展性&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;支持多节点集群部署，可以水平扩展以处理大规模数据流。&lt;/li&gt;
    &lt;li&gt;集群中的节点通过 Apache ZooKeeper 进行协调和管理。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;数据安全与合规&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;支持数据加密、访问控制和用户身份验证，确保数据的安全性。&lt;/li&gt;
    &lt;li&gt;提供数据审计功能，记录数据流的处理历史和用户操作。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;错误处理与重试机制&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;自动处理数据传输和处理过程中出现的错误，支持重试和故障转移。&lt;/li&gt;
    &lt;li&gt;提供数据回退和恢复功能，确保数据的可靠性和完整性。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;可扩展性与集成性&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;支持自定义处理器和控制器服务的开发，用户可以根据需要扩展 NiFi 的功能。&lt;/li&gt;
    &lt;li&gt;与其他大数据工具和框架（如 Apache Kafka、Hadoop、Spark）紧密集成，支持复杂的数据处理和分析工作流。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;监控与管理&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;提供详细的日志记录和监控功能，帮助用户了解数据流的执行状态和性能指标。&lt;/li&gt;
    &lt;li&gt;支持告警和通知机制，用户可以根据特定条件设置告警，及时响应异常情况。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;Apache NiFi 的设计目标是提供一个灵活、高效且易于管理的数据流管理平台，适用于各种数据集成和处理场景。其丰富的功能集使其成为企业数据管道构建和管理的理想选择。&lt;/p&gt;
 &lt;h3&gt;Apache NiFi的优势&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;灵活性：通过丰富的处理器和自定义开发能力，NiFi 可以适应各种复杂的数据处理需求。&lt;/li&gt;
  &lt;li&gt;可扩展性：支持多节点集群部署，可以水平扩展以处理大规模数据流。&lt;/li&gt;
  &lt;li&gt;可视化管理：提供直观的 Web UI，用户可以轻松设计和管理数据流，无需编写复杂的代码。&lt;/li&gt;
  &lt;li&gt;高可用性：通过故障转移和数据重试机制，确保数据流的高可用性和可靠性。&lt;/li&gt;
  &lt;li&gt;安全性：支持数据加密、访问控制和审计，确保数据的安全性和隐私保护。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h2&gt;Apache NiFi的架构&lt;/h2&gt;
 &lt;p&gt;Apache NiFi 的架构设计旨在提供一个灵活、高效且可扩展的数据流管理平台。它采用模块化设计，支持分布式部署，能够处理各种规模和复杂度的数据流任务。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="510" src="https://www.biaodianfu.com/wp-content/uploads/2024/11/nifi-2.png" width="970"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h3&gt;核心组件&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;Web UI（用户界面）：NiFi 提供了一个直观的 Web 用户界面，用于设计、监控和管理数据流。用户可以通过拖拽和配置组件来构建数据流，并实时查看数据流的状态和性能指标。&lt;/li&gt;
  &lt;li&gt;FlowFile：FlowFile 是 NiFi 中的数据单元，包含数据内容和属性。每个 FlowFile 都有唯一标识符和元数据，支持数据的高效传输和处理。&lt;/li&gt;
  &lt;li&gt;处理器（Processor）：处理器是执行特定数据处理任务的基本单元。NiFi 提供了丰富的内置处理器，用于数据采集、转换、路由和传输。用户还可以开发自定义处理器以满足特定需求。&lt;/li&gt;
  &lt;li&gt;连接（Connection）：连接用于在处理器之间传递 FlowFile。连接可以配置为使用不同的队列策略，以控制数据的流动速度和优先级。&lt;/li&gt;
  &lt;li&gt;流程组（Process Group）：流程组用于组织和管理多个处理器和连接，形成逻辑上的子流程。这有助于复杂数据流的模块化设计和维护。&lt;/li&gt;
  &lt;li&gt;控制器服务（Controller Service）：控制器服务提供共享的配置和服务，例如数据库连接池、分布式缓存等。它们可以在多个处理器之间复用，提高资源利用率。&lt;/li&gt;
  &lt;li&gt;报告任务（Reporting Task）：报告任务用于生成和发送 NiFi 系统的运行状态和指标数据，通常用于监控和告警系统。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;工作流和数据流&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;数据采集与处理&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;数据流从输入处理器开始，输入处理器从外部数据源（如文件系统、HTTP、Kafka）获取数据并生成 FlowFile。&lt;/li&gt;
    &lt;li&gt;中间处理器对 FlowFile 进行处理，包括数据解析、转换、过滤和聚合等操作。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;数据路由与分发&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;根据业务规则和条件，NiFi 可以将 FlowFile 路由到不同的处理器或流程组。&lt;/li&gt;
    &lt;li&gt;输出处理器将处理后的 FlowFile 发送到目标系统（如 HDFS、数据库、云存储）。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;实时监控与管理&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;Web UI 提供实时数据流监控功能，用户可以查看处理器的性能指标、队列长度、处理速率等。&lt;/li&gt;
    &lt;li&gt;用户可以动态调整数据流的配置和参数，以优化性能和处理逻辑。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;分布式架构&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;多节点集群&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;NiFi 支持多节点集群部署，可以通过增加节点来扩展处理能力。集群中的每个节点都可以执行数据流任务。&lt;/li&gt;
    &lt;li&gt;集群节点通过 Apache ZooKeeper 进行协调和管理，以确保任务的负载均衡和高可用性。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;高可用性与故障转移&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;NiFi 采用主从架构，集群中一个节点为主节点（Primary Node），负责调度任务和管理集群配置。&lt;/li&gt;
    &lt;li&gt;在主节点故障时，集群会自动选举新的主节点，确保数据流的持续性和可靠性。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;安全性&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;用户认证与授权&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;支持多种认证机制（如 LDAP、Kerberos），确保只有授权用户才能访问和管理 NiFi 系统。&lt;/li&gt;
    &lt;li&gt;提供细粒度的权限控制，用户可以对不同的数据流组件和操作进行授权。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;数据加密&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;支持数据传输加密和存储加密，确保数据在传输和存储过程中的安全性。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;审计与日志&lt;/strong&gt;：
   &lt;ul&gt;
    &lt;li&gt;提供详细的审计日志记录，记录用户操作和数据流处理历史，便于合规性检查和故障排查。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;Apache NiFi 的架构设计使其成为一个灵活、可扩展和安全的数据流管理平台，适用于各种规模和复杂度的数据集成和处理任务。其模块化设计和丰富的功能集使得用户能够高效地构建和管理复杂的数据流管道。&lt;/p&gt;
 &lt;h2&gt;Airflow、Kafka的对比&lt;/h2&gt;
 &lt;p&gt;Apache NiFi、Apache Airflow 和 Apache Kafka 都是现代数据处理和管理生态系统中的重要工具，但它们各自的设计目的和应用场景有所不同。以下是它们的详细对比：&lt;/p&gt;
 &lt;table&gt;

  &lt;tr&gt;
   &lt;td&gt;特性&lt;/td&gt;
   &lt;td&gt;Apache NiFi&lt;/td&gt;
   &lt;td&gt;Apache Airflow&lt;/td&gt;
   &lt;td&gt;Apache Kafka&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;主要用途&lt;/td&gt;
   &lt;td&gt;实时数据流管理和自动化&lt;/td&gt;
   &lt;td&gt;工作流调度和管理&lt;/td&gt;
   &lt;td&gt;消息队列和流处理&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;架构特点&lt;/td&gt;
   &lt;td&gt;可视化界面，事件驱动架构&lt;/td&gt;
   &lt;td&gt;编程接口定义工作流（DAGs），基于调度器和执行器&lt;/td&gt;
   &lt;td&gt;发布/订阅模型，分布式架构&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;数据处理&lt;/td&gt;
   &lt;td&gt;实时数据采集、转换和路由&lt;/td&gt;
   &lt;td&gt;批处理任务调度，不直接处理数据流&lt;/td&gt;
   &lt;td&gt;高吞吐量的消息传输，支持实时流处理&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;扩展性与部署&lt;/td&gt;
   &lt;td&gt;多节点集群，水平扩展&lt;/td&gt;
   &lt;td&gt;分布式调度和执行，支持多种执行器&lt;/td&gt;
   &lt;td&gt;水平扩展，通过分区和副本实现容错&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;安全性&lt;/td&gt;
   &lt;td&gt;细粒度权限控制和数据加密&lt;/td&gt;
   &lt;td&gt;用户认证和授权（RBAC）&lt;/td&gt;
   &lt;td&gt;SSL 加密、SASL 认证和 ACL 授权&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;应用场景&lt;/td&gt;
   &lt;td&gt;实时数据集成、物联网数据采集、日志管理和监控&lt;/td&gt;
   &lt;td&gt;定时数据处理任务、复杂的 ETL 管道、机器学习工作流&lt;/td&gt;
   &lt;td&gt;实时数据传输、日志收集和分析、事件驱动架构&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
 &lt;p&gt;  &lt;strong&gt;对比总结&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;实时 vs 批处理：
   &lt;ul&gt;
    &lt;li&gt;NiFi：适合实时数据流处理和自动化。&lt;/li&gt;
    &lt;li&gt;Airflow：适合批处理任务调度和复杂的工作流管理。&lt;/li&gt;
    &lt;li&gt;Kafka：适合高吞吐量的消息传输和实时流处理。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;用户界面 vs 编程接口：
   &lt;ul&gt;
    &lt;li&gt;NiFi：提供可视化界面，适合需要快速构建和管理数据流的场景。&lt;/li&gt;
    &lt;li&gt;Airflow：提供编程接口，适合需要灵活定义复杂工作流的场景。&lt;/li&gt;
    &lt;li&gt;Kafka：主要通过编程接口和命令行工具进行管理和配置。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;数据流管理 vs 工作流调度 vs 消息队列：
   &lt;ul&gt;
    &lt;li&gt;NiFi：专注于数据流的管理和处理。&lt;/li&gt;
    &lt;li&gt;Airflow：专注于任务调度和工作流管理。&lt;/li&gt;
    &lt;li&gt;Kafka：专注于消息队列和流处理。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;根据具体的需求和场景，企业可以选择合适的工具或组合使用这些工具来构建复杂的数据处理和管理生态系统。例如，可以使用 NiFi 进行数据采集和预处理，使用 Kafka 进行高吞吐量的消息传输，使用 Airflow 进行批处理任务的调度和管理。&lt;/p&gt;
 &lt;div&gt;

  &lt;h3&gt;相关文章:&lt;/h3&gt;  &lt;ol&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/kafka.html" rel="bookmark" title="&amp;#20998;&amp;#24067;&amp;#24335;&amp;#28040;&amp;#24687;&amp;#31995;&amp;#32479;Kafka"&gt;分布式消息系统Kafka&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/hive-sql-guide.html" rel="bookmark" title="Hive SQL&amp;#31995;&amp;#32479;&amp;#21270;&amp;#23398;&amp;#20064;"&gt;Hive SQL系统化学习&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/python-schedule.html" rel="bookmark" title="Python&amp;#33258;&amp;#21160;&amp;#21270;&amp;#20043;&amp;#23450;&amp;#26102;&amp;#20219;&amp;#21153;"&gt;Python自动化之定时任务&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>器→工具 开源项目 大数据</category>
      <guid isPermaLink="true">https://itindex.net/detail/62957-%E5%BC%80%E6%BA%90-%E5%AE%9E%E6%97%B6-%E6%95%B0%E6%8D%AE</guid>
      <pubDate>Sat, 09 Nov 2024 21:04:10 CST</pubDate>
    </item>
    <item>
      <title>数据湖存储系统Paimon</title>
      <link>https://itindex.net/detail/62956-%E6%95%B0%E6%8D%AE-%E7%B3%BB%E7%BB%9F-paimon</link>
      <description>&lt;h2&gt;Paimon简介&lt;/h2&gt;
 &lt;p&gt;Apache Paimon 是一个面向大数据生态系统的高性能数据湖存储系统。它最初是由 Flink 社区开发的，旨在为大数据处理提供高效的存储解决方案。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="520" src="https://www.biaodianfu.com/wp-content/uploads/2024/11/Paimon.png" width="1819"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;Apache Paimon（以前称为 Flink Table Store）是一个专为流处理和批处理而设计的数据湖存储系统。它解决了现代数据处理中的一些关键问题，以下是一些主要的方面：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;统一的批处理和流处理：传统的数据处理系统通常将批处理和流处理分开，导致架构复杂性增加。Apache Paimon 提供了一种统一的存储格式，支持高效的批处理和流处理，简化了数据管道的构建和维护。&lt;/li&gt;
  &lt;li&gt;高效的数据更新和删除：许多数据湖解决方案在处理更新和删除操作时效率较低。Paimon 通过支持高效的增量更新和删除操作，提升了数据处理的灵活性，适合需要频繁更新的数据场景。&lt;/li&gt;
  &lt;li&gt;事务一致性：在数据湖中实现事务一致性是一个挑战。Paimon 提供了 ACID 事务支持，确保数据操作的原子性、一致性、隔离性和持久性，增强了数据的可靠性和一致性。&lt;/li&gt;
  &lt;li&gt;优化的存储格式：Paimon 使用了优化的存储格式，支持列式存储和高效的数据压缩，这不仅提高了查询性能，还降低了存储成本。&lt;/li&gt;
  &lt;li&gt;与 Apache Flink 的深度集成：Paimon 与 Apache Flink 深度集成，使得在 Flink 上构建实时数据应用变得更加容易。这种集成使得开发者可以利用 Flink 强大的流处理能力，直接在 Paimon 上执行复杂的实时分析任务。&lt;/li&gt;
  &lt;li&gt;元数据管理：Paimon 提供了强大的元数据管理功能，支持对大规模数据集的高效管理和操作，简化了数据治理和合规性管理。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;通过解决这些问题，Apache Paimon 为需要处理大规模数据的企业提供了一种高效、灵活且一致的数据存储和处理解决方案。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;设计目标&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;实时性：Apache Paimon 旨在支持实时数据处理和分析，使得用户可以对不断变化的数据进行快速查询和处理。&lt;/li&gt;
  &lt;li&gt;高吞吐和低延迟：系统设计考虑了高吞吐量和低延迟的需求，能够处理大规模数据的同时，保持较低的响应时间。&lt;/li&gt;
  &lt;li&gt;事务支持：支持 ACID 事务，以确保数据的一致性和可靠性，即使在高并发环境下也能保证数据的正确性。&lt;/li&gt;
  &lt;li&gt;易于集成：Paimon 可以与多种大数据处理框架无缝集成，如 Apache Flink、Apache Spark 等，提供灵活的数据处理能力。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;核心特性&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;数据湖架构：采用数据湖架构，允许用户在存储中保存大规模的结构化和非结构化数据，并对其进行管理和分析。&lt;/li&gt;
  &lt;li&gt;Schema 演化：支持动态的 Schema 演化，允许在不影响现有数据和查询的情况下进行 Schema 的更改。&lt;/li&gt;
  &lt;li&gt;高效的存储格式：使用高效的列式存储格式（如 Parquet 或 ORC），以减少存储空间和提高查询性能。&lt;/li&gt;
  &lt;li&gt;数据版本管理：提供数据版本管理功能，支持时间旅行查询（Time Travel Query），用户可以查询历史数据快照。&lt;/li&gt;
  &lt;li&gt;高可用性和扩展性：设计为分布式系统，能够在多节点环境中运行，提供高可用性和良好的扩展性。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;img alt="" height="373" src="https://www.biaodianfu.com/wp-content/uploads/2024/11/apache-paimon.png" width="950"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;目前Apache Paimon提供以下核心能力：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;基于HDFS或者对象存储构建低成本的轻量级数据湖存储服务。&lt;/li&gt;
  &lt;li&gt;支持在流模式与批模式下读写大规模数据集。&lt;/li&gt;
  &lt;li&gt;支持分钟级到秒级数据新鲜度的批查询和OLAP查询。&lt;/li&gt;
  &lt;li&gt;支持消费与产生增量数据，可作为传统数仓与流式数仓的各级存储。&lt;/li&gt;
  &lt;li&gt;支持预聚合数据，降低存储成本与下游计算压力。&lt;/li&gt;
  &lt;li&gt;支持历史版本回溯。&lt;/li&gt;
  &lt;li&gt;支持高效的数据过滤。&lt;/li&gt;
  &lt;li&gt;支持表结构变更。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;应用场景&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;实时数据分析：适用于需要对流数据进行实时分析的场景，如金融交易分析、实时用户行为分析等。&lt;/li&gt;
  &lt;li&gt;大规模数据处理：适合需要处理和存储大规模数据的企业，提供高效的数据存储和查询能力。&lt;/li&gt;
  &lt;li&gt;数据湖和数据仓库集成：可以作为数据湖的一部分，与传统数据仓库系统集成，为数据分析提供灵活的解决方案。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;社区和发展&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;Apache Paimon 是 Apache 软件基金会下的一个开源项目，受益于活跃的开发者社区和用户群体。其持续的发展和更新，使其不断适应大数据领域的新需求和新挑战。&lt;/p&gt;
 &lt;h2&gt;paimon的生态系统&lt;/h2&gt;
 &lt;p&gt;Apache Paimon 的生态系统设计旨在与现有的大数据处理框架和工具无缝集成，从而提供灵活性和易用性。以下是关于 Paimon 在兼容性和集成方面的一些细节：&lt;/p&gt;
 &lt;h3&gt;兼容性&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;与 Hadoop 的兼容性：&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;存储兼容性：Paimon 可以部署在 Hadoop 兼容的存储系统上，比如 HDFS。这使得用户可以利用现有的 Hadoop 基础设施来存储和管理数据。&lt;/li&gt;
  &lt;li&gt;生态系统工具支持：Paimon 可以与 Hadoop 生态系统中的其他工具（如 Hive）集成，支持在这些工具中查询和处理 Paimon 存储的数据。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;与 Spark 的兼容性：&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;数据源和数据接收器：Paimon 提供了与 Apache Spark 的集成，允许 Spark 任务将数据写入 Paimon 或从 Paimon 读取数据。通过 Spark 的 DataFrame API，用户可以方便地对 Paimon 数据进行复杂的批处理分析。&lt;/li&gt;
  &lt;li&gt;流处理支持：Paimon 的流数据更新能力可以与 Spark Streaming 集成，实现实时数据处理。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;与 Flink 的兼容性：&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;深度集成：Paimon 与 Apache Flink 的深度集成是其一大特色。Flink 用户可以使用 Paimon 作为流式和批处理作业的存储层，利用 Flink 强大的流处理能力直接对 Paimon 数据进行操作。&lt;/li&gt;
  &lt;li&gt;统一 API 支持：通过 Flink 的 Table API 和 SQL，用户可以在 Paimon 数据上执行统一的批处理和流处理任务。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;集成&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;与大数据处理框架的集成：&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Paimon 提供了与多种大数据处理框架的连接器和 API，使得这些框架可以轻松地将数据读写到 Paimon。开发者可以通过标准的 API 和连接器将 Paimon 纳入现有的数据处理管道。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;与数据湖和数据仓库的集成：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Paimon 可以作为数据湖的一部分，与其他数据湖技术（如 Delta Lake 或 Apache Iceberg）共同使用，提供统一的存储和管理能力。&lt;/li&gt;
  &lt;li&gt;通过与数据仓库系统的集成，Paimon 可以支持更复杂的分析和查询需求。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;可扩展的插件体系：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Paimon 支持插件机制，允许用户和开发者根据具体需求扩展其功能。这种灵活性使得 Paimon 能够适应多种应用场景和技术栈。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;通过与这些大数据生态系统的兼容性和集成能力，Apache Paimon 提供了一种灵活而强大的解决方案，能够在不改变现有基础设施的情况下提升数据处理能力。&lt;/p&gt;
 &lt;h2&gt;Paimon的核心概念&lt;/h2&gt;
 &lt;p&gt;Apache Paimon 是一种专为流处理和批处理设计的数据湖存储系统，其数据存储设计旨在提供高效的数据读写、更新和删除操作。&lt;/p&gt;
 &lt;h3&gt;数据存储格式&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;列式存储：&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Paimon 采用列式存储格式，类似于 Apache Parquet 或 ORC。这种格式有助于提高查询性能，特别是在需要扫描大量数据但只访问部分列的情况下。&lt;/li&gt;
  &lt;li&gt;列式存储也支持更高效的数据压缩，从而降低存储成本。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;分区和分桶：&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;数据可以按特定的字段进行分区和分桶。这种方式有助于提高数据的访问速度，因为查询可以更快地定位到相关的数据分区或分桶。&lt;/li&gt;
  &lt;li&gt;分区和分桶策略可以根据数据访问模式进行配置，以优化性能。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;数据更新和删除&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;增量更新&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Paimon 支持高效的增量更新，这意味着可以在不重写整个数据集的情况下对数据进行更新。这对于需要频繁更新的数据集（如实时数据）非常重要。&lt;/li&gt;
  &lt;li&gt;通过维护数据的增量变化，Paimon 可以快速地应用更新而不影响整体性能。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;删除操作&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;支持基于条件的删除操作，允许用户删除符合特定条件的数据。&lt;/li&gt;
  &lt;li&gt;Paimon 通过维护有效数据的快照来管理删除操作，这样可以在不影响读取性能的情况下安全地删除数据。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;事务一致性&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;ACID 事务&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Paimon 提供了 ACID 事务支持，确保数据操作的原子性、一致性、隔离性和持久性。&lt;/li&gt;
  &lt;li&gt;事务支持使得用户可以安全地进行并发数据操作，而无需担心数据不一致的问题。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;快照机制&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Paimon 使用快照机制来管理数据版本和事务。这种机制允许用户查看和回滚到特定时间点的数据状态。&lt;/li&gt;
  &lt;li&gt;快照机制也有助于实现数据的时间旅行查询（Time Travel Query），用户可以查询历史数据状态。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;元数据管理&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;元数据存储&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Paimon 的元数据可以存储在多种后端，包括文件系统和数据库。元数据存储用于管理表结构、分区信息和快照等。&lt;/li&gt;
  &lt;li&gt;高效的元数据管理使得 Paimon 可以在大规模数据集上提供快速的查询和更新。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;Schema 演变&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Paimon 支持 Schema 演变，允许用户在不影响现有数据的情况下修改表结构。这种灵活性对于需要不断调整数据模型的应用非常有用。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;数据读写性能&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;高效的读取&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Paimon 的列式存储和分区策略使得读取操作非常高效，特别是在只需访问部分列或特定分区时。&lt;/li&gt;
  &lt;li&gt;支持向量化查询处理，进一步提高读取性能。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;写入优化&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;通过批量写入和增量更新机制，Paimon 优化了写入性能，减少了 I/O 开销。&lt;/li&gt;
  &lt;li&gt;支持流式数据写入，使其适合实时数据处理场景。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;索引&lt;/h3&gt;
 &lt;p&gt;索引是提高数据查询性能的有效工具。在 Paimon 中，虽然具体的索引机制可能依赖于底层的存储和计算引擎，但一般支持以下几种常见的索引类型：&lt;/p&gt;
 &lt;p&gt;主键索引：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;主键索引用于快速定位特定的记录。对于需要频繁进行更新和删除操作的表，主键索引是非常有用的。&lt;/li&gt;
  &lt;li&gt;使用场景：主键索引适用于需要快速检索单条记录的场景，如根据订单 ID 查询订单详情。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;二级索引：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;二级索引用于加速非主键列的查询。它允许在非主键列上进行高效的查找操作。&lt;/li&gt;
  &lt;li&gt;使用场景：在频繁按某个非主键字段进行过滤查询时，二级索引可以显著提高性能。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;分区索引：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;分区本身可以视作一种粗粒度的索引，通过将数据按某个字段分区，可以快速定位到相关的数据块。&lt;/li&gt;
  &lt;li&gt;使用场景：按时间或地理位置等字段进行查询时，分区索引可以减少扫描的数据量。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;缓存机制&lt;/h3&gt;
 &lt;p&gt;缓存机制通过在内存中存储数据的部分或全部，提高数据访问速度，减少对磁盘的 I/O 操作。&lt;/p&gt;
 &lt;p&gt;查询结果缓存：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;查询结果缓存是指将经常访问的查询结果存储在内存中，以便在重复查询时可以直接返回缓存结果，而无需重新计算。&lt;/li&gt;
  &lt;li&gt;使用场景：适用于经常重复执行相同查询的场景，如报表生成或仪表盘展示。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;数据块缓存：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;数据块缓存涉及将常用的数据块（如列块或行块）缓存到内存中，以加快读取速度。&lt;/li&gt;
  &lt;li&gt;使用场景：对于那些访问频率高的数据集，数据块缓存可以显著减少磁盘 I/O。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;元数据缓存：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;元数据缓存用于存储表结构、分区信息等元数据，以减少查询时的元数据加载时间。&lt;/li&gt;
  &lt;li&gt;使用场景：在大规模数据环境中，元数据缓存可以加快查询计划的生成。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h2&gt;Paimon的使用&lt;/h2&gt;
 &lt;h3&gt;Paimon表的创建&lt;/h3&gt;
 &lt;p&gt;创建 Apache Paimon 表通常需要通过 SQL 语句来完成。Paimon 支持标准的 SQL 语法，可以使用各种计算框架（如 Apache Flink 或 Apache Spark）来执行这些 SQL 语句。&lt;/p&gt;
 &lt;h4&gt;使用 Apache Flink 创建 Paimon 表&lt;/h4&gt;
 &lt;p&gt;步骤：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;设置 Flink 环境：确保 Flink 已正确安装并配置好。确保 Flink 可以访问 Paimon 存储路径。&lt;/li&gt;
  &lt;li&gt;编写 Flink 作业：使用 Flink 的 Table API 或 SQL API 来创建 Paimon 表。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;示例代码：&lt;/p&gt;
 &lt;pre&gt;import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.table.api.bridge.java.StreamTableEnvironment;

public class CreatePaimonTable {
    public static void main(String[] args) throws Exception {
        // 设置 Flink 执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env);

        // 创建 Paimon 表
        tableEnv.executeSql(
            &amp;quot;CREATE TABLE paimon_table (&amp;quot; +
            &amp;quot;  id INT, &amp;quot; +
            &amp;quot;  name STRING, &amp;quot; +
            &amp;quot;  age INT, &amp;quot; +
            &amp;quot;  PRIMARY KEY (id) NOT ENFORCED&amp;quot; +
            &amp;quot;) WITH (&amp;quot; +
            &amp;quot;  &amp;apos;connector&amp;apos; = &amp;apos;paimon&amp;apos;,&amp;quot; +
            &amp;quot;  &amp;apos;path&amp;apos; = &amp;apos;path/to/paimon/table&amp;apos;&amp;quot; +
            &amp;quot;)&amp;quot;
        );

        // 打印表信息
        tableEnv.executeSql(&amp;quot;DESCRIBE paimon_table&amp;quot;).print();

        // 执行作业
        env.execute(&amp;quot;Create Paimon Table&amp;quot;);
    }
}
&lt;/pre&gt;
 &lt;h4&gt;使用 Apache Spark 创建 Paimon 表&lt;/h4&gt;
 &lt;p&gt;步骤：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;设置 Spark 环境：确保 Spark 已正确安装并配置好。确保 Spark 可以访问 Paimon 存储路径。&lt;/li&gt;
  &lt;li&gt;编写 PySpark 脚本：使用 PySpark 的 DataFrame API 或 SQL API 来创建 Paimon 表。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;示例代码：&lt;/p&gt;
 &lt;pre&gt;from pyspark.sql import SparkSession

# 创建 SparkSession
spark = SparkSession.builder \
    .appName(&amp;quot;Create Paimon Table&amp;quot;) \
    .config(&amp;quot;spark.jars.packages&amp;quot;, &amp;quot;&amp;lt;paimon-connector-package&amp;gt;&amp;quot;) \
    .getOrCreate()

# 创建 Paimon 表
spark.sql(&amp;quot;&amp;quot;&amp;quot;
    CREATE TABLE paimon_table (
        id INT,
        name STRING,
        age INT,
        PRIMARY KEY (id) NOT ENFORCED
    ) USING paimon
    OPTIONS (
        path &amp;apos;path/to/paimon/table&amp;apos;
    )
&amp;quot;&amp;quot;&amp;quot;)

# 打印表信息
spark.sql(&amp;quot;DESCRIBE paimon_table&amp;quot;).show()

# 停止 SparkSession
spark.stop()
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;注意事项&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;路径配置：path参数指定了 Paimon 表在文件系统中的存储路径。确保该路径是可写的，并且 Flink 或 Spark 有权限访问。&lt;/li&gt;
  &lt;li&gt;主键约束：PRIMARY KEY (id) NOT ENFORCED表示定义了一个主键，但不强制执行。Paimon 支持主键约束，但不强制执行可以提高写入性能。&lt;/li&gt;
  &lt;li&gt;连接器包：如果使用 Spark，确保在SparkSession 配置中指定了 Paimon 连接器包（&amp;lt;paimon-connector-package&amp;gt;）。这个包通常是通过 Maven 仓库提供的，需要查找并替换为实际的包名和版本。&lt;/li&gt;
  &lt;li&gt;Schema 设计：确保表的 Schema 设计合理，字段类型和名称符合业务需求。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;合理的分区&lt;/h3&gt;
 &lt;p&gt;在 Apache Paimon 中，对数据进行分区是一种有效的策略，可以提高查询性能和管理大规模数据集。分区允许将数据划分为更小的部分，使得查询可以更快地定位到相关的数据集，从而减少扫描的数据量。&lt;/p&gt;
 &lt;p&gt;分区是一种将数据集根据某些字段的值划分为多个逻辑部分的方式。每个分区包含特定字段值范围内的数据。常见的分区字段包括日期、地理位置或其他业务相关字段。&lt;/p&gt;
 &lt;h4&gt;如何设置分区&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;选择分区字段&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;选择合适的分区字段是分区策略的关键。通常选择那些在查询条件中经常使用的字段。&lt;/li&gt;
  &lt;li&gt;例如，对于时间序列数据，可以选择时间戳或日期字段进行分区。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;定义分区策略&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;在创建表时定义分区策略。Paimon 支持在表创建时指定分区字段。&lt;/li&gt;
  &lt;li&gt;例如，在 SQL 中创建一个分区表的语法如下：&lt;/li&gt;
&lt;/ul&gt;
 &lt;pre&gt;CREATE TABLE orders (
    order_id STRING,
    customer_id STRING,
    order_date DATE,
    amount DOUBLE
) PARTITIONED BY (order_date);
&lt;/pre&gt;
 &lt;p&gt;在这个例子中，order_date 字段被用作分区字段。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;数据写入和管理&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;当数据写入 Paimon 时，系统会根据定义的分区策略将数据分配到相应的分区中。&lt;/li&gt;
  &lt;li&gt;Paimon 自动管理分区的创建和维护，用户不需要手动管理分区文件或目录。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;分区的优点&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;提高查询性能：
   &lt;ul&gt;
    &lt;li&gt;通过限制查询扫描的分区数量，可以显著提高查询性能。例如，当查询条件包含分区字段时，系统只需扫描相关的分区。&lt;/li&gt;
    &lt;li&gt;这种优化特别适用于大规模数据集。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;简化数据管理：
   &lt;ul&gt;
    &lt;li&gt;分区使得数据管理更加简化。用户可以对单个分区执行操作（如删除或归档），而不影响其他分区的数据。&lt;/li&gt;
    &lt;li&gt;这在数据生命周期管理和存储优化方面非常有用。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;支持增量处理：
   &lt;ul&gt;
    &lt;li&gt;分区策略还可以帮助实现增量数据处理。例如，可以通过处理新的或特定的分区来实现增量更新或批量操作。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;分区的注意事项&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;分区数量：过多的分区可能导致元数据管理开销增加。因此，选择合适的分区粒度非常重要。&lt;/li&gt;
  &lt;li&gt;动态分区：对于某些场景，动态分区（即基于数据内容自动创建分区）可能是有用的，但也需要小心管理以避免过多的分区。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;数据导入Paimon&lt;/h3&gt;
 &lt;p&gt;将数据导入到 Apache Paimon 中，通常需要通过与大数据处理框架（如 Apache Flink 或 Apache Spark）的集成来实现。这是因为 Paimon 本身是一个数据湖存储系统，通常需要借助计算框架来进行数据的读写操作。以下是几种常见的方法：&lt;/p&gt;
 &lt;h4&gt;使用 Apache Flink 导入数据&lt;/h4&gt;
 &lt;p&gt;Apache Flink 是与 Paimon 集成最紧密的流处理框架。你可以通过 Flink 作业将数据导入到 Paimon。&lt;/p&gt;
 &lt;p&gt;步骤：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;设置 Flink 环境：确保 Flink 已正确安装并配置好。&lt;/li&gt;
  &lt;li&gt;配置 Paimon 表：在 Paimon 中创建一个目标表，定义表的 Schema（字段名称、类型等）。&lt;/li&gt;
  &lt;li&gt;编写 Flink 作业：编写一个 Flink 作业，使用 Paimon 提供的连接器来读取源数据（例如从 Kafka、文件系统、数据库等），并将其写入 Paimon 表。在 Flink 作业中，指定 Paimon 表的路径和配置。&lt;/li&gt;
  &lt;li&gt;运行 Flink 作业：提交并运行 Flink 作业，将数据流式写入 Paimon。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;使用 Apache Spark 导入数据&lt;/h4&gt;
 &lt;p&gt;Apache Spark 也是一个常用的数据处理框架，可以用于将批处理数据导入到 Paimon。&lt;/p&gt;
 &lt;p&gt;步骤：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;设置 Spark 环境：确保 Spark 已正确安装并配置好。&lt;/li&gt;
  &lt;li&gt;配置 Paimon 表：在 Paimon 中创建一个目标表。&lt;/li&gt;
  &lt;li&gt;编写 Spark 作业：使用 Spark 的 DataFrame API 读取源数据。使用 Paimon 的 Spark 连接器，将 DataFrame 写入到 Paimon 表。&lt;/li&gt;
  &lt;li&gt;运行 Spark 作业：提交并运行 Spark 作业，完成数据导入。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;使用命令行工具&lt;/h4&gt;
 &lt;p&gt;如果 Paimon 提供了命令行工具，你也可以直接使用这些工具将数据导入到 Paimon。&lt;/p&gt;
 &lt;p&gt;步骤：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;准备数据文件：准备好需要导入的数据文件，通常是 CSV、JSON 等格式。&lt;/li&gt;
  &lt;li&gt;使用命令行工具：使用 Paimon 提供的命令行工具，指定数据文件路径和目标表路径，将数据导入。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;使用 API&lt;/h4&gt;
 &lt;p&gt;如果需要更高的灵活性或集成到自定义应用程序中，你可以使用 Paimon 的 Java API 或其他语言支持的 API。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;步骤：&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;编写代码：使用 Paimon 提供的 API，编写代码来读取源数据并写入 Paimon 表。&lt;/li&gt;
  &lt;li&gt;运行程序：编译并运行你的程序，将数据导入到 Paimon。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;注意事项&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Schema 设计：确保 Paimon 表的 Schema 与源数据的结构匹配。&lt;/li&gt;
  &lt;li&gt;数据格式：确认源数据格式与 Paimon 支持的格式兼容。&lt;/li&gt;
  &lt;li&gt;性能优化：根据数据量和集群配置，适当调整作业的并行度和资源分配，以提高导入性能。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;MySQL数据同步paimon示例&lt;/h4&gt;
 &lt;p&gt;要将 MySQL 的 binlog 数据导入到 Apache Paimon 中，你可以使用 Apache Flink 作为数据处理引擎，因为 Flink 提供了对 MySQL binlog 的良好支持。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;配置 MySQL binlog&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;启用 binlog：在 MySQL 配置文件中启用 binlog。&lt;/p&gt;
 &lt;pre&gt;[mysqld]
log-bin=mysql-bin
server-id=1
binlog-format=ROW
&lt;/pre&gt;
 &lt;p&gt;创建用户：为 Flink 创建一个用户，具有读取 binlog 的权限。&lt;/p&gt;
 &lt;pre&gt;CREATE USER &amp;apos;flink&amp;apos;@&amp;apos;%&amp;apos; IDENTIFIED BY &amp;apos;password&amp;apos;;
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO &amp;apos;flink&amp;apos;@&amp;apos;%&amp;apos;;
FLUSH PRIVILEGES;
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;编写 Flink 作业&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;使用 Flink 的 MySQL CDC（Change Data Capture）连接器来读取 MySQL binlog 数据，并将其写入 Paimon。&lt;/p&gt;
 &lt;p&gt;Flink 作业示例：&lt;/p&gt;
 &lt;p&gt;依赖配置：确保在 Flink 项目中添加 MySQL CDC 连接器和 Paimon 连接器的依赖。&lt;/p&gt;
 &lt;p&gt;作业代码：&lt;/p&gt;
 &lt;pre&gt;import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.table.api.bridge.java.StreamTableEnvironment;
import org.apache.flink.table.api.Table;
import org.apache.flink.connector.mysql.cdc.MySQLSource;
import org.apache.flink.connector.mysql.cdc.config.MySQLSourceConfigFactory;
import org.apache.flink.types.Row;

public class MySQLToPaimon {
    public static void main(String[] args) throws Exception {
        // 设置 Flink 执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env);

        // 配置 MySQL Source
        MySQLSourceConfigFactory configFactory = MySQLSourceConfigFactory.newBuilder()
                .hostname(&amp;quot;your-mysql-host&amp;quot;)
                .port(3306)
                .databaseList(&amp;quot;your-database&amp;quot;)
                .tableList(&amp;quot;your-database.your-table&amp;quot;)
                .username(&amp;quot;flink&amp;quot;)
                .password(&amp;quot;password&amp;quot;)
                .build();

        MySQLSource&amp;lt;String&amp;gt; mySQLSource = MySQLSource.&amp;lt;String&amp;gt;builder()
                .hostname(&amp;quot;your-mysql-host&amp;quot;)
                .port(3306)
                .databaseList(&amp;quot;your-database&amp;quot;)
                .tableList(&amp;quot;your-database.your-table&amp;quot;)
                .username(&amp;quot;flink&amp;quot;)
                .password(&amp;quot;password&amp;quot;)
                .deserializer(new StringDebeziumDeserializationSchema())
                .build();

        // 读取 binlog 数据
        DataStream&amp;lt;String&amp;gt; mySQLStream = env.addSource(mySQLSource);

        // 将数据转换为表
        Table mySQLTable = tableEnv.fromDataStream(mySQLStream);

        // 写入 Paimon
        tableEnv.executeSql(
            &amp;quot;CREATE TABLE paimon_table (...) WITH (...)&amp;quot;
        );

        mySQLTable.executeInsert(&amp;quot;paimon_table&amp;quot;);

        // 执行作业
        env.execute(&amp;quot;MySQL Binlog to Paimon&amp;quot;);
    }
}
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;运行 Flink 作业&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;编译和打包：将 Flink 作业代码编译并打包成 JAR 文件。&lt;/li&gt;
  &lt;li&gt;提交作业：使用 Flink 提供的命令行工具或 Web UI 将作业提交到 Flink 集群。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;验证数据导入&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;检查 Paimon 表：在 Paimon 中检查数据是否正确导入。&lt;/li&gt;
  &lt;li&gt;监控作业：使用 Flink 的监控工具，确保作业正常运行，没有报错。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;注意事项&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;数据格式和 Schema：确保 MySQL 表的 Schema 与 Paimon 表的 Schema 一致。&lt;/li&gt;
  &lt;li&gt;错误处理：考虑添加错误处理机制，以便在读取 binlog 或写入 Paimon 过程中出现问题时能及时响应。&lt;/li&gt;
  &lt;li&gt;性能优化：根据数据量和集群配置，调整 Flink 作业的并行度和资源分配，以提高性能。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;Paimon数据查询&lt;/h3&gt;
 &lt;p&gt;查询 Apache Paimon 中的数据通常需要借助与之集成的计算框架，如 Apache Flink 或 Apache Spark。这些框架提供了灵活的查询能力，可以对存储在 Paimon 中的数据进行分析和处理。&lt;/p&gt;
 &lt;h4&gt;使用 Apache Flink 查询 Paimon 数据&lt;/h4&gt;
 &lt;p&gt;Flink 提供了流处理和批处理的能力，可以通过 SQL 或 Table API 来查询 Paimon 中的数据。&lt;/p&gt;
 &lt;p&gt;步骤：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;设置 Flink 环境：确保 Flink 已正确安装并配置好，并且可以访问 Paimon 存储。&lt;/li&gt;
  &lt;li&gt;编写 Flink SQL 查询：使用 Flink 的 Table API 或 SQL API 来查询 Paimon 中的数据。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;示例代码：&lt;/p&gt;
 &lt;pre&gt;import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.table.api.bridge.java.StreamTableEnvironment;
import org.apache.flink.table.api.Table;

public class PaimonQuery {
    public static void main(String[] args) throws Exception {
        // 设置 Flink 执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env);

        // 注册 Paimon 表
        tableEnv.executeSql(
            &amp;quot;CREATE TABLE paimon_table (&amp;quot; +
            &amp;quot;  id INT, &amp;quot; +
            &amp;quot;  name STRING, &amp;quot; +
            &amp;quot;  age INT&amp;quot; +
            &amp;quot;) WITH (&amp;quot; +
            &amp;quot;  &amp;apos;connector&amp;apos; = &amp;apos;paimon&amp;apos;,&amp;quot; +
            &amp;quot;  &amp;apos;path&amp;apos; = &amp;apos;path/to/paimon/table&amp;apos;&amp;quot; +
            &amp;quot;)&amp;quot;
        );

        // 执行查询
        Table result = tableEnv.sqlQuery(&amp;quot;SELECT * FROM paimon_table WHERE age &amp;gt; 30&amp;quot;);

        // 输出查询结果
        tableEnv.toChangelogStream(result).print();

        // 执行作业
        env.execute(&amp;quot;Paimon Query&amp;quot;);
    }
}
&lt;/pre&gt;
 &lt;h4&gt;使用 Apache Spark 查询 Paimon 数据&lt;/h4&gt;
 &lt;p&gt;Spark 也可以通过 DataFrame API 或 SQL 来查询 Paimon 中的数据。&lt;/p&gt;
 &lt;p&gt;步骤：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;设置 Spark 环境：确保 Spark 已正确安装并配置好，并且可以访问 Paimon 存储。&lt;/li&gt;
  &lt;li&gt;编写 Spark SQL 查询：使用 Spark 的 DataFrame API 或 SQL API 来查询 Paimon 中的数据。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;示例代码：&lt;/p&gt;
 &lt;pre&gt;import org.apache.spark.sql.SparkSession

object PaimonQuery {
  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder()
      .appName(&amp;quot;Paimon Query&amp;quot;)
      .getOrCreate()

    // 读取 Paimon 表
    val paimonDF = spark.read
      .format(&amp;quot;paimon&amp;quot;)
      .load(&amp;quot;path/to/paimon/table&amp;quot;)

    // 执行查询
    val result = paimonDF.filter(&amp;quot;age &amp;gt; 30&amp;quot;)

    // 显示查询结果
    result.show()

    spark.stop()
  }
}
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;注意事项&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Schema 一致性：确保查询中使用的 Schema 与 Paimon 表的 Schema 一致。&lt;/li&gt;
  &lt;li&gt;性能优化：根据查询的复杂度和数据量，调整 Flink 或 Spark 的资源配置以优化查询性能。&lt;/li&gt;
  &lt;li&gt;集成配置：在使用 Flink 或 Spark 进行查询时，确保正确配置了与 Paimon 的连接器。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;PySpark查询Paimon表示例&lt;/h4&gt;
 &lt;p&gt;要使用 PySpark 查询 Apache Paimon 中的数据，你需要确保 Paimon 和 Spark 环境已正确配置，并且可以通过 Spark SQL 或 DataFrame API 来访问和查询 Paimon 中的数据。以下是一个详细的指南，帮助你在 PySpark 中查询 Paimon 数据：&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;环境准备&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Spark 安装：确保已经安装并配置好 Apache Spark，并且可以使用 PySpark。&lt;/li&gt;
  &lt;li&gt;Paimon 连接器：确保 Spark 能够访问 Paimon 的数据存储路径，并配置好必要的连接器（如果需要）。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;启动 PySpark Shell 或 编写 PySpark 脚本&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;你可以选择在 PySpark Shell 中直接运行命令，或者编写一个独立的 PySpark 脚本。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;使用 PySpark Shell&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;pyspark --packages &amp;lt;paimon-connector-package&amp;gt;&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;编写 PySpark 脚本&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;from pyspark.sql import SparkSession

# 创建 SparkSession
spark = SparkSession.builder \
    .appName(&amp;quot;Paimon Query&amp;quot;) \
    .config(&amp;quot;spark.jars.packages&amp;quot;, &amp;quot;&amp;lt;paimon-connector-package&amp;gt;&amp;quot;) \
    .getOrCreate()

# 读取 Paimon 表
paimon_df = spark.read \
    .format(&amp;quot;paimon&amp;quot;) \
    .load(&amp;quot;path/to/paimon/table&amp;quot;)

# 执行查询
result_df = paimon_df.filter(paimon_df.age &amp;gt; 30)

# 显示查询结果
result_df.show()

# 停止 SparkSession
spark.stop()
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;运行脚本或命令&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;如果使用的是 PySpark Shell，直接在 Shell 中输入相应的命令。&lt;/li&gt;
  &lt;li&gt;如果是独立的 PySpark 脚本，使用 Spark 提供的命令行工具运行脚本：spark-submit –packages &amp;lt;paimon-connector-package&amp;gt; your_script.py&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;注意事项&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Paimon 连接器：在启动 PySpark Shell 或运行 PySpark 脚本时，需要指定 Paimon 的连接器包。这个包可能是通过 Maven 仓库提供的，你需要查找并替换 &amp;lt;paimon-connector-package&amp;gt; 为实际的包名和版本。&lt;/li&gt;
  &lt;li&gt;数据路径：确保 load(“path/to/paimon/table”) 中的路径正确指向 Paimon 中存储数据的实际路径。&lt;/li&gt;
  &lt;li&gt;Schema 一致性：在编写查询时，确保使用的字段名和类型与 Paimon 表的 Schema 保持一致。&lt;/li&gt;
  &lt;li&gt;性能优化：根据数据量和查询复杂度，调整 Spark 的资源配置（如执行器数量和内存）以提高查询性能。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;Paimon数据版本管理&lt;/h3&gt;
 &lt;p&gt;Apache Paimon 提供了强大的数据版本管理和时间旅行功能，这些功能对于数据分析和管理非常有用，特别是在需要审计、调试或回溯历史数据时。以下是对 Paimon 数据版本控制和时间旅行功能的详细介绍：&lt;/p&gt;
 &lt;h4&gt;数据版本控制&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;版本化数据存储&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Paimon 采用版本化的数据存储机制，每次对数据的更改（如插入、更新或删除）都会生成一个新的版本。&lt;/li&gt;
  &lt;li&gt;这些版本通过快照（Snapshot）进行管理，每个快照代表数据在某一时间点的状态。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;快照管理&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;快照是 Paimon 版本控制的核心。每个快照都有一个唯一的标识符和时间戳，记录了自上一个快照以来的数据变化。&lt;/li&gt;
  &lt;li&gt;快照可以用于回滚数据到某个历史状态，或用于审计和分析。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;增量更新&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;通过维护数据的增量变化，Paimon 可以高效地管理版本。只需存储和处理自上一个版本以来的变化，而不必复制整个数据集。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;时间旅行功能&lt;/h4&gt;
 &lt;p&gt;  &lt;strong&gt;时间旅行查询&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;时间旅行功能允许用户查询数据在过去某一时间点的状态。通过指定快照 ID 或时间戳，用户可以检索历史数据。&lt;/li&gt;
  &lt;li&gt;这对于需要调试数据问题、执行回溯分析或验证数据变化的场景非常有用。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;SQL 支持&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Paimon 支持通过 SQL 语句执行时间旅行查询。用户可以使用特定的语法指定要查询的快照或时间。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;示例查询语法：&lt;/p&gt;
 &lt;p&gt;SELECT * FROM table_name FOR SYSTEM_TIME AS OF ‘2023-01-01 10:00:00’;&lt;/p&gt;
 &lt;p&gt;在这个例子中，查询将返回数据在指定时间点的状态。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;快照导航&lt;/strong&gt;：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;用户可以列出所有可用的快照，并选择特定的快照进行查询。这种导航能力使得用户可以方便地找到需要的历史版本。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;实践中的应用&lt;/h4&gt;
 &lt;ul&gt;
  &lt;li&gt;数据审计：可以使用时间旅行功能查看数据在某个历史时间点的状态，以满足审计和合规性要求。&lt;/li&gt;
  &lt;li&gt;错误回溯：在发现数据错误时，通过时间旅行功能回溯到错误发生之前的版本，从而帮助定位和修复问题。&lt;/li&gt;
  &lt;li&gt;变化分析：分析数据在不同时间点的变化趋势，以支持业务决策。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;管理和优化&lt;/h4&gt;
 &lt;ul&gt;
  &lt;li&gt;存储优化：虽然版本控制和时间旅行功能提供了极大的便利，但也会增加存储需求。可以通过配置保留策略，定期清理不再需要的历史版本来优化存储。&lt;/li&gt;
  &lt;li&gt;性能考虑：在执行时间旅行查询时，考虑到数据规模和查询复杂度，以确保查询性能符合要求。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;参考链接：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;a href="https://paimon.apache.org/"&gt;Apache Paimon™&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://www.cnblogs.com/johnnyzen/p/18189005"&gt;[湖仓架构] Apache Paimon核心原理 – 千千寰宇 – 博客园 (cnblogs.com)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://www.cnblogs.com/itxiaoshen/p/17604141.html"&gt;新一代开源流数据湖平台Apache Paimon入门实操-上 – itxiaoshen – 博客园 (cnblogs.com)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://juejin.cn/post/7260389317176361016"&gt;当流计算邂逅数据湖：Paimon 的前生今世希望通过笔者以下的经历，回顾流计算一步一步扩大场景的过程，并引出 Apach – 掘金 (juejin.cn)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://www.alibabacloud.com/help/zh/flink/use-cases/build-a-streaming-data-warehouse-based-on-flink-and-apache-paimon"&gt;基于Flink+Paimon搭建流式湖仓 – 实时计算Flink版 – 阿里云 (alibabacloud.com)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;div&gt;

  &lt;h3&gt;相关文章:&lt;/h3&gt;  &lt;ol&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/hive-sql-guide.html" rel="bookmark" title="Hive SQL&amp;#31995;&amp;#32479;&amp;#21270;&amp;#23398;&amp;#20064;"&gt;Hive SQL系统化学习&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/spark-sql.html" rel="bookmark" title="Spark SQL &amp;#31995;&amp;#32479;&amp;#21270;&amp;#23398;&amp;#20064;"&gt;Spark SQL 系统化学习&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/python-connect-database.html" rel="bookmark" title="Python&amp;#22914;&amp;#20309;&amp;#36830;&amp;#25509;&amp;#25968;&amp;#25454;&amp;#24211;"&gt;Python如何连接数据库&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>器→工具 开源项目 大数据 数据仓库 数据湖</category>
      <guid isPermaLink="true">https://itindex.net/detail/62956-%E6%95%B0%E6%8D%AE-%E7%B3%BB%E7%BB%9F-paimon</guid>
      <pubDate>Wed, 06 Nov 2024 21:53:23 CST</pubDate>
    </item>
    <item>
      <title>Python地理数据分析工具MovingPandas</title>
      <link>https://itindex.net/detail/62944-python-%E5%9C%B0%E7%90%86-%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90</link>
      <description>&lt;p&gt;MovingPandas 是一个用于分析轨迹数据的 Python 库。它在处理和分析移动对象的时空数据方面非常强大，适用于地理信息系统（GIS）、时空数据分析和可视化等领域。它是在热门的地理数据处理库 GeoPandas 的基础上构建的，GeoPandas 本身是建立在Pandas数据处理库之上的。MovingPandas 旨在提供高效、易于使用的工具，以便分析和处理包含位置信息的时间序列数据。MovingPandas使得研究移动模式、路径分析、时空聚类等任务变得更加高效和直观。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="719" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/MovingPandas.png" width="977"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;核心功能：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;轨迹数据表示。MovingPandas 使用 GeoPandas GeoDataFrames 来表示轨迹数据。每条轨迹由一系列带有时间戳的点组成，形成一条时空路径。&lt;/li&gt;
  &lt;li&gt;轨迹分割。可以根据时间间隔、距离阈值等条件将轨迹分割成多个子轨迹。这对于处理长轨迹或者在某些关键事件发生前后进行分析非常有用。&lt;/li&gt;
  &lt;li&gt;轨迹特征提取。提供了多种方法来计算轨迹的特征，比如速度、加速度、方向变化等。这些特征在进行模式识别和行为分析时非常有用。&lt;/li&gt;
  &lt;li&gt;轨迹聚类。支持基于轨迹的聚类分析，可以识别出类似移动模式的轨迹群体。常用的聚类方法包括基于密度的聚类（DBSCAN）、分层聚类等。&lt;/li&gt;
  &lt;li&gt;轨迹可视化。通过与 Matplotlib 和 Folium 等库的集成，MovingPandas 能够提供强大的轨迹数据可视化功能，包括静态和交互式地图。&lt;/li&gt;
  &lt;li&gt;时空聚合。支持时空聚合分析，比如计算某个区域在特定时间段内的平均速度、轨迹数量等。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h2&gt;MovingPandas的使用&lt;/h2&gt;
 &lt;h3&gt;MovingPandas的安装&lt;/h3&gt;
 &lt;p&gt;MovingPandas作者推荐在Python 3.7及以上环境下安装。请确保你的Python版本符合这一要求。如果你已经安装了Anaconda，可以使用conda命令来安装MovingPandas及其依赖包。&lt;/p&gt;
 &lt;pre&gt;conda install -c conda-forge movingpandas&lt;/pre&gt;
 &lt;p&gt;MovingPandas同样可以使用pip进行安装，但是不推荐，主要原因是其依赖环境较为复杂，使用pip安装可能会出现依赖项缺失或版本冲突的问题。因此，推荐使用conda进行安装。&lt;/p&gt;
 &lt;h3&gt;MovingPandas接口详解&lt;/h3&gt;
 &lt;h4&gt;MovingPandas.Trajectory对象&lt;/h4&gt;
 &lt;p&gt;在 MovingPandas 中，Trajectory 类是核心组件之一，主要用于表示和处理单个轨迹。Trajectory 对象是一个时间序列的集合，其中每个数据点代表轨迹上的一个位置，包含了位置信息（经纬度或其他地理空间参考）、时间戳和其他可能的属性（如速度、方向等）。因此，一个 Trajectory 对象是连续移动的点组成的线，这些点按照时间顺序排列。&lt;/p&gt;
 &lt;p&gt;Trajectory 对象的主要特性：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;时间索引：Trajectory 对象的索引通常是时间戳，这使得基于时间的查询和操作变得直观和高效。&lt;/li&gt;
  &lt;li&gt;空间位置：每个时间点对应一个空间位置，这通常是通过经纬度坐标表示的。&lt;/li&gt;
  &lt;li&gt;其他属性：除了时间和位置，还可以包含其他相关的数据列，如速度、加速度、方向等，这些信息对于分析移动行为至关重要。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;创建 Trajectory 对象通常涉及几个步骤，首先你可能需要有一个包含时空数据的pandas DataFrame。这个DataFrame应该至少包含三列：表示时间戳的列（通常会被设置为索引）、表示X坐标的列（如经度）、表示Y坐标的列（如纬度）。然后，你可以使用 MovingPandas 提供的函数或方法（如TrajectoryCollection.from_geodataframe()）来创建一个或多个 Trajectory 对象。&lt;/p&gt;
 &lt;p&gt;class movingpandas.Trajectory(df, traj_id, traj_id_col=None, obj_id=None, t=None, x=None, y=None, crs=’epsg:4326′, parent=None)&lt;/p&gt;
 &lt;p&gt;参数说明：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;df：具有GeoPandas的geometry坐标列和时间戳索引的GeoDataFrame，或Pandas的DataFrame。必填参数。&lt;/li&gt;
  &lt;li&gt;traj_id：任意类型，表示轨迹的唯一标识符。必填参数。&lt;/li&gt;
  &lt;li&gt;obj_id：任意类型，表示移动物体的唯一标识符。默认为 None。&lt;/li&gt;
  &lt;li&gt;t：表示包含时间戳的列名，默认为 None。&lt;/li&gt;
  &lt;li&gt;x：表示包含x坐标的列名，使用Pandas的DataFrame需指定。默认为 None。&lt;/li&gt;
  &lt;li&gt;y：表示包含y坐标的列名，使用Pandas的DataFrame需指定。默认为 None。&lt;/li&gt;
  &lt;li&gt;crs：表示 x/y 坐标的坐标参考系统。默认为 “epsg:4326″，即 WGS84。&lt;/li&gt;
  &lt;li&gt;parent：一个Trajectory 对象，表示父轨迹。默认为 None。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;基本信息与操作&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;copy(): 返回轨迹对象的一个副本。&lt;/li&gt;
  &lt;li&gt;drop(**kwargs) 方法用于从数据集中删除满足特定条件的行或列。&lt;/li&gt;
  &lt;li&gt;plot(self, *args, **kwargs): 绘制轨迹。&lt;/li&gt;
  &lt;li&gt;explore(*args, **kwargs) 方法用于以交互方式可视化和分析数据，支持多种参数和选项以定制显示。&lt;/li&gt;
  &lt;li&gt;is_latlon() 方法用于判断轨迹数据是否采用经纬度坐标系。&lt;/li&gt;
  &lt;li&gt;is_valid() 方法用于检查轨迹数据是否有效，例如是否包含必要的字段和合理的坐标。&lt;/li&gt;
  &lt;li&gt;size() 方法用于返回轨迹中包含的定位点数量。&lt;/li&gt;
  &lt;li&gt;get_crs() 方法用于获取当前地理数据集的坐标参考系统（CRS），返回一个描述该坐标系的对象或信息。&lt;/li&gt;
  &lt;li&gt;to_crs(self, crs): 转换轨迹的坐标参考系统。&lt;/li&gt;
  &lt;li&gt;get_column_names() 方法用于获取数据集中的所有列名，返回一个包含列名的列表。这个方法通常用于快速查看数据集的结构或在进行数据处理时动态获取列名。&lt;/li&gt;
  &lt;li&gt;get_direction_col() 方法用于获取表示方向数据的列，这些数据通常以角度或方位形式存储。&lt;/li&gt;
  &lt;li&gt;get_distance_col() 方法用于获取表示距离数据的列，这些数据通常用于计算或分析两点之间的距离。&lt;/li&gt;
  &lt;li&gt;get_speed_col() 方法用于获取表示对象速度的列名。&lt;/li&gt;
  &lt;li&gt;get_timedelta_col() 方法用于获取表示时间增量的列名。&lt;/li&gt;
  &lt;li&gt;get_traj_id_col() 方法用于获取表示轨迹标识符的列名。&lt;/li&gt;
  &lt;li&gt;get_geom_col() 方法用于获取表示几何数据的列，该列通常包含地理空间信息，如点、线或多边形。&lt;/li&gt;
  &lt;li&gt;get_angular_difference_col() 方法用于获取包含角度差异的列，这些差异通常用于分析方向或角度变化。&lt;/li&gt;
  &lt;li&gt;to_point_gdf(self): 返回包含轨迹点的GeoDataFrame。&lt;/li&gt;
  &lt;li&gt;to_line_gdf(columns=None) 方法用于将轨迹数据转换为 GeoDataFrame 格式的线条几何数据，可以选择包含特定的列。&lt;/li&gt;
  &lt;li&gt;to_linestring() 方法用于将轨迹数据转换为 LineString 对象，表示轨迹的线条几何形状。&lt;/li&gt;
  &lt;li&gt;to_linestringm_wkt() 方法用于将轨迹数据转换为包含 ZM（高程和度量）信息的 WKT（Well-Known Text）格式的 LineStringM 字符串。&lt;/li&gt;
  &lt;li&gt;to_mf_json(datetime_to_str=True, temporal_columns=None) 方法用于将轨迹数据转换为 Moving Features JSON 格式，可以选择将日期时间转换为字符串，并指定时间相关的列。&lt;/li&gt;
  &lt;li&gt;to_point_gdf(return_orig_tz=False) 方法将轨迹数据转换为 GeoDataFrame 格式的点几何数据，可以选择返回原始时区的时间。&lt;/li&gt;
  &lt;li&gt;to_traj_gdf(wkt=False, agg=False) 方法将轨迹数据转换为 GeoDataFrame 格式，可以选择生成 WKT 格式的几何数据或进行聚合处理。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;轨迹分析与聚合统计&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;get_bbox(self): 返回轨迹的范围 (bounding box)。&lt;/li&gt;
  &lt;li&gt;get_start_location(self): 返回轨迹的起始位置。&lt;/li&gt;
  &lt;li&gt;get_end_location(self): 返回轨迹的结束位置。&lt;/li&gt;
  &lt;li&gt;get_start_time() 方法用于获取时间序列数据或对象轨迹的起始时间。&lt;/li&gt;
  &lt;li&gt;get_end_time() 方法用于获取某个事件或过程的结束时间，通常返回一个时间戳或日期时间对象。&lt;/li&gt;
  &lt;li&gt;get_max(column) 方法用于获取指定列 column 中的最大值。&lt;/li&gt;
  &lt;li&gt;get_min(column) 方法用于获取指定列 column 中的最小值。&lt;/li&gt;
  &lt;li&gt;get_position_at(t, method=’interpolated’) 方法用于获取在时间点 t 处的对象位置，默认使用插值方法来计算位置。&lt;/li&gt;
  &lt;li&gt;get_row_at(t, method=’nearest’) 方法用于获取在时间点 t 附近的对象所在的行，默认使用最近邻方法来选择行。&lt;/li&gt;
  &lt;li&gt;get_length(units=(None, None, None, None)) 方法用于计算并获取几何对象的长度，可以接受多个单位参数来指定长度的测量单位。&lt;/li&gt;
  &lt;li&gt;get_mcp() 方法用于获取某个对象的最小凸包 (Minimum Convex Polygon, MCP)，通常用于地理空间分析中确定一组点的最小包围区域。&lt;/li&gt;
  &lt;li&gt;add_direction(self, overwrite=False): 计算并添加方向信息到轨迹数据中。&lt;/li&gt;
  &lt;li&gt;get_direction() 方法用于计算和获取两个地理点之间的方向或方位角，通常以度数表示。&lt;/li&gt;
  &lt;li&gt;get_duration(self): 返回轨迹的总时长。&lt;/li&gt;
  &lt;li&gt;add_distance(overwrite=False, name=’distance’, units=None)：计算并添加轨迹数据中相邻点之间的距离信息。&lt;/li&gt;
  &lt;li&gt;add_acceleration(self, overwrite=False, name=’acceleration’): 计算并添加加速度信息到轨迹数据中。&lt;/li&gt;
  &lt;li&gt;add_speed(self, overwrite=False): 计算并添加速度信息到轨迹数据中。&lt;/li&gt;
  &lt;li&gt;add_angular_difference(overwrite=False, name=’angular_difference’)：计算并添加轨迹中相邻点之间的角度差异信息到轨迹数据中。&lt;/li&gt;
  &lt;li&gt;add_timedelta(overwrite=False, name=’timedelta’) ：计算并添加轨迹数据中相邻点之间的时间差信息。&lt;/li&gt;
  &lt;li&gt;add_traj_id(overwrite=False) 方法用于为轨迹数据添加或覆盖轨迹ID列，以标识相同轨迹中的所有点。&lt;/li&gt;
  &lt;li&gt;get_segment_between(t1, t2) 方法用于获取在时间点 t1 和 t2 之间的对象轨迹或数据段。&lt;/li&gt;
  &lt;li&gt;get_linestring_between(t1, t2, method=’interpolated’) 方法用于生成并获取在时间点 t1 和 t2 之间的一条线串，默认使用插值方法。&lt;/li&gt;
  &lt;li&gt;get_sampling_interval() 方法用于获取时间序列数据中的采样时间间隔。&lt;/li&gt;
  &lt;li&gt;hausdorff_distance(other, units=(None, None, None, None)) 方法用于计算当前轨迹与另一个轨迹之间的Hausdorff距离，并允许指定单位。&lt;/li&gt;
  &lt;li&gt;hvplot(*args, **kwargs) 方法用于使用hvPlot库创建高度可定制的图形和可视化。&lt;/li&gt;
  &lt;li&gt;hvplot_pts(*args, **kwargs) 方法用于使用hvPlot库对地理点数据进行可视化并创建交互式图形。&lt;/li&gt;
  &lt;li&gt;interpolate_position_at(t) 方法用于在给定时间 t 处插值并返回轨迹的位置。&lt;/li&gt;
  &lt;li&gt;intersection(feature, point_based=False) 方法用于计算轨迹与给定地理特征的交集，并可以选择基于点的方式进行计算。&lt;/li&gt;
  &lt;li&gt;intersects(polygon) 方法用于判断轨迹是否与指定的多边形区域相交。&lt;/li&gt;
  &lt;li&gt;clip(self, polygon): 按多边形裁剪轨迹。&lt;/li&gt;
  &lt;li&gt;apply_offset_minutes(column, offset) 方法用于将指定列的时间值按给定的分钟数进行偏移调整。&lt;/li&gt;
  &lt;li&gt;apply_offset_seconds(column, offset) 方法用于将指定列的时间值按给定的秒数进行偏移调整。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;MovingPandas.TrajectoryCollection对象&lt;/h4&gt;
 &lt;p&gt;TrajectoryCollection 类是 MovingPandas 中用于表示多条轨迹的集合。它允许用户以集合的形式操作多条轨迹，支持对这些轨迹的批量处理和分析。&lt;/p&gt;
 &lt;p&gt;可以通过传递一系列 Trajectory 对象来创建一个 TrajectoryCollection。每个 Trajectory 对象代表一条轨迹，包含了时间和位置的信息。&lt;/p&gt;
 &lt;p&gt;class movingpandas.TrajectoryCollection(data, traj_id_col=None, obj_id_col=None, t=None, x=None, y=None, crs=’epsg:4326′, min_length=0, min_duration=None)&lt;/p&gt;
 &lt;p&gt;参数说明：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;data (list[Trajectory] 或 GeoDataFrame 或 DataFrame) – 包含 Trajectory 对象的列表，或一个包含轨迹 ID、点几何列和时间戳索引的 GeoDataFrame。&lt;/li&gt;
  &lt;li&gt;traj_id_col (string) – 包含轨迹 ID 的 GeoDataFrame 列名。&lt;/li&gt;
  &lt;li&gt;obj_id_col (string) – 包含移动对象 ID 的 GeoDataFrame 列名。&lt;/li&gt;
  &lt;li&gt;t (string) – 包含时间戳的 DataFrame 列名。&lt;/li&gt;
  &lt;li&gt;x (string) – 包含 x 坐标的 DataFrame 列名。&lt;/li&gt;
  &lt;li&gt;y (string) – 包含 y 坐标的 DataFrame 列名。&lt;/li&gt;
  &lt;li&gt;crs (string) – x/y 坐标的坐标参考系 (CRS)。&lt;/li&gt;
  &lt;li&gt;min_length (numeric) – 期望的轨迹最小长度。长度使用 CRS 单位计算，若 CRS 是地理坐标系（例如 EPSG:4326 WGS84），则长度以米为单位计算。（较短的轨迹将被丢弃。）&lt;/li&gt;
  &lt;li&gt;min_duration (timedelta) – 期望的轨迹最短持续时间。（较短的轨迹将被丢弃。）&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;相比MovingPandas.Trajectory多了一些方法：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;filter(predicate): 根据给定条件过滤轨迹集合。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;MovingPandas.TrajectoryCollectionAggregator对象&lt;/h4&gt;
 &lt;p&gt;MovingPandas.TrajectoryCollectionAggregator 是 MovingPandas 库中的一个类，主要用于对轨迹集合进行聚合操作。通过对轨迹数据进行空间和时间上的聚合，可以帮助用户有效地分析和总结移动模式。&lt;/p&gt;
 &lt;p&gt;class movingpandas.TrajectoryCollectionAggregator(traj_collection, max_distance, min_distance, min_stop_duration, min_angle=45)&lt;/p&gt;
 &lt;p&gt;参数说明&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;traj_collection (TrajectoryCollection) – 要进行聚合的 TrajectoryCollection 对象。&lt;/li&gt;
  &lt;li&gt;max_distance (float) – 重要点之间的最大距离（距离使用 CRS 单位计算，若 CRS 是地理坐标系，例如 EPSG:4326 WGS84，则距离以米为单位计算）。&lt;/li&gt;
  &lt;li&gt;min_distance (float) – 重要点之间的最小距离。&lt;/li&gt;
  &lt;li&gt;min_stop_duration (datetime.timedelta) – 停止检测所需的最短持续时间。&lt;/li&gt;
  &lt;li&gt;min_angle (float) – 提取重要点的最小角度。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;相关方法：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;get_clusters_gdf() 方法返回一个 GeoDataFrame，其中包含聚合后的轨迹数据的簇（clusters）。&lt;/li&gt;
  &lt;li&gt;get_flows_gdf() 方法返回一个 GeoDataFrame，其中包含聚合后的轨迹数据的流动（flows）信息。&lt;/li&gt;
  &lt;li&gt;get_significant_points_gdf() 方法返回一个 GeoDataFrame，其中包含从轨迹数据中提取的显著点（significant points）。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;MovingPandas.TrajectoryCleaner对象&lt;/h4&gt;
 &lt;p&gt;MovingPandas.TrajectoryCleaner 是 MovingPandas 库中的一个类，专门用于清理轨迹数据。清理操作可以帮助去除数据中的噪声、填补缺失值以及进行其他预处理步骤，确保轨迹数据的质量和一致性。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;IqrCleaner(traj) 是一个类，用于基于四分位数范围 (IQR) 方法来清理轨迹数据中的异常值。&lt;/li&gt;
  &lt;li&gt;OutlierCleaner(traj) 是一个类，用于通过多种方法识别和清理轨迹数据中的离群点（异常值）。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;MovingPandas.TrajectoryGeneralizer对象&lt;/h4&gt;
 &lt;p&gt;MovingPandas.TrajectoryGeneralizer 是 MovingPandas 库中的一个类，用于对轨迹数据进行简化和概括。通过轨迹数据的概括，可以减少数据量，提高处理效率，并且在某些应用场景下有助于更清晰地展示轨迹特征。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;TrajectoryGeneralizer(traj) 是一个类，用于通过多种算法对轨迹数据进行简化和概括，以减少数据量并提高处理效率。&lt;/li&gt;
  &lt;li&gt;DouglasPeuckerGeneralizer(traj) 是一个类，专门使用 Douglas-Peucker 算法对轨迹数据进行简化，保留主要特征点以减少数据量。&lt;/li&gt;
  &lt;li&gt;MinDistanceGeneralizer(traj) 是一个类，用于根据最小距离间隔对轨迹数据进行简化，移除距离变化小于指定阈值的点。&lt;/li&gt;
  &lt;li&gt;MinTimeDeltaGeneralizer(traj) 是一个类，用于根据最小时间间隔对轨迹数据进行简化，移除时间间隔小于指定阈值的点。&lt;/li&gt;
  &lt;li&gt;TopDownTimeRatioGeneralizer(traj) 是一个类，用于通过时间比率算法对轨迹数据进行简化，保留关键时间点以减少数据量。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;MovingPandas.TrajectorySmoother对象&lt;/h4&gt;
 &lt;p&gt;MovingPandas.TrajectorySmoother 是一个类，用于对轨迹数据进行平滑处理。轨迹平滑通常是为了减少由于数据采集误差和噪声导致的轨迹抖动和异常点，从而得到更加平滑和准确的轨迹线条。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;KalmanSmootherCV(traj) 是一个类，用于使用常速模型（Constant Velocity Model）的卡尔曼滤波算法对轨迹数据进行平滑处理，以减少噪声和抖动。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;MovingPandas.TrajectorySplitter对象&lt;/h4&gt;
 &lt;p&gt;MovingPandas.TrajectorySplitter 是一个类，用于将轨迹数据根据特定条件进行分割。这在处理长时间、多段的轨迹数据时特别有用，比如在分析车辆行驶路径、运动员运动轨迹或动物迁徙路径时，可以根据特定的规则将连续的轨迹分割成多个部分，以便进行更细致的分析。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;TrajectorySplitter(traj) 是一个类，用于根据指定的条件（如距离、时间或速度）对轨迹数据进行分割，生成多个段以便更细致的分析。&lt;/li&gt;
  &lt;li&gt;TemporalSplitter(traj) 是一个类，用于根据时间间隔对轨迹数据进行分割，将轨迹分成多个时间段以便更细致的时间序列分析。&lt;/li&gt;
  &lt;li&gt;ObservationGapSplitter(traj) 是一个类，用于根据观测数据中的时间间隙对轨迹进行分割，当连续观测点之间的时间间隔超过指定阈值时，将轨迹分割成多个部分。&lt;/li&gt;
  &lt;li&gt;SpeedSplitter(traj) 是一个类，用于根据速度阈值对轨迹数据进行分割，当轨迹点的速度超过指定阈值时，将轨迹分割成多个部分。&lt;/li&gt;
  &lt;li&gt;StopSplitter(traj) 是一个类，用于根据停留点（长时间停留的点）对轨迹数据进行分割，将轨迹分成移动段和停留段以便更细致的分析。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;MovingPandas.TrajectoryStopDetector对象&lt;/h4&gt;
 &lt;p&gt;TrajectoryStopDetector 通过分析轨迹点的时空属性来识别停留点。它会检查一个轨迹对象中的每个点，并根据设定的阈值参数（如最小速度、最小停留时间和最小停留距离等）来鉴定轨迹中是否存在停留段。&lt;/p&gt;
 &lt;p&gt;class movingpandas.TrajectoryStopDetector(traj, n_threads=1)&lt;/p&gt;
 &lt;p&gt;方法介绍：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;get_stop_points(max_diameter, min_duration) 是 TrajectoryStopDetector 类中的方法，用于根据最大停留直径和最小持续时间来识别和提取轨迹数据中的停留点，并返回包含这些停留点的 GeoDataFrame。&lt;/li&gt;
  &lt;li&gt;get_stop_segments(max_diameter, min_duration) 是 TrajectoryStopDetector 类中的方法，用于根据最大停留直径和最小持续时间来识别和提取轨迹中的停留段，并返回包含这些停留段的列表。&lt;/li&gt;
  &lt;li&gt;get_stop_time_ranges(max_diameter, min_duration) 是 TrajectoryStopDetector 类中的方法，用于根据最大停留直径和最小持续时间来识别停留时间范围，并返回停留时间段的列表。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h2&gt;MovingPandas使用实例&lt;/h2&gt;
 &lt;h3&gt;准备工作&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;加载需要的库&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;import pandas as pd
import geopandas as gpd
import movingpandas as mpd
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import folium
import bokeh.io
bokeh.io.output_notebook()
from holoviews import opts
opts.defaults(opts.Overlay(active_tools=[&amp;quot;wheel_zoom&amp;quot;], frame_width=500, frame_height=400))
&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;加载数据&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;df = pd.read_excel(&amp;quot;driver_log.xlsx&amp;quot;)

# 将DataFrame 转换为 GeoDataFrame
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df.lon, df.lat), crs=&amp;apos;EPSG:4326&amp;apos;)

# 将GeoDataFrame转化为TrajectoryCollection对象
tc = mpd.TrajectoryCollection(gdf, traj_id_col=&amp;apos;session_id&amp;apos;, obj_id_col = &amp;apos;driver_no&amp;apos;, t=&amp;apos;log_time&amp;apos;)
# 过滤某个司机的轨迹
df[&amp;apos;driver_no&amp;apos;].value_counts()
df[&amp;apos;driver_no&amp;apos;].value_counts().plot(kind=&amp;apos;bar&amp;apos;, figsize=(15,3))
driver_tc = tc.filter(&amp;apos;driver_no&amp;apos;, &amp;apos;DR202407021504081000000&amp;apos;)

# 展示司机轨迹
driver_tc.plot()
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="413" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/driver_traj.png" width="450"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;# 获取单个轨迹
my_traj = driver_tc.trajectories[0]

# 展示单个轨迹
traj_plot = my_traj.hvplot(title=&amp;quot;Trajectory {}&amp;quot;.format(my_traj.id),line_width=7.0, tiles=&amp;quot;CartoLight&amp;quot;, color=&amp;quot;slategray&amp;quot;)
traj_plot
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="636" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/my_traj.png" width="815"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h3&gt;停留点检测&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;针对单轨迹停留点检测&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;detector = mpd.TrajectoryStopDetector(my_traj)
## 检测停留的时间（这里检测5分钟位移100米以内）
stop_time_ranges = detector.get_stop_time_ranges(min_duration=timedelta(seconds=300), max_diameter=100)
## 检测停留的时间
for stop_time in stop_time_ranges:
    print(stop_time)
## 检测停留点
stop_points = detector.get_stop_points(min_duration=timedelta(seconds=300), max_diameter=100)
stop_points
## 展示停留点
stop_point_plot = traj_plot * stop_points.hvplot(geo=True, size=&amp;quot;duration_s&amp;quot;, color=&amp;quot;deeppink&amp;quot;)
stop_point_plot
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="631" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/stop-point.png" width="817"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;## 停留点信息
stop_points_gdf = gpd.GeoDataFrame(stop_points, geometry=&amp;quot;geometry&amp;quot;, crs=&amp;quot;EPSG:4326&amp;quot;)
stop_points_gdf
## 使用folium展示停留点
# m = my_traj.explore(color=&amp;quot;blue&amp;quot;,style_kwds={&amp;quot;weight&amp;quot;: 4},name=&amp;quot;Trajectory&amp;quot;)
# stop_points_gdf.explore(m=m,color=&amp;quot;red&amp;quot;,style_kwds={&amp;quot;style_function&amp;quot;: lambda x: {&amp;quot;radius&amp;quot;: x[&amp;quot;properties&amp;quot;][&amp;quot;duration_s&amp;quot;] / 10 }},name=&amp;quot;Stop points&amp;quot;)
# folium.TileLayer(&amp;quot;OpenStreetMap&amp;quot;).add_to(m)
# folium.LayerControl().add_to(m)
# m
## 停留轨迹
stop_segments = detector.get_stop_segments(min_duration=timedelta(seconds=60), max_diameter=100)
stop_segments.to_traj_gdf()
## 停留轨迹
stop_segment_plot = stop_point_plot * stop_segments.hvplot(line_width=7.0, tiles=None, color=&amp;quot;orange&amp;quot;)
stop_segment_plot
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="629" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/stop_segment.png" width="811"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;## 使用folium绘图
# m = my_traj.explore(
#     color=&amp;quot;blue&amp;quot;,
#     popup=True,
#     style_kwds={&amp;quot;weight&amp;quot;: 4},
#     name=&amp;quot;Trajectory&amp;quot;,
# )

# stop_segments.explore(
#     m=m,
#     color=&amp;quot;orange&amp;quot;,
#     popup=True,
#     style_kwds={&amp;quot;weight&amp;quot;: 4},
#     name=&amp;quot;Stop segments&amp;quot;,
# )

# stop_points_gdf.explore(
#     m=m,
#     color=&amp;quot;red&amp;quot;,
#     tooltip=&amp;quot;stop_id&amp;quot;,
#     popup=True,
#     marker_kwds={&amp;quot;radius&amp;quot;: 3},
#     name=&amp;quot;Stop points&amp;quot;,
# )

# folium.TileLayer(&amp;quot;CartoDB positron&amp;quot;).add_to(m)
# folium.LayerControl().add_to(m)

# m

## 行驶线路
split = mpd.StopSplitter(my_traj).split(min_duration=timedelta(seconds=300), max_diameter=100)
split.to_traj_gdf()
## 可视化行驶线路
split.explore(column=&amp;quot;session_id&amp;quot;, tiles=&amp;quot;CartoDB positron&amp;quot;, style_kwds={&amp;quot;weight&amp;quot;: 4})

## 整体可视化
stop_segment_plot + split.hvplot(title=&amp;quot;Trajectory {} split at stops&amp;quot;.format(my_traj.id),line_width=7.0,tiles=&amp;quot;CartoLight&amp;quot;)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="457" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/stop_segment_plot.png" width="1058"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;轨迹合集的经停点检测&lt;/strong&gt;&lt;/p&gt;
 &lt;pre&gt;## 停留点检测
detector = mpd.TrajectoryStopDetector(driver_tc)
stop_points = detector.get_stop_points(min_duration=timedelta(seconds=300), max_diameter=100)
stop_points
## 停留点可视化
ax = driver_tc.plot(figsize=(7, 7))
stop_points.plot(ax=ax, color=&amp;quot;red&amp;quot;)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="486" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/TrajectoryStopDetector.png" width="603"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;## 使用folium可视化
## 使用方folium可视化
# m = driver_tc.explore(
#     column=&amp;quot;session_id&amp;quot;,
#     popup=True,
#     style_kwds={&amp;quot;weight&amp;quot;: 4},
#     name=&amp;quot;Trajectories&amp;quot;,
# )

# stop_points.explore(
#     m=m,
#     color=&amp;quot;red&amp;quot;,
#     tooltip=&amp;quot;stop_id&amp;quot;,
#     popup=True,
#     marker_kwds={&amp;quot;radius&amp;quot;: 5},
#     name=&amp;quot;Stop points&amp;quot;,
# )

# folium.TileLayer(&amp;quot;CartoDB positron&amp;quot;).add_to(m)
# folium.LayerControl().add_to(m)

# m
&lt;/pre&gt;
 &lt;h3&gt;速度计算&lt;/h3&gt;
 &lt;pre&gt;## 单轨迹增加速度
my_traj.add_speed(overwrite=True,units=(&amp;quot;km&amp;quot;, &amp;quot;h&amp;quot;))
my_traj.df.head()

## 展示速度
my_traj.plot(column=&amp;quot;speed&amp;quot;, linewidth=5, capstyle=&amp;apos;round&amp;apos;, legend=True)
# my_traj.hvplot(c=&amp;apos;speed&amp;apos;, clim=(0,20), line_width=7.0, tiles=&amp;apos;CartoLight&amp;apos;, cmap=&amp;apos;Viridis&amp;apos;, colorbar=True)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="404" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/speed.png" width="546"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;## 添加方向
my_traj.add_direction(overwrite=True)
my_traj.df.head()

## 添加时差
my_traj.add_timedelta(overwrite=True)
my_traj.df.head()

## 添加距离
my_traj.add_distance(overwrite=True, name=&amp;quot;distance (km)&amp;quot;, units=&amp;quot;m&amp;quot;)
my_traj.df.head()

## 添加加速度
my_traj.add_acceleration(overwrite=True, name=&amp;quot;acceleration (mph/s)&amp;quot;, units=(&amp;quot;mi&amp;quot;, &amp;quot;h&amp;quot;, &amp;quot;s&amp;quot;))
my_traj.df.head()

## 轨迹集增加速度
driver_tc.add_speed(overwrite=True,units=(&amp;quot;km&amp;quot;, &amp;quot;h&amp;quot;))
driver_tc.plot(column=&amp;apos;speed&amp;apos;, linewidth=5, capstyle=&amp;apos;round&amp;apos;, legend=True, vmax=20)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="418" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/speed2.png" width="534"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h3&gt;提取位置&lt;/h3&gt;
 &lt;pre&gt;## 获取起点与终点
ax = my_traj.plot()
gpd.GeoSeries(my_traj.get_start_location()).plot(ax=ax, color=&amp;apos;blue&amp;apos;)
gpd.GeoSeries(my_traj.get_end_location()).plot(ax=ax, color=&amp;apos;red&amp;apos;)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="417" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/location.png" width="574"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;## 获取特定时间点的位置
t = datetime(2024,7,3,9,30,0)
print(my_traj.get_position_at(t, method=&amp;quot;nearest&amp;quot;))
print(my_traj.get_position_at(t, method=&amp;quot;interpolated&amp;quot;))
print(my_traj.get_position_at(t, method=&amp;quot;ffill&amp;quot;)) # from the previous row
print(my_traj.get_position_at(t, method=&amp;quot;bfill&amp;quot;)) # from the following row

point = my_traj.get_position_at(t, method=&amp;quot;interpolated&amp;quot;)
ax = my_traj.plot()
gpd.GeoSeries(point).plot(ax=ax, color=&amp;apos;red&amp;apos;, markersize=100)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="417" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/time-point.png" width="574"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;## 获取特定时间区间的位置
segment = my_traj.get_segment_between(datetime(2024,7,3,9,10,0), datetime(2024,7,3,9,30,0))
print(segment)
ax = my_traj.plot()
segment.plot(ax=ax, color=&amp;apos;red&amp;apos;, linewidth=5)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="446" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/segment.png" width="542"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;## 获取特定区域内的轨迹
from shapely.geometry import Polygon

xmin, xmax, ymin, ymax = 104.135, 104.137, 30.642, 30.643
polygon = Polygon([(xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin), (xmin, ymin)])
intersections = my_traj.clip(polygon)
ax = my_traj.plot()
gpd.GeoSeries(polygon).plot(ax=ax, color=&amp;apos;lightgray&amp;apos;)
intersections.plot(ax=ax, color=&amp;apos;red&amp;apos;, linewidth=5, capstyle=&amp;apos;round&amp;apos;)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="446" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/intersections.png" width="542"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h3&gt;导出轨迹&lt;/h3&gt;
 &lt;pre&gt;## 返回 GeoDataFrame
driver_tc.to_point_gdf()
driver_tc.to_line_gdf()
driver_tc.to_traj_gdf(wkt=True) # 生成wkt格式的聚合

# 聚合数据
driver_tc.add_speed(overwrite=True,units=(&amp;quot;km&amp;quot;, &amp;quot;h&amp;quot;))
driver_tc.to_traj_gdf(agg={&amp;apos;speed&amp;apos;:[&amp;apos;min&amp;apos;, &amp;apos;max&amp;apos;,&amp;apos;mode&amp;apos;]})

# 导出数据
export_gdf = driver_tc.to_traj_gdf(agg={&amp;apos;speed&amp;apos;:[&amp;apos;min&amp;apos;, &amp;apos;max&amp;apos;,&amp;apos;mode&amp;apos;]})
export_gdf.to_file(&amp;quot;temp.gpkg&amp;quot;, layer=&amp;apos;trajectories&amp;apos;, driver=&amp;quot;GPKG&amp;quot;)
gpd.read_file(&amp;apos;temp.gpkg&amp;apos;).plot()
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="413" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/export_gdf.png" width="450"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h3&gt;轨迹分割&lt;/h3&gt;
 &lt;pre&gt;## 数据准备
my_traj.add_speed(overwrite=True,units=(&amp;quot;km&amp;quot;, &amp;quot;h&amp;quot;))
my_traj.plot(column=&amp;apos;speed&amp;apos;, vmax=20, linewidth=5, capstyle=&amp;apos;round&amp;apos;, figsize=(9,3), legend=True )
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="308" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/my_traj.plot_.png" width="455"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;## 根据观测数据中的时间间隙对轨迹进行分割
split = mpd.ObservationGapSplitter(my_traj).split(gap=timedelta(minutes=1))
split.to_traj_gdf()
fig, axes = plt.subplots(nrows=1, ncols=len(split), figsize=(19,4))
for i, traj in enumerate(split):
    traj.plot(ax=axes[i], linewidth=5.0, capstyle=&amp;apos;round&amp;apos;, column=&amp;apos;speed&amp;apos;, vmax=20)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="288" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/split.png" width="1047"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;## 根据停留点（长时间停留的点）对轨迹数据进行分割
split = mpd.StopSplitter(my_traj).split(max_diameter=10, min_duration=timedelta(minutes=1), min_length=20)
split.to_traj_gdf()
fig, axes = plt.subplots(nrows=1, ncols=len(split), figsize=(19,4))
for i, traj in enumerate(split):
    traj.plot(ax=axes[i], linewidth=5.0, capstyle=&amp;apos;round&amp;apos;, column=&amp;apos;speed&amp;apos;, vmax=20)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="269" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/split2.png" width="1055"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;## 根据速度阈值对轨迹数据进行分割
split = mpd.SpeedSplitter(my_traj).split(speed=0, duration=timedelta(minutes=1))
split.to_traj_gdf()
fig, axes = plt.subplots(nrows=1, ncols=len(split), figsize=(19,4))
for i, traj in enumerate(split):
    traj.plot(ax=axes[i], linewidth=5.0, capstyle=&amp;apos;round&amp;apos;, column=&amp;apos;speed&amp;apos;, vmax=20)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="284" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/split3.png" width="1031"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h3&gt;轨迹抽稀&lt;/h3&gt;
 &lt;pre&gt;## 展示原始轨迹
plot_defaults = {&amp;apos;linewidth&amp;apos;:5, &amp;apos;capstyle&amp;apos;:&amp;apos;round&amp;apos;, &amp;apos;figsize&amp;apos;:(9,3), &amp;apos;legend&amp;apos;:True}
my_traj.add_speed(overwrite=True,units=(&amp;quot;km&amp;quot;, &amp;quot;h&amp;quot;))
my_traj.plot(column=&amp;apos;speed&amp;apos;, vmax=20, **plot_defaults)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="308" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/plot_defaults.png" width="455"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;## 使用 Douglas-Peucker 算法对轨迹数据进行简化
dp_generalized  = mpd.DouglasPeuckerGeneralizer(my_traj).generalize(tolerance=0.0001)
dp_generalized.plot(column=&amp;apos;speed&amp;apos;, vmax=20, **plot_defaults)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="308" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/dp_generalized.png" width="448"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;print(&amp;apos;Original length: %s&amp;apos;%(my_traj.get_length()))
print(&amp;apos;Generalized length: %s&amp;apos;%(dp_generalized.get_length()))

## 根据最小时间间隔对轨迹数据进行简化
time_generalized = mpd.MinTimeDeltaGeneralizer(my_traj).generalize(tolerance=timedelta(minutes=3))
time_generalized.plot(column=&amp;apos;speed&amp;apos;, vmax=20, **plot_defaults)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="308" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/time_generalized.png" width="448"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;## 通过时间比率算法对轨迹数据进行简化
tdtr_generalized = mpd.TopDownTimeRatioGeneralizer(my_traj).generalize(tolerance=0.001)
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(19,4))
tdtr_generalized.plot(ax=axes[0], column=&amp;apos;speed&amp;apos;, vmax=20, **plot_defaults)
dp_generalized.plot(ax=axes[1], column=&amp;apos;speed&amp;apos;, vmax=20, **plot_defaults)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="344" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/tdtr_generalized.png" width="1198"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(19,4))
tdtr_generalized.plot(ax=axes[0], column=&amp;apos;speed&amp;apos;, vmax=20, **plot_defaults)
time_generalized.plot(ax=axes[1], column=&amp;apos;speed&amp;apos;, vmax=20, **plot_defaults)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="344" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/tdtr_generalized.plot_.png" width="1199"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h3&gt;平滑轨迹&lt;/h3&gt;
 &lt;pre&gt;split = mpd.ObservationGapSplitter(my_traj).split(gap=timedelta(minutes=1))
smooth = mpd.KalmanSmootherCV(split).smooth(process_noise_std=0.1, measurement_noise_std=10)
hvplot_defaults = {&amp;apos;tiles&amp;apos;:&amp;apos;CartoLight&amp;apos;, &amp;apos;frame_height&amp;apos;:320, &amp;apos;frame_width&amp;apos;:320, &amp;apos;cmap&amp;apos;:&amp;apos;Viridis&amp;apos;, &amp;apos;colorbar&amp;apos;:True}
kwargs = {**hvplot_defaults, &amp;apos;line_width&amp;apos;:4}
(split.hvplot(title=&amp;apos;Original Trajectories&amp;apos;, **kwargs) +  smooth.hvplot(title=&amp;apos;Smooth Trajectories&amp;apos;, **kwargs))
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="378" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/smooth.png" width="733"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;kwargs = {**hvplot_defaults, &amp;apos;c&amp;apos;:&amp;apos;speed&amp;apos;, &amp;apos;line_width&amp;apos;:7, &amp;apos;clim&amp;apos;:(0,20)}
(split.trajectories[1].hvplot(title=&amp;apos;Original Trajectory&amp;apos;, **kwargs) + smooth.trajectories[1].hvplot(title=&amp;apos;Smooth Trajectory&amp;apos;, **kwargs))
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="380" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/split.trajectories.png" width="846"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;traj = split.trajectories[1]

cleaned = traj.copy()
cleaned = mpd.OutlierCleaner(cleaned).clean(alpha=2)

smoothed = mpd.KalmanSmootherCV(cleaned).smooth(process_noise_std=0.1, measurement_noise_std=10)
    
(traj.hvplot(title=&amp;apos;Original Trajectory&amp;apos;, **kwargs) + 
 cleaned.hvplot(title=&amp;apos;Cleaned Trajectory&amp;apos;, **kwargs) + 
 smoothed.hvplot(title=&amp;apos;Cleaned &amp;amp; Smoothed Trajectory&amp;apos;, **kwargs))
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="386" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/smoothed.png" width="1301"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h3&gt;轨迹聚类和分类&lt;/h3&gt;
 &lt;pre&gt;## 查看数据
driver_tc.explore(column=&amp;quot;session_id&amp;quot;, cmap=&amp;quot;plasma&amp;quot;, style_kwds={&amp;quot;weight&amp;quot;: 4})
## 根据最小距离间隔对轨迹数据进行简化
generalized = mpd.MinDistanceGeneralizer(driver_tc).generalize(tolerance=100)
generalized.to_traj_gdf()

## 对轨迹进行聚合操作
aggregator = mpd.TrajectoryCollectionAggregator(
    generalized,
    max_distance=1000,
    min_distance=100,
    min_stop_duration=timedelta(minutes=10),
)

## 提取显著点
pts = aggregator.get_significant_points_gdf()
pts.hvplot(geo=True, tiles=&amp;quot;OSM&amp;quot;)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="634" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/pts.png" width="819"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;## 获取聚合轨迹的簇
clusters = aggregator.get_clusters_gdf()
(pts.hvplot(geo=True, tiles=&amp;quot;OSM&amp;quot;) * clusters.hvplot(geo=True, color=&amp;quot;red&amp;quot;))
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="638" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/clusters.png" width="815"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;## 使用folium绘制
# m = pts.explore(marker_kwds={&amp;quot;radius&amp;quot;: 3}, name=&amp;quot;Significant points&amp;quot;)
# clusters.explore(m=m, color=&amp;quot;red&amp;quot;, marker_kwds={&amp;quot;radius&amp;quot;: 3}, name=&amp;quot;Cluster centroids&amp;quot;)
# folium.TileLayer(&amp;quot;CartoDB positron&amp;quot;).add_to(m)
# folium.LayerControl().add_to(m)
# m

## 获取聚合后的轨迹数据的流动
flows = aggregator.get_flows_gdf()
(flows.hvplot(geo=True, hover_cols=[&amp;quot;weight&amp;quot;], line_width=dim(&amp;quot;weight&amp;quot;) * 7, color=&amp;quot;#1f77b3&amp;quot;,tiles=&amp;quot;CartoLight&amp;quot;) * clusters.hvplot(geo=True, color=&amp;quot;red&amp;quot;, size=dim(&amp;quot;n&amp;quot;)))
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="626" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/flows.png" width="829"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;## 使用Folium绘制
# m = flows.explore(style_kwds={&amp;quot;weight&amp;quot;: 5},name=&amp;quot;Flows&amp;quot;)
# clusters.explore( m=m,color=&amp;quot;red&amp;quot;,style_kwds={&amp;quot;style_function&amp;quot;: lambda x: {&amp;quot;radius&amp;quot;: x[&amp;quot;properties&amp;quot;][&amp;quot;n&amp;quot;]}}, name=&amp;quot;Clusters&amp;quot;)
# folium.TileLayer(&amp;quot;OpenStreetMap&amp;quot;).add_to(m)
# folium.LayerControl().add_to(m)
# m
&lt;/pre&gt;
 &lt;h3&gt;距离计算&lt;/h3&gt;
 &lt;pre&gt;## 选择2个轨迹
my_traj = driver_tc.trajectories[3]
toy_traj = driver_tc.trajectories[1]
## 呈现数据
ax = my_traj.plot()
toy_traj.plot(ax=ax, color=&amp;apos;red&amp;apos;)
&lt;/pre&gt;
 &lt;p&gt;  &lt;img alt="" height="343" src="https://www.biaodianfu.com/wp-content/uploads/2024/10/toy_traj.plot_.png" width="565"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;pre&gt;## 计算记录
print(f&amp;apos;Distance: {toy_traj.distance(my_traj)} meters&amp;apos;) # 返回最短距离
print(f&amp;apos;Hausdorff distance: {toy_traj.hausdorff_distance(my_traj):.2f} meters&amp;apos;) # 返回Hausdorff距离
&lt;/pre&gt;
 &lt;p&gt;Hausdorff距离可以理解为：对于集合A 中的每个点，计算它到集合B的最近距离，然后在这些距离中找到最大值；反过来对于集合 B 中的每个点，计算它到集合A 的最近距离，然后在这些距离中找到最大值。Hausdorff距离是这两个最大值中的较大者。&lt;/p&gt;
 &lt;p&gt;参考链接：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;a href="https://github.com/movingpandas/movingpandas"&gt;movingpandas/movingpandas: Movement trajectory classes and functions built on top of GeoPandas (github.com)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://movingpandas.org/"&gt;MovingPandas | A Python library for movement data exploration and analysis&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://movingpandas.org/examples.html"&gt;Tutorials | MovingPandas&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://movingpandas.readthedocs.io/en/main/"&gt;MovingPandas Documentation — MovingPandas main documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;div&gt;

  &lt;h3&gt;相关文章:&lt;/h3&gt;  &lt;ol&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/seaborn.html" rel="bookmark" title="Python&amp;#25968;&amp;#25454;&amp;#21487;&amp;#35270;&amp;#21270;&amp;#20043;Seaborn"&gt;Python数据可视化之Seaborn&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/learn-css.html" rel="bookmark" title="CSS&amp;#20307;&amp;#31995;&amp;#21270;&amp;#23398;&amp;#20064;"&gt;CSS体系化学习&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/arima.html" rel="bookmark" title="&amp;#26102;&amp;#38388;&amp;#24207;&amp;#21015;&amp;#39044;&amp;#27979;&amp;#20043;ARIMA"&gt;时间序列预测之ARIMA&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>器→工具 工具软件 开源项目 GIS</category>
      <guid isPermaLink="true">https://itindex.net/detail/62944-python-%E5%9C%B0%E7%90%86-%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90</guid>
      <pubDate>Wed, 09 Oct 2024 19:54:20 CST</pubDate>
    </item>
    <item>
      <title>使用 GoatCounter 与 Zeabur 搭建网站数据统计系统</title>
      <link>https://itindex.net/detail/62924-goatcounter-zeabur-%E7%BD%91%E7%AB%99</link>
      <description>&lt;h2&gt;前言&lt;/h2&gt;
 &lt;p&gt;在「  &lt;a href="https://www.pseudoyu.com/zh/2024/06/29/what_changed_in_my_blog_2024/"&gt;2024 年了，我的博客有了什么变化&lt;/a&gt;」一文中，我介绍了自己使用 Serverless 平台和一些开源项目搭建的博客系统，也开启了这个系列教程来记录搭建和部署全过程。&lt;/p&gt;
 &lt;p&gt;本篇是关于统计系统的解决方案。&lt;/p&gt;
 &lt;h2&gt;统计系统方案&lt;/h2&gt;
 &lt;p&gt;相比起博客本体和评论系统，我在很长的一段时间其实都没有在意过统计系统（主要当时也没人看），更加没考虑太多 SEO 或是什么其他推广方向上的事，但后来逐渐发现，其实统计下来的数据并不只是一张好看的可以用来发推的图表，其对于博客的选题、内容都有着很大的参考价值。&lt;/p&gt;
 &lt;p&gt;其实主流成熟的方案都能够满足基本的需求，即使是免费的 Google Analytics 也完全够用，但在博客发展过程中，我依然因各种原因有过几次迭代，最终使用了 GoatCounter 这一方案。&lt;/p&gt;
 &lt;h3&gt;splitbee&lt;/h3&gt;
 &lt;p&gt;我最初使用的是一个免费的工具 splitbee，它提供了免费的基础统计额度，有着还不错的界面，并且还支持一些复杂的用户追踪，A/B test 等，但印象里好像只能保留半年的数据，并且每月超过 5000 pv 后就需要升级了，所以后来放弃了。&lt;/p&gt;
 &lt;h3&gt;Cloudflare + Google Search Console&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="cloudflare_web_stats" src="https://image.pseudoyu.com/images/cloudflare_web_stats.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;放弃 splitbee 之后，很长一段时间我没有集成额外的统计应用，而是用的 Cloudflare 自带的站点统计，但是发现它其实统计的只是网络总流量，有包括爬虫在内的非常多的无效数据，并且没有精确到路径等细节。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="google_search_console" src="https://image.pseudoyu.com/images/google_search_console.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;后来了解到了 SEO 这一概念后，又添加了   &lt;a href="https://search.google.com/search-console/about"&gt;Google Search Console&lt;/a&gt; 这一统计维度，这也是目前觉得对我写博文最有意义的数据，主要呈现的是用户在搜索引擎中触达我博客站点的关键词以及通过搜索点击进入我博客的页面路径。&lt;/p&gt;
 &lt;p&gt;可以看到，一篇「  &lt;a href="https://www.pseudoyu.com/zh/category/tools/"&gt;Warp，iTerm2 还是 Alacritty？我的终端折腾小记&lt;/a&gt;」为我带来了许多访客，而关于博客搭建、智能合约开发也是大部分从搜索引擎来的自然用户对我博客的第一印象。&lt;/p&gt;
 &lt;h3&gt;Umami + Supabase + Netlify&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="yu_umami_record" src="https://image.pseudoyu.com/images/yu_umami_record.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;但是上述两者依然只能看到网站整体的数据，想精确到某篇文章在一段时间的表现或者文章发布后的实时访问数据，依然需要一个统计系统，我在看了 Reorx 的一篇「  &lt;a href="https://reorx.com/blog/deploy-umami-for-personal-website/"&gt;搭建 umami 收集个人网站统计数据 | Reorx’s Forge&lt;/a&gt;」选择使用了 umami 这一开源、易自部署的统计系统，界面简洁，功能易用，很方便集成到自己的博客系统中。&lt;/p&gt;
 &lt;p&gt;使用了一年半，一直倒没出现什么问题，，只不过可能因为自己用得比较早，在一次大版本更新的时候数据库 Migration 脚本出现了不兼容的字段更新，其实有点不理解这样量级的开源项目为什么会出现这样的问题，也看到 issue 中有很多其他用户有同样的诉求，但最终并没有给出一个比较好的解决方案。&lt;/p&gt;
 &lt;p&gt;但其实最大的问题是一个统计系统依赖了两个平台，部署和维护上都还是有些太重了。当数据库或是 Netlify 任一出现问题或需要迁移时，会带来许多额外的成本。于是前段时间在更新博客评论系统的时候，想着干脆就一起更换为更轻量的 GoatCounter。&lt;/p&gt;
 &lt;h3&gt;GoatCounter + Zeabur&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="goatcounter_stats" src="https://image.pseudoyu.com/images/goatcounter_stats.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;这个小众的统计系统是我在看 Reorx 的博客代码更新的时候偶然发现的，一下子被这种 Retro Internet 的风格所吸引，几乎没有任何多余的按钮，功能却很完备，而且使用的是 go 单二进制文件 + sqlite 数据库单文件的架构，轻量而易于部署，于是打算迁移。&lt;/p&gt;
 &lt;p&gt;其实我自己的 GoatCounter 是部署在   &lt;a href="https://fly.io/"&gt;fly.io&lt;/a&gt; 上的，但我在上一篇 Remark42 的文章中已经非常详细地介绍了 fly 的操作说明，不想有太多重复，刚好最近又在重度使用   &lt;a href="https://zeabur.com?referralCode=pseudoyu"&gt;Zeabur&lt;/a&gt; 这一 Serverless 平台，于是本文将以   &lt;a href="https://zeabur.com?referralCode=pseudoyu"&gt;Zeabur&lt;/a&gt; 为例，方式同样适用于其他类似平台。&lt;/p&gt;
 &lt;p&gt;我也在下文的 Zeabur 部署方案之后提供了 fly.io 和在 VPS 上使用 docker-compose 部署的配置文件，供大家参考。&lt;/p&gt;
 &lt;h2&gt;GoatCounter 部署说明&lt;/h2&gt;
 &lt;p&gt;GoatCounter 本身代码开源 —— 「  &lt;a href="https://github.com/arp242/goatcounter"&gt;GitHub - arp242/goatcounter&lt;/a&gt;」，文档清晰易读，可以根据自己的实际需求进行配置。GoatCounter + Zeabur 的方案仅牵扯到单个服务，数据库使用的是 sqlite 挂载于 volume 中，所以部署起来非常简单。&lt;/p&gt;
 &lt;h3&gt;使用 Zeabur 部署&lt;/h3&gt;
 &lt;p&gt;  &lt;a href="https://zeabur.com?referralCode=pseudoyu"&gt;Zeabur&lt;/a&gt; 对于容器应用的部署是需要 Developer Plan 的，5 美元/月，但是像这样的镜像服务整体用量和费用都较低，每月的额度足够部署非常多服务，可以酌情选择。整体部署流程比起 fly.io 简单很多，所有操作都可以使用 Web 界面完成，不需要额外安装命令行工具等。&lt;/p&gt;
 &lt;h4&gt;注册 zeabur&lt;/h4&gt;
 &lt;p&gt;  &lt;img alt="zeabur_login" src="https://image.pseudoyu.com/images/zeabur_login.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;访问   &lt;a href="https://zeabur.com?referralCode=pseudoyu"&gt;Zeabur&lt;/a&gt; 官网，并点击右上角，使用 GitHub 账号授权登录。&lt;/p&gt;
 &lt;h4&gt;创建新项目&lt;/h4&gt;
 &lt;p&gt;  &lt;img alt="zeabur_new_project" src="https://image.pseudoyu.com/images/zeabur_new_project.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;进入主界面后，点击右上角   &lt;code&gt;创建项目&lt;/code&gt; 按钮。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="zeabur_hk_region" src="https://image.pseudoyu.com/images/zeabur_hk_region.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;我选择了香港的 AWS 机房，不同机房的访问速度、性能和价格会有一些差异，可以根据自己的需求进行选择。&lt;/p&gt;
 &lt;h4&gt;配置镜像部署&lt;/h4&gt;
 &lt;p&gt;  &lt;img alt="zeabur_build" src="https://image.pseudoyu.com/images/zeabur_build.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;在下一步中选择 Docker 容器镜像进行部署。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="zeabur_docker_custom_config" src="https://image.pseudoyu.com/images/zeabur_docker_custom_config.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;由于我们使用的是自己构建的镜像，官方也没有上线 GoatCounter 模板，因此我们点击选择自定义。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="zeabur_prebuilt_edit_toml" src="https://image.pseudoyu.com/images/zeabur_prebuilt_edit_toml.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;这一步可以自己在界面上填写各种配置项，但可能由于我习惯了 fly.io 的文件配置模式，我选择左下角的   &lt;code&gt;编辑 TOML 文件&lt;/code&gt;，大家也可以直接复制我的配置文件并直接修改。&lt;/p&gt;
 &lt;div&gt;  &lt;pre&gt;   &lt;code&gt;name = &amp;quot;yu-goatcounter&amp;quot;

[source]
image = &amp;quot;pseudoyu/goatcounter&amp;quot;

[[ports]]
id = &amp;quot;web&amp;quot;
port = 8080
type = &amp;quot;HTTP&amp;quot;

[[volumes]]
id = &amp;quot;goatcounter-data&amp;quot;
dir = &amp;quot;/data&amp;quot;

[env]
PORT = { default = &amp;quot;8080&amp;quot; , expose = true }
GOATCOUNTER_DB = { default = &amp;quot;sqlite3://data/goatcounter.sqlite3&amp;quot; , expose = true }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;  &lt;img alt="zeabur_prebuilt_goatcounter_toml" src="https://image.pseudoyu.com/images/zeabur_prebuilt_goatcounter_toml.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;配置好后点击右下角部署按钮即可。&lt;/p&gt;
 &lt;h4&gt;部署完成&lt;/h4&gt;
 &lt;p&gt;  &lt;img alt="yu-goatcounter_project" src="https://image.pseudoyu.com/images/yu-goatcounter_project.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;点击部署后，等待片刻，会有一个生成的项目默认名称，可以在左上角的设置中去修改为可读性较强的名称，如   &lt;code&gt;yu-goatcounter&lt;/code&gt;。&lt;/p&gt;
 &lt;h4&gt;配置自定义域名&lt;/h4&gt;
 &lt;p&gt;  &lt;img alt="zeabur_create_domain" src="https://image.pseudoyu.com/images/zeabur_create_domain.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;服务部署完成后，我们需要进行域名绑定才能通过公网访问网站，Zeabur 提供了免费的二级域名   &lt;code&gt;xx.zeabur.app&lt;/code&gt;，也可以绑定自己的域名。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="zeabur_custom_domain" src="https://image.pseudoyu.com/images/zeabur_custom_domain.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;其中生成域名可直接使用，无须进行其他配置，如   &lt;code&gt;goatcounter.zeabur.app&lt;/code&gt;；而如果使用的是自定义域名，则需要在自己域名管理后台添加 CNAME 记录，指向格式为   &lt;code&gt;xxx.cname.zeabur-dns.com&lt;/code&gt; 的机房地址。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="cloudflare_goatcounter_config" src="https://image.pseudoyu.com/images/cloudflare_goatcounter_config.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;例如我的域名托管在 Cloudflare 上，添加的 CNAME 记录如上图所示，有去问过官方，说如果选 AWS HK 机房的话可以不使用 Cloudflare 的代理，速度理论上会更快，可以根据自己的需要酌情配置。&lt;/p&gt;
 &lt;p&gt;此外，如果你选择的是华为云机房，则需要域名备案并且额外新增一条 TXT 记录，可以根据提示进行操作。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="zeabur_custom_domain_success" src="https://image.pseudoyu.com/images/zeabur_custom_domain_success.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;显示绿色则为配置成功，至此我们的 GoatCounter 服务就部署完成了。&lt;/p&gt;
 &lt;h4&gt;数据备份&lt;/h4&gt;
 &lt;p&gt;我们在配置时候有这么一段&lt;/p&gt;
 &lt;div&gt;  &lt;pre&gt;   &lt;code&gt;[[volumes]]
id = &amp;quot;goatcounter-data&amp;quot;
dir = &amp;quot;/data&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;功能是将容器内的   &lt;code&gt;/data&lt;/code&gt; 目录（即我们的 sqlite 数据库存在的位置）挂载到一个 id 为   &lt;code&gt;goatcounter-data&lt;/code&gt; 的存储卷，如果不挂载存储卷的话，容器重启或重新部署数据将会丢失。&lt;/p&gt;
 &lt;p&gt;关于存储卷这一点 Zeabur 的界面上没有很直观的显示和管理操作，以至于我总是怀疑自己的配置是否生效。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="zeabur_add_goatcounter_backup" src="https://image.pseudoyu.com/images/zeabur_add_goatcounter_backup.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;研究了半天发现可以先在设置中暂停服务，然后在上面的备份模块新增一个备份，点击下载后可以在本地看到我们备份文件，目录层级如下：&lt;/p&gt;
 &lt;div&gt;  &lt;pre&gt;   &lt;code&gt;data/
└── goatcounter-data
    └── goatcounter.sqlite3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;这样则能表示我们的数据成功持久化了，希望 Zeabur 能在界面上有更直观的显示。&lt;/p&gt;
 &lt;h3&gt;使用 fly.io 部署&lt;/h3&gt;
 &lt;p&gt;纯免费的方案依然可以参照我提到的这篇「  &lt;a href="https://www.pseudoyu.com/zh/2024/07/22/free_commenting_system_using_remark42_and_flyio/"&gt;从零开始搭建你的免费博客评论系统（Remark42 + fly.io）&lt;/a&gt;」，仅在   &lt;code&gt;fly.toml&lt;/code&gt; 配置部分不同，我也提供的我所使用的配置文件 —— 「  &lt;a href="https://github.com/pseudoyu/goatcounter-on-fly/blob/master/fly.toml"&gt;fly.toml&lt;/a&gt;」供大家参考。&lt;/p&gt;
 &lt;h3&gt;使用 Docker 与 docker-compose 部署&lt;/h3&gt;
 &lt;p&gt;有意思的是，因为 goatcounter 的作者很有坚持，觉得这样单文件的应用容器化反而会增加更多维护成本，所以不提供官方镜像，不过自己在 vps 或者 serverless 平台部署有个镜像还是方便一些，所以我使用 Github Actions 做了一个构建镜像和上传 Docker Hub 的 CI，有需要的可以使用，对应的 Dockerfile 和 Docker Compose 文件也可以参照这个   &lt;a href="https://github.com/pseudoyu/goatcounter/commit/b98de9873ee331133a39b409fd4bb00cf55c8a05"&gt;Commit&lt;/a&gt;，或者直接使用   &lt;code&gt;pseudoyu/goatcounter&lt;/code&gt; 和   &lt;code&gt;docker-compose.yml&lt;/code&gt; 文件即可。&lt;/p&gt;
 &lt;div&gt;  &lt;pre&gt;   &lt;code&gt;version: &amp;apos;3&amp;apos;

services:
  goatcounter:
    image: pseudoyu/goatcounter
    ports:
      - 8080:8080
    environment:
      - PORT=8080
      - GOATCOUNTER_DB=sqlite3://data/goatcounter.sqlite3
    volumes:
      - ./data:/data
    restart: unless-stopped
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h2&gt;GoatCounter 配置说明&lt;/h2&gt;
 &lt;p&gt;上文我们完成了 GoatCounter 服务的部署，现在就可以通过我们生成/自定义的域名访问到我们的统计系统服务了，如我是通过   &lt;code&gt;https://goatcounter.pseudoyu.com&lt;/code&gt; 进行访问的。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="goatcounter_create_user" src="https://image.pseudoyu.com/images/goatcounter_create_user.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;第一次登录需要创建一个用户，填写邮箱、密码点击   &lt;code&gt;Create&lt;/code&gt; 即可。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="goatcounter_dashboard_success" src="https://image.pseudoyu.com/images/goatcounter_dashboard_success.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;登录成功后，当前还没有数据，会提示一个脚本，后续在我们博客使用的配置中会用到。&lt;/p&gt;
 &lt;h2&gt;博客配置 GoatCounter&lt;/h2&gt;
 &lt;p&gt;跟着上文我们完成了 GoatCounter 服务的部署和基础配置，现在则需要在我们的博文中加入统计组件，以我使用的 Hugo 博客为例。&lt;/p&gt;
 &lt;div&gt;  &lt;pre&gt;   &lt;code&gt;&amp;lt;script data-goatcounter=&amp;quot;https://goatcounter.pseudoyu.com/count&amp;quot;
        async src=&amp;quot;//goatcounter.pseudoyu.com/count.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;  &lt;img alt="add_goatcounter_script_in_hugo" src="https://image.pseudoyu.com/images/add_goatcounter_script_in_hugo.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;将上述代码加到我 hugo 主题的   &lt;code&gt;head&lt;/code&gt; 中即可，如我的 Hugo 主题在   &lt;code&gt;layouts/partials/head.html&lt;/code&gt; 这一文件，不同主题或是不同 SSG 框架位置有所不同但大同小异。&lt;/p&gt;
 &lt;p&gt;有一点要注意的是， goatcounter 会忽略来自   &lt;code&gt;localhost&lt;/code&gt; 的请求以避免在本地预览时造成太多脏数据，因此在本地调试时是看不到数据的，需要部署网页才能看到访问数据。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="final_display_of_goatcounter" src="https://image.pseudoyu.com/images/final_display_of_goatcounter.png"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;收集了数据后的效果大致如上图所示，还可以在 GoatCounter 界面中设置一些配置项、新增网页、查看详细数据等，包括还可以显示每个页面的访问计数等，可以自己根据文档进行探索。&lt;/p&gt;
 &lt;h2&gt;总结&lt;/h2&gt;
 &lt;p&gt;至此我们的博客统计系统就搭建完成了！本文是我的博客搭建部署系列教程之一，博客主题体部分都已经完成了，剩下只是一些例如博客内搜索等细节体验优化，希望能对大家有所参考。&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62924-goatcounter-zeabur-%E7%BD%91%E7%AB%99</guid>
      <pubDate>Tue, 06 Aug 2024 19:00:42 CST</pubDate>
    </item>
    <item>
      <title>数据中心网络高可用技术之从交换机到交换机：MLAG, 堆叠技术</title>
      <link>https://itindex.net/detail/62923-%E6%95%B0%E6%8D%AE%E4%B8%AD%E5%BF%83-%E7%BD%91%E7%BB%9C-%E6%8A%80%E6%9C%AF</link>
      <description>&lt;p&gt;在  &lt;a href="https://www.kawabangga.com/?p=6509"&gt;上一篇文章结束对链路聚合的讨论&lt;/a&gt;之后，我们发现一个问题——我们只能用多条线连接到同一个 switch 上面，这样万一这个交换机挂了，连接这个这个交换机的机器（通常是一个 Rack）就一起消失了。&lt;/p&gt;



 &lt;h2&gt;MLAG 技术&lt;/h2&gt;



 &lt;p&gt;MLAG(Multi-Chassis Link Aggregation) 可以提供跨设备的链路聚合功能。&lt;/p&gt;


 &lt;div&gt;
  &lt;a href="https://www.kawabangga.com/wp-content/uploads/2024/08/cisco-modular-switch.jpeg"&gt;   &lt;img alt="" height="289" src="https://www.kawabangga.com/wp-content/uploads/2024/08/cisco-modular-switch.jpeg" width="605"&gt;&lt;/img&gt;&lt;/a&gt;思科模块化交换机&lt;/div&gt;


 &lt;p&gt;Multi-Chassis 这个词很有意思，为什么叫做 Chassis （机箱）而不叫座 Multi-Switch LAG 呢？因为这个功能不仅仅是运行在 Switch 上，还记得在  &lt;a href="https://www.kawabangga.com/posts/6295"&gt;理解网络的分层模型&lt;/a&gt;中说的吗？二层和三层设备的界限已经越来越模糊了，三层设备也可以有这个功能。&lt;/p&gt;



 &lt;p&gt;现在的网络设备都是模块化的，一个机箱上面可以根据自己的需求插不同的线卡，卡上面甚至还能装不同的模块，满足不同的需求。机箱可以认为是网络设备单元，以「机箱」来说，意思就是运行于不同网络设备之间的功能。&lt;/p&gt;



 &lt;p&gt;  &lt;em&gt;MLAG 是一个设备的 feature，而不是协议，所以在不同厂商的产品中，MLAG，Peer Link 等术语会有所不同。&lt;/em&gt;&lt;/p&gt;


 &lt;div&gt;
  &lt;a href="https://www.kawabangga.com/wp-content/uploads/2024/08/mlag.png"&gt;   &lt;img alt="" height="306" src="https://www.kawabangga.com/wp-content/uploads/2024/08/mlag.png" width="424"&gt;&lt;/img&gt;&lt;/a&gt;多交换机 MLAG&lt;/div&gt;


 &lt;p&gt;对于客户端 Linux 来说，不知道对端是两个设备，在 Linux 的视角下，自己的多条线路连接的就是同一个设备。&lt;/p&gt;



 &lt;p&gt;在交换机侧，就需要跨设备完成 LACP 信息的同步，两个交换机设备之间需要协调好，A 的 3号端口 和 B 的 3号端口是同一个链路聚合组(LAG)。所以两个交换机之间需要一条线，来沟通控制面的信息。这条线就叫做 Peer Link。在 Peer Link 上如何传输控制信息，取决于不同厂商对于 MLAG 的实现。某些厂商的设备使用   &lt;a href="https://en.wikipedia.org/wiki/IEC_60870-6"&gt;ICCP&lt;/a&gt; (Inter-Control Center Communications Protocol) 来进行不同的机箱之间的连接。&lt;/p&gt;



 &lt;p&gt;这样，就可以完成从服务器到交换机的高可用了，服务器网卡、网线、交换机接口、交换机系统、交换机整机，任意一个地方出现问题，都有冗余路线，不会对服务造成太大影响。&lt;/p&gt;



 &lt;p&gt;数据中心广泛使用的就是 MLAG。&lt;/p&gt;



 &lt;h2&gt;堆叠技术&lt;/h2&gt;



 &lt;p&gt;在交换机之间的高可用，还有一种技术，就是交换机堆叠。这个功能在不同的厂商里也是不同的名字，比如华为的 istack，思科的 StackWise.&lt;/p&gt;



 &lt;p&gt;简单来说，这个功能可以让多个交换机虚拟成一个。只有一个主操作系统在运行，其他的交换机就像主交换机扩展出来的板卡一样。堆叠之后只有一个管理 IP 和 MAC 地址，只需要登录一个系统进行配置操作。&lt;/p&gt;



 &lt;a href="https://www.kawabangga.com/wp-content/uploads/2024/08/ip-mac-stacking-switch.png"&gt;  &lt;img alt="" height="430" src="https://www.kawabangga.com/wp-content/uploads/2024/08/ip-mac-stacking-switch-1024x430.png" width="1024"&gt;&lt;/img&gt;&lt;/a&gt;4个交换机完成堆叠之后，相当于一个交换机有了 4 倍的端口



 &lt;p&gt;堆叠之后逻辑上就是一个交换机，所以服务器可以直接连接到多个物理交换机，从逻辑上看，交换机侧也是同一个了。&lt;/p&gt;



 &lt;a href="https://www.kawabangga.com/wp-content/uploads/2024/08/switch-stacking.png"&gt;  &lt;img alt="" height="629" src="https://www.kawabangga.com/wp-content/uploads/2024/08/switch-stacking-1024x629.png" width="1024"&gt;&lt;/img&gt;&lt;/a&gt;交换机堆叠连接服务器



 &lt;p&gt;堆叠也能实现故障快速切换，在正常情况下也能充分利用线路的带宽，配置简单。但是和 MLAG 相比，稳定性上来说 MLAG 更高，因为堆叠交换机只有一个控制面，如果主交换机出现故障，比如堆叠失效，整个堆叠集群都会出错。MLAG 的故障域更小，交换机坏也就坏一台。这也带来很多维护便利，从升级维护上说，MLAG 可以让我们一台一台地操作交换机升级而不影响服务，堆叠就会更加麻烦一些。从部署上，MLAG 不受距离显示，堆叠的话，两个交换机距离越远，出错的概率越大。&lt;/p&gt;



 &lt;p&gt;  &lt;em&gt;说起来，思科还有一个    &lt;a href="https://www.cisco.com/c/en/us/td/docs/switches/datacenter/nexus7000/sw/vdc/config/cisco_nexus7000_vdc_config_guide_8x/overview.html"&gt;VDC 技术&lt;/a&gt;(Virtual Device Context), 支持把一个设备虚拟成多个。这些技术又是把一个物理设备拆成多个又是把多个合成一个的，可真有意思。&lt;/em&gt;&lt;/p&gt;



 &lt;p&gt;这个系列的二层技术介绍的差不多了，我们下一篇就开始聊三层技术。&lt;/p&gt;



 &lt;p&gt;Until next time!&lt;/p&gt;



 &lt;h2&gt;数据中心网络高可用技术系列&lt;/h2&gt;



 &lt;ol&gt;
  &lt;li&gt;   &lt;a href="https://www.kawabangga.com/posts/6417"&gt;数据中心网络高可用技术：序&lt;/a&gt;&lt;/li&gt;



  &lt;li&gt;   &lt;a href="https://www.kawabangga.com/posts/6430"&gt;数据中心网络高可用技术之从服务器到交换机：active-backup&lt;/a&gt;&lt;/li&gt;



  &lt;li&gt;   &lt;a href="https://www.kawabangga.com/posts/6485"&gt;数据中心网络高可用技术之从服务器到交换机：balance-tlb 和 balance-alb&lt;/a&gt;&lt;/li&gt;



  &lt;li&gt;   &lt;a href="https://www.kawabangga.com/posts/6460"&gt;数据中心网络高可用技术之从服务器到交换机：链路聚合 (balance-xor, balance-rr, broadcast)&lt;/a&gt;&lt;/li&gt;



  &lt;li&gt;   &lt;a href="https://www.kawabangga.com/posts/6509"&gt;数据中心网络高可用技术之从服务器到交换机：802.3 ad&lt;/a&gt;&lt;/li&gt;



  &lt;li&gt;   &lt;a href="https://www.kawabangga.com/posts/6537"&gt;数据中心网络高可用技术之从交换机到交换机：MLAG, 堆叠技术&lt;/a&gt;&lt;/li&gt;



  &lt;li&gt;   &lt;a href="https://www.kawabangga.com/posts/6594"&gt;数据中心网络高可用技术之从服务器到网关：VRRP&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>网络 ICCP (Inter-Control Center Communications Protocol) MLAG (Multi-Chassis Link Aggregation) Peer Link VDC (Virtual Device Context)</category>
      <guid isPermaLink="true">https://itindex.net/detail/62923-%E6%95%B0%E6%8D%AE%E4%B8%AD%E5%BF%83-%E7%BD%91%E7%BB%9C-%E6%8A%80%E6%9C%AF</guid>
      <pubDate>Thu, 08 Aug 2024 10:04:25 CST</pubDate>
    </item>
    <item>
      <title>数据分析模式的演进</title>
      <link>https://itindex.net/detail/62883-%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90-%E6%A8%A1%E5%BC%8F</link>
      <description>&lt;p&gt;数据分析是一个不断变化的领域。稍微了解一下历史将帮助你欣赏到这一领域取得的进展，以及数据架构模式如何演进以满足不断变化的分析需求。&lt;/p&gt;
 &lt;p&gt;首先，让我们从一些定义开始：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;什么是分析？分析被定义为将数据转化为洞察的任何行为。&lt;/li&gt;
  &lt;li&gt;什么是数据架构？数据架构是使数据的存储、转换、利用和治理成为可能的结构。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;分析及支持分析的数据架构已经走过了很长的路。现在让我们来探讨一些在过去几十年中逐渐演变的模式。&lt;/p&gt;
 &lt;p&gt;本章探讨了数据增长的起源，并解释了对数据架构新范式的需求。本章首先检视了主导的范式——企业数据仓库，在20世纪90年代和2000年代很受欢迎。它探讨了与这一范式相关的挑战，然后介绍了导致数据激增的驱动因素。接着，它进一步探讨了新范式——数据湖的崛起及其面临的挑战。此外，本章最后提倡了对一个新的范式——数据湖仓的需求，并阐明了一个经过良好设计的数据湖仓所提供的关键优势。&lt;/p&gt;
 &lt;p&gt;我们将在以下主题中涵盖所有这些内容：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;发现企业数据仓库时代&lt;/li&gt;
  &lt;li&gt;探索变革的五个因素&lt;/li&gt;
  &lt;li&gt;调查数据湖时代&lt;/li&gt;
  &lt;li&gt;介绍数据湖仓范式&lt;/li&gt;
&lt;/ol&gt;
 &lt;h1&gt;探索企业数据仓库时代&lt;/h1&gt;
 &lt;p&gt;由Ralph Kimball和Bill Inmon推广的企业数据仓库（EDW）模式在20世纪90年代和2000年代占主导地位。这一时代的需求相对较为简单（至少与当前背景相比是如此）。焦点主要集中在优化数据库结构以满足报告需求上。在这个时期，分析与报告是同义的。机器学习是一个专业领域，尚未在企业中普及。&lt;/p&gt;
 &lt;p&gt;下图展示了一个典型的企业数据仓库模式：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7ccfc7b32a69420d8b812e325ab7504a~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1198&amp;h=730&amp;s=156470&amp;e=png&amp;b=fefefe"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;如图1.1所示，该模式涉及由数据库或平面文件结构组成的源系统。数据源主要是结构化的，即行和列。一个称为提取-转换-加载（ETL）的过程首先从源系统中提取数据。然后，该过程将数据转化为有利于分析的形状和形式。一旦数据被转换，就被加载到企业数据仓库（EDW）中。然后，数据的子集被填充到下游的数据集市中。数据集市可以被看作是满足特定部门业务需求的小型数据仓库。&lt;/p&gt;
 &lt;p&gt;正如你可以想象的，这一模式主要关注以下方面：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;创建一个对存储进行优化并为报告建模的数据结构&lt;/li&gt;
  &lt;li&gt;关注业务的报告需求&lt;/li&gt;
  &lt;li&gt;将结构化数据转化为可操作的洞察&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;每个硬币都有两面。EDW模式也不例外。它有其优势和劣势。这一模式经受住了时间的考验。由于以下关键优势，它被广泛采用：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;由于大多数分析需求与报告相关，这一模式有效地满足了许多组织的报告需求。&lt;/li&gt;
  &lt;li&gt;大型企业数据模型能够将组织的数据结构化为逻辑和物理模型。这一模式以模块化和高效的方式管理组织的数据。&lt;/li&gt;
  &lt;li&gt;由于这一模式只服务于结构化数据，因此用于利用结构化数据的技术得以发展，并且随时可用。关系数据库管理系统（RDBMS）得以发展，并被适当地用于报告的特性。&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;然而，它也面临一系列随着数据量增长和新的数据格式出现而浮出水面的挑战。与EDW模式相关的一些挑战包括：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;这一模式不如变化迅速的业务需求希望它变得敏捷。对报告需求的任何更改都必须经过漫长的数据模型更改、ETL代码更改和报告系统的相应更改过程。通常，ETL过程是一种专业技能，并成为减少数据到洞察转化时间的瓶颈。分析的性质是独特的。你看到的产出越多，你就越要求。许多EDW项目被认为是失败的。失败并非来自技术角度，而是来自业务角度。在操作上，为了满足这些快速发展的需求而需要进行的设计更改太难处理了。&lt;/li&gt;
  &lt;li&gt;随着数据量的增长，这一模式变得成本过高。大规模的并行处理数据库技术开始演变，专门用于数据仓库工作负载。维护这些数据库的成本也是禁锢的。它涉及昂贵的软件价格、频繁的硬件更新和可观的人工成本。投资回报不再合理。&lt;/li&gt;
  &lt;li&gt;随着数据格式的演变，与EDW相关的挑战变得更为明显。数据库技术已经发展到可以满足半结构化数据（JSON）的需求。然而，基本概念仍然是基于关系数据库管理系统（RDBMS）。底层技术无法有效地满足这些新类型数据的需求。分析非结构化数据的价值更大。数据的多样性对EDW来说过于复杂，难以处理。&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;EDW主要专注于商业智能（BI）。它促进了定期报告的创建、自由数据分析和自助式BI。尽管它适应了大多数执行分析的角色，但不利于AI/ML用例。EDW中的数据已经被清理并以对报告的高度专注的方式进行了结构化。这留下了很少的空间供数据科学家（当时的统计建模者）探索数据并提出新的假设。简而言之，EDW主要关注于BI。&lt;/p&gt;
 &lt;p&gt;而EDW模式变得主流的同时，一场完美的风暴正在兴起，改变了数据架构模式。接下来的部分将专注于五个不同的因素，它们共同作用，以改变数据架构模式为善。&lt;/p&gt;
 &lt;h1&gt;探索变革的五个因素&lt;/h1&gt;
 &lt;p&gt;2007年改变了我们所知的世界；史蒂夫·乔布斯走上舞台宣布iPhone发布的那一天是数据时代的转折点。那一天酝酿出了完美的“数据”风暴。&lt;/p&gt;
 &lt;p&gt;完美风暴是由罕见的多种因素组合而成的气象事件。在数据演进的世界中，在过去的十年里发生了这样一场完美的风暴，它将数据推上了战略性企业资产的顶峰。五个因素引发了这场完美的“数据”风暴。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/87dfbb4db8ea4c879c366bc2bc4710f8~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1430&amp;h=881&amp;s=325428&amp;e=png&amp;b=ffffff"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;正如图1.2所示，形成完美风暴的有五个因素。数据的指数增长和计算能力的增加是前两个因素。这两个因素与存储成本的降低同时发生。人工智能的崛起和云计算的进步同时汇聚在一起，形成了这场完美的风暴。&lt;/p&gt;
 &lt;p&gt;这些因素独立发展并共同趋势，改变和塑造了产业。让我们简要地了解一下每个因素。&lt;/p&gt;
 &lt;h2&gt;数据的指数增长&lt;/h2&gt;
 &lt;p&gt;数据的指数增长是完美风暴的第一个因素。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2b9099332fb646c88b4f7bdb827d7376~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=899&amp;h=586&amp;s=75823&amp;e=png&amp;b=ffffff"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;根据国际数据公司（IDC）的数据，到2025年，生成的总数据量将达到约163 ZB（字节），即一万亿吉字节。而2010年，这个数字大约是0.5 ZB。这种数据的指数增长归因于互联网技术的巨大改进，推动了许多行业的增长。电信行业是发生转变的主要行业。这反过来又改变了许多其他行业。数据变得无处不在，每个企业都渴望更多的数据带宽。社交媒体平台也开始被广泛使用。像Facebook、Twitter和Instagram这样的平台在互联网空间里涌入了更多的数据。流媒体服务和电子商务也产生了大量的数据。这些生成的数据被用来塑造和影响消费者行为。最后但同样重要的是，物联网（IoT）领域的技术飞跃产生了大量的数据。&lt;/p&gt;
 &lt;p&gt;传统的企业数据仓库（EDW）模式无法应对这种数据增长。它们被设计用于处理结构化数据。大数据已经改变了可用数据的定义。现在的数据是庞大的（体积），其中一些是持续流动的（速度），以不同的形状和形式生成的（多样性），来自各种来源且带有噪声（真实性）。&lt;/p&gt;
 &lt;h2&gt;计算能力的增加&lt;/h2&gt;
 &lt;p&gt;计算能力的指数增长是完美风暴的第二个因素。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b4aade5f3b1f4877afc0b87fd553e1cd~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=811&amp;h=480&amp;s=86921&amp;e=png&amp;b=fefefe"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;摩尔定律是美国工程师戈登·摩尔在1965年提出的一个预测，即每年硅芯片上的晶体管数量翻倍一次。迄今为止，这一定律一直忠实于其预测。2010年，微处理器上的晶体管数量约为20亿。到2020年，这一数字已经达到了540亿。计算能力的这种指数增长与提供无限计算能力的云计算技术的崛起密切相关，而且价格合理。&lt;/p&gt;
 &lt;p&gt;计算能力在一个合理的价格点上的增加为大数据提供了迫切需要的推动力。组织现在可以以更低的价格点采购越来越多的计算能力。云计算中可用的计算能力现在可以用于按需处理和分析数据。&lt;/p&gt;
 &lt;h2&gt;存储成本的降低&lt;/h2&gt;
 &lt;p&gt;存储成本的迅速降低是完美风暴的第三个因素。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fbe360390ff4426d90ec0a81e64ff2c1~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=776&amp;h=476&amp;s=58912&amp;e=png&amp;b=ffffff"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;存储成本也呈指数级下降。在2010年，将一GB数据存储到硬盘驱动器（HDD）中的平均成本约为0.1美元。而在10年后，这一数字降至大约0.01美元。在传统的企业数据仓库（EDW）模式中，组织必须谨慎选择哪些数据需要存储用于分析，哪些数据可以丢弃。保留数据是一项昂贵的提议。然而，存储成本的指数级下降意味着现在可以以之前成本的一小部分存储所有数据。现在无需挑选哪些数据应该被存储，哪些应该被丢弃。以任何形式的数据都可以以较低的价格进行存储。现在可以实施先存储，后分析的策略。&lt;/p&gt;
 &lt;h2&gt;人工智能的崛起&lt;/h2&gt;
 &lt;p&gt;人工智能（AI）系统并非新事物。实际上，它们的起源可以追溯到1950年代，当时使用统计模型基于过去的数据估计数据点的值。由于当时缺乏运行这些模型所需的计算能力和大量数据，这一领域在很长一段时间内未受到关注。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/513b29afe8d04d4b98c47774111be102~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1398&amp;h=641&amp;s=238194&amp;e=png&amp;b=fefefe"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;然而，在长时间的休眠之后，人工智能技术在2010年代初期迎来了复苏。这种复苏部分原因在于强大的计算资源的丰富和数据的充分可用。现在，人工智能模型可以更快地进行训练，并且结果惊人地准确。&lt;/p&gt;
 &lt;p&gt;存储成本降低和计算资源更加充足的因素对人工智能来说是一种福音。现在可以训练更加复杂的模型。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e22e6b626f3d45d48d1bf6fe143a83e2~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1336&amp;h=630&amp;s=131012&amp;e=png&amp;b=ffffff"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;这对深度学习算法尤其是真实。例如，一种称为卷积神经网络（CNNs）的深度学习技术在图像检测方面变得非常流行。随着时间的推移，越来越深层次的神经网络被创建出来。现在，人工智能系统在检测对象方面已经超过了人类。&lt;/p&gt;
 &lt;p&gt;随着人工智能系统变得更加准确，它们变得越来越受欢迎。这推动了循环行为，越来越多的企业将人工智能应用于数字化转型议程中。&lt;/p&gt;
 &lt;h2&gt;云计算的进步&lt;/h2&gt;
 &lt;p&gt;完美“数据”风暴的第五个因素是云计算的崛起。云计算是计算和存储资源按需提供的服务。典型的公共云服务提供商包括亚马逊（AWS）、微软（Azure）和谷歌（GCP）等大型科技公司。云计算消除了在组织数据中心托管大型服务器的需求。根据在云中订阅的服务，组织还可以减少对软件和硬件维护的依赖。云以非常经济的价格提供了大量的按需服务。自2010年以来，云计算领域不断攀升。2010年，全球公共云的支出约为770亿美元，而到2020年已经达到约4410亿美元。云计算还促使了数字原生业务（DNB）的崛起。它推动了Uber、Deliveroo、TikTok和Instagram等组织的兴起，仅举几例。&lt;/p&gt;
 &lt;p&gt;云计算对数据而言是一种福音。随着云计算的兴起，数据现在可以以较低的成本存储。云提供的相对无限的计算能力意味着能够迅速转换数据。云计算还提供创新的数据平台，可以轻松点击利用。&lt;/p&gt;
 &lt;p&gt;这五个因素在一个适当的时刻相互交汇，挑战了现有的数据架构模式。完美“数据”风暴促使了一个以大数据为重点的新数据架构范式的崛起，即数据湖。&lt;/p&gt;
 &lt;h1&gt;探讨数据湖时代&lt;/h1&gt;
 &lt;p&gt;数据湖的起源可以追溯到2004年。在2004年，Google的研究人员Jeffery Dean和Sanjay Ghemawat发表了一篇题为《MapReduce: Simplified Data Processing on Large Clusters》的论文。这篇论文奠定了一项新技术的基础，演变成了Hadoop，最初的作者是Doug Cutting和Mike Cafarella。 Hadoop后来被整合到了Apache Software Foundation，这是一个分散的开源开发者社区。Hadoop一直是Apache生态系统中最重要的开源项目之一。 Hadoop基于一个简单的概念——分而治之。这个想法包括三个步骤：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;将数据分发到多个文件，并将它们分布在集群中的各个节点上。&lt;/li&gt;
  &lt;li&gt;使用计算节点在每个集群节点上本地处理数据。&lt;/li&gt;
  &lt;li&gt;使用与每个节点通信并聚合数据以得到最终输出的编排器。 多年来，这个概念逐渐获得了推广，为分析出现了一种新的范式。这种架构范式就是数据湖范式。一个典型的数据湖模式可以在下图中描述：&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/32554f280e404551b5474fa6371d61a3~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1315&amp;h=575&amp;s=152193&amp;e=png&amp;b=fefefe"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;这种模式解决了企业数据仓库（EDW）模式中普遍存在的挑战。数据湖架构模式能够提供的优势是显而易见的。其主要优势包括：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;数据湖适用于结构化和非结构化数据。Hadoop生态系统最初是为存储和处理JSON、文本和图像等数据格式而开发的。而EDW模式并未设计用于存储或分析这些数据类型。&lt;/li&gt;
  &lt;li&gt;数据湖模式可以以相对较低的成本处理大量数据。数据湖可以存储和处理的数据量可达高TB或PB级。而EDW模式发现难以高效地存储和处理这么大量的数据。&lt;/li&gt;
  &lt;li&gt;数据湖能更好地应对快速变化的业务需求。不断发展的人工智能技术可以更好地利用数据湖。&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;尽管这种模式得到了广泛采用，但它也有自己的挑战。与这种模式相关的一些挑战包括：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;数据湖很容易变成数据沼泽。数据湖接收各种形式的数据，并以其原始形式存储。其理念是首先摄取数据，然后再弄清楚如何处理它。这导致治理方面容易失控，对数据湖的治理变得具有挑战性。没有适当的数据治理，数据就会在数据湖的各个地方迅速增多，很快就变成了数据沼泽。&lt;/li&gt;
  &lt;li&gt;数据湖在技术快速发展方面也面临挑战。数据湖范式主要依赖于开源软件。开源软件迅速演变成难以管理的庞然大物。该软件主要由社区驱动，缺乏适当的企业支持。这导致了大量的维护开销和实施复杂性。企业需要的许多功能在开源软件中缺失，例如健壮的安全框架。&lt;/li&gt;
  &lt;li&gt;数据湖更注重于AI的支持，而非BI。随着开源软件演变，更多的关注点集中在支持人工智能上。人工智能正在经历自己的发展过程，并随着Hadoop的潮涌而起伏。而BI被视为过时，因为它已经成熟了。&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;很快就变得明显，单独采用数据湖模式在长期内是不可持续的。需要一种新的范式将这两种模式融合起来。&lt;/p&gt;
 &lt;h2&gt;介绍数据湖仓范式&lt;/h2&gt;
 &lt;p&gt;在2006年，英国数学家Clive Humbly创造了如今著名的短语：“数据是新石油。” 这就像透过水晶球，窥探未来。数据是组织的生命线。竞争优势取决于组织如何使用数据。在这个数字化转型的时代，数据管理至关重要。越来越多的组织正在拥抱数字化转型计划，而数据是这些转型的核心。&lt;/p&gt;
 &lt;p&gt;正如前面讨论的，企业数据仓库（EDW）和数据湖的范式在它们的时代是合适的。它们有它们的优势和挑战。需要出现一种新的范式，它在核心上是有纪律的，而在边缘上是灵活的。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5c7075048c364b8ca8782ca51e6464ad~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1341&amp;h=869&amp;s=306240&amp;e=png&amp;b=fefefe"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;新的数据架构范式被称为数据湖仓。它努力将数据湖和企业数据仓库（EDW）这两种范式的优势结合起来，同时尽量减少它们的挑战。&lt;/p&gt;
 &lt;p&gt;一个经过适当架构的数据湖仓提供了四个关键优势。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8d07679a47104f3ea2d01948d3f10c5f~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=683&amp;h=561&amp;s=103106&amp;e=png&amp;b=ffffff"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;它从结构化和非结构化数据中获取洞察：数据湖仓架构应能够存储、转换和整合结构化和非结构化数据。它应能够将它们融合在一起，实现从数据中提取有价值洞察。&lt;/p&gt;
 &lt;p&gt;它满足组织的不同角色需求：数据是一道供不同角色品尝的美食。数据湖仓应能够满足这些角色的需求。数据湖仓满足一系列组织角色的需求，满足他们对洞察的要求。数据科学家应该有一个测试他们假设的场所。分析师应该能够使用他们选择的工具分析数据，业务用户应该能够准确及时地获得他们的报告。它使数据分析民主化。&lt;/p&gt;
 &lt;p&gt;它促进了强大治理框架的采用：数据湖架构模式的主要挑战是缺乏强大的治理框架。数据湖很容易变成数据沼泽。相比之下，企业数据仓库架构由于内容太少而受到过多治理的限制。数据湖仓架构力求在治理方面取得平衡。它力求为正确的数据类型实现适当的治理，并使正确的利益相关方能够访问。&lt;/p&gt;
 &lt;p&gt;它利用云计算：数据湖仓架构需要具备灵活性和创新性。该模式需要适应不断变化的组织需求，缩短数据转化为洞察的时间。为了实现这种灵活性，采用云计算技术是必不可少的。云计算平台提供所需的创新性。它提供了具有可伸缩性和灵活性的适当技术堆栈，并满足现代数据分析平台的需求。&lt;/p&gt;
 &lt;p&gt;数据湖仓范式解决了企业数据仓库和数据湖范式所面临的挑战。然而，它确实有自己一套需要管理的挑战。其中一些挑战包括：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;   &lt;strong&gt;架构复杂性：&lt;/strong&gt; 鉴于数据湖仓模式融合了企业数据仓库和数据湖模式，它必然会具有相当一部分的架构复杂性。这种复杂性体现在实现该模式所需的多个组件中。架构模式是一种交换，因此在架构复杂性与潜在业务收益之间进行仔细权衡至关重要。数据湖仓架构需要小心谨慎地走这条路。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;全面数据治理的需要：&lt;/strong&gt; 与数据湖范式相关的挑战并没有随着数据湖仓范式的出现而神奇地消失。数据湖最大的问题之一是它容易变成数据沼泽。随着数据湖仓在范围和复杂性上的增长，缺乏全面治理框架是将数据湖仓变成沼泽的一种确切方式。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;在灵活性与纪律之间平衡：&lt;/strong&gt; 数据湖仓范式力求在核心上具有灵活性，以及在边缘上具有适应不断变化的业务需求的灵活性。它运作的原则是在核心上保持纪律，在边缘上保持灵活性。实现这一目标是一种谨慎的平衡行为，清晰地定义灵活性的界限和纪律的严格性。数据湖仓的管理者在确保这种平衡方面发挥着关键作用。&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;让我们回顾一下我们在本章讨论的内容。&lt;/p&gt;
 &lt;h1&gt;总结&lt;/h1&gt;
 &lt;p&gt;这一章是关于新范式的起源。了解起源是重要的，这样我们就能理解前任的不足之处以及新框架如何发展以解决这些不足之处。了解导致这种演变的驱动因素也很重要。技术领域的其他发展，如存储、云计算和人工智能，对数据架构产生了涟漪效应。在这一章中，我们首先探讨了长时间占主导地位的EDW架构模式。然后，我们探讨了导致完美的“数据”风暴的因素。随后，本章深入探讨了数据湖架构模式。接着讨论了新的架构范式——数据湖仓的需求。最后，本章总结了新架构范式的关键优势。&lt;/p&gt;
 &lt;p&gt;下一章旨在深入研究数据湖仓架构的组件。&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62883-%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90-%E6%A8%A1%E5%BC%8F</guid>
      <pubDate>Sun, 19 Nov 2023 16:44:39 CST</pubDate>
    </item>
    <item>
      <title>打造企业级智能问答系统的秘密：如何使用云数据库 PostgreSQL 版实现向量检索...</title>
      <link>https://itindex.net/detail/62879-%E4%BC%81%E4%B8%9A-%E6%99%BA%E8%83%BD-%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F</link>
      <description>&lt;div&gt;    &lt;p&gt;本文就如何利用火山引擎云数据库 PostgreSQL 版和大语言模型技术（Large Language Model，简称 LLM），实现企业级智能交互式问答系统进行介绍。通过本文，你将会了解交互式问答系统的原理，学习 PostgreSQL 的向量化存储和检索技术，以及大语言模型交互技术等。&lt;/p&gt;    &lt;h3&gt;背景&lt;/h3&gt;    &lt;p&gt;在大数据的浪潮下，众多企业建立了自己的知识库，以便于信息检索和知识查询。然而，随着知识库内容的膨胀，传统的信息检索方式变得低效，经常出现费时费力且结果不尽人意的情况。随着生成式人工智能（AI Generated Content，简称 AIGC）的出现，人们看到了一种更智能的实现方式，通过问答的方式，知识获取的效率、准确性和用户体验在多方面得到提升。&lt;/p&gt;    &lt;p&gt;即便如此，对于特定垂直领域的企业，生成式人工智能的局限性也开始显现，例如大模型训练周期长、对某一领域专业知识掌握不足等，这常常会导致 AI“幻觉”问题的出现（即 AI 的“一本正经地胡说八道”）。为了解决这一难题，我们通常会采用以下两种方式：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;Fine Tune 方法，“驯服”大语言模型。&lt;/p&gt;        &lt;ul&gt;          &lt;li&gt;            &lt;p&gt;利用领域知识，对大语言模型进行监督微调（Supervised Fine Tune）和蒸馏（Distillation）。这种方式可塑性强，但需要大量的算力和人才资源，综合成本高。此外，企业还需要持续监控和更新模型，以确保与不断变化的领域知识保持同步。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;Prompt Engineering 方法，改变“自己”。&lt;/p&gt;        &lt;ul&gt;          &lt;li&gt;            &lt;p&gt;该方法基于向量数据库，补充足够的对话上下文和参考资料，完善与大语言模型进行交互的问答问题（Prompt），其本质是将大语言模型的推理归纳能力与向量化信息检索能力相结合，从而快速建立能够理解特定语境和逻辑的问答系统。该方法的实现成本相对较低。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;接下来，本文针对 Prompt Engineering 方法，来演示将云数据库 PostgreSQL 版作为向量数据库的使用方法。&lt;/p&gt;    &lt;h3&gt;核心概念及原理&lt;/h3&gt;    &lt;h4&gt;嵌入向量（Embedding Vectors）&lt;/h4&gt;    &lt;p&gt;向量 Embedding 是在自然语言处理和机器学习中广泛使用的概念。各种文本、图片或其他信号，均可通过一些算法转换为向量化的 Embedding。在向量空间中，相似的词语或信号距离更近，可以用这种性质来表示词语或信号之间的关系和相似性。例如，通过一定的向量化模型算法，将如下三句话，转换成二维向量（x，y），我们可通过坐标系来画出这些向量的位置，它们在二维坐标中的远近，就显示了其相似性，坐标位置越接近，其内容就越相似。如下图所示：&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;“今天天气真好，我们出去放风筝吧”
“今天天气真好，我们出去散散步吧”
“这么大的雨，我们还是在家呆着吧”&lt;/code&gt;&lt;/pre&gt;    &lt;img alt="786dfb750e173303877415a82edc29bb.png" src="https://img-blog.csdnimg.cn/img_convert/786dfb750e173303877415a82edc29bb.png"&gt;&lt;/img&gt;    &lt;h4&gt;Prompt Engineering 过程原理&lt;/h4&gt;    &lt;p&gt;如上所说，使用者需要不断调整输入提示，从而获得相关领域的专业回答。输入模型的相关提示内容越接近问题本身，模型的输出越趋近于专业水平。通俗理解就是，模型能够利用所输入的提示信息，从中抽取出问题的答案，并总结出一份专业水准的回答。整个 Prompt Engineering 工作流程如下图所示：&lt;/p&gt;    &lt;img alt="df8c4e91120fb924dd883c913ebaeebb.jpeg" src="https://img-blog.csdnimg.cn/img_convert/df8c4e91120fb924dd883c913ebaeebb.jpeg"&gt;&lt;/img&gt;    &lt;p&gt;其大致可以分为两个阶段：      &lt;strong&gt;向量构建阶段和问答阶段&lt;/strong&gt;。在向量构建阶段，将企业知识库的所有文档，分割成内容大小适当的片段，然后通过 Embeddings 转换算法，例如 OpenAI 的模型 API（https://platform.openai.com/docs/guides/embeddings/what-are-embeddings），将其转换成 Embeddings 数据，存储于云数据库 PostgreSQL 版向量数据库中，详细流程如下图所示：&lt;/p&gt;    &lt;img alt="623a012d2537a0a6292ab905476b3424.png" src="https://img-blog.csdnimg.cn/img_convert/623a012d2537a0a6292ab905476b3424.png"&gt;&lt;/img&gt;    &lt;p&gt;在问答阶段，问答系统首先接收用户的提问，并将其转化为 Embedding 数据，然后通过与向量化的问题进行相似性检索，获取最相关的 TOP N 的知识单元。接着，通过 Prompt 模板将问题、最相关的 TOP N 知识单元、历史聊天记录整合成新的问题。大语言模型将理解并优化这个问题，然后返回相关结果。最后，系统将结果返回给提问者。流程如下图所示：&lt;/p&gt;    &lt;img alt="8a2bf673b0068160f1394c74050431bb.png" src="https://img-blog.csdnimg.cn/img_convert/8a2bf673b0068160f1394c74050431bb.png"&gt;&lt;/img&gt;    &lt;h3&gt;实现过程&lt;/h3&gt;    &lt;p&gt;接下来将介绍如何利用云数据库 PostgreSQL 版提供的 pg_vector 插件构建用于向量高效存储、检索的向量数据库。&lt;/p&gt;    &lt;h4&gt;前置条件&lt;/h4&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;已创建 ECS 实例，或者使用本地具备 Linux 环境的主机，作为访问数据库的客户端机器。&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;请确保您具备 OpenAI Secret API Key，并且您的网络环境可以使用 OpenAI。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;h4&gt;训练步骤&lt;/h4&gt;    &lt;p&gt;本文将以构建企业专属“数据库顾问”问答系统为例，演示整个构建过程。使用的知识库样例为https://www.postgresql.org/docs/15/index.html，脚本获取方式详见文末。&lt;/p&gt;    &lt;blockquote&gt;      &lt;p&gt;搭建的环境基于 Debian 9.13，以下方案仅供参考，环境不同依赖包安装有所差异。&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;以下过程包括两个主要脚本文件，构建知识库的      &lt;strong&gt;generate-embeddings.ts&lt;/strong&gt;，问答脚本      &lt;strong&gt;queryGPT.py&lt;/strong&gt;，建议组织项目目录如下所示：&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;.
├── package.json                              // ts依赖包
├── docs
│   ├── PostgreSQL15.mdx                      // 知识库文档
├── script
│   ├── generate-embeddings.ts                // 构建知识库
│   ├── queryGPT.py                           // 问答脚本&lt;/code&gt;&lt;/pre&gt;    &lt;h4&gt;1. 学习阶段&lt;/h4&gt;    &lt;h5&gt;1. 创建 PostgreSQL 实例&lt;/h5&gt;    &lt;p&gt;登录云数据库 PostgreSQL 版控制台（https://console.volcengine.com/db/rds-pg）创建实例，并创建数据库和账号。关于创建 PostgreSQL 实例、数据库、账号的详细信息，请参见云数据库 PostgreSQL 版快速入门（https://www.volcengine.com/docs/6438/79234）。&lt;/p&gt;    &lt;h5&gt;2. 创建插件&lt;/h5&gt;    &lt;p&gt;进入测试数据库，并创建 pg_vector 插件。&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;create extension if not exists vector;&lt;/code&gt;&lt;/pre&gt;    &lt;p&gt;创建对应的数据库表，其中表 doc_chunks 中的字段 embedding 即为表示知识片段的向量。&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;-- 记录文档信息
create table docs (
  id bigserial primary key,
  -- 父文档ID
  parent_doc bigint references docs,
  -- 文档路径
  path text not null unique,
  -- 文档校验值
  checksum text
);
-- 记录chunk信息
create table doc_chunks (
  id bigserial primary key,
  doc_id bigint not null references docs on delete cascade, -- 文档ID
  content text, -- chunk内容
  token_count int, -- chunk中的token数量
  embedding vector(1536), -- chunk转化成的embedding向量
  slug text, -- 为标题生成唯一标志
  heading text -- 标题
);&lt;/code&gt;&lt;/pre&gt;    &lt;h5&gt;3. 构建向量知识库&lt;/h5&gt;    &lt;p&gt;在客户端机器上，将知识库文档内容，分割成内容大小适当的片段，通过 OpenAI 的 embedding 转化接口，转化成embedding 向量，并存储到数据库，参考脚本获取方式详见文末。&lt;/p&gt;    &lt;blockquote&gt;      &lt;p&gt;        &lt;strong&gt;注意&lt;/strong&gt;该脚本只能处理 markdown 格式的文件。&lt;/p&gt;&lt;/blockquote&gt;    &lt;p&gt;安装 pnpm：&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;curl -fsSL https://get.pnpm.io/install.sh | sh -&lt;/code&gt;&lt;/pre&gt;    &lt;p&gt;安装 nodejs（参考https://github.com/nodesource/distributions）：&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
NODE_MAJOR=16
echo &amp;quot;deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main&amp;quot; | sudo tee /etc/apt/sources.list.d/nodesource.list
sudo apt-get update
sudo apt-get install nodejs -y&lt;/code&gt;&lt;/pre&gt;    &lt;p&gt;安装 typescript 依赖，配置文件 package.json 获取方式详见文末：&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;pnpm run setup
pnpm install tsx&lt;/code&gt;&lt;/pre&gt;    &lt;p&gt;修改 generate-embeddings.ts，设置 OpenAI 的 key、PG 的连接串以及 markdown 文档目录：&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;#这里需要将user、passwd、127.0.0.1、5432 替换为实际数据库用户、密码、数据库地址、端口
const postgresql_url = &amp;apos;pg://user:passwd@127.0.0.1:5432/database&amp;apos;;
const openai_key = &amp;apos;-------------&amp;apos;;
const SOURCE_DIR = path.join(__dirname, &amp;apos;document path&amp;apos;);&lt;/code&gt;&lt;/pre&gt;    &lt;p&gt;运行脚本，生成文档 embedding 向量并插入数据库：&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;pnpm tsx script/generate-embeddings.ts&lt;/code&gt;&lt;/pre&gt;    &lt;p&gt;运行过程：&lt;/p&gt;    &lt;img alt="05166731a0d641b7ab9788edc98e7002.png" src="https://img-blog.csdnimg.cn/img_convert/05166731a0d641b7ab9788edc98e7002.png"&gt;&lt;/img&gt;    &lt;p&gt;脚本运行后，我们查看下所构建的知识库。查询 docs 表：&lt;/p&gt;    &lt;img alt="26c4130a573ddba1bd20d1e23625304c.png" src="https://img-blog.csdnimg.cn/img_convert/26c4130a573ddba1bd20d1e23625304c.png"&gt;&lt;/img&gt;    &lt;p&gt;查询 docs_chunk 表，批量导入向量成功：&lt;/p&gt;    &lt;img alt="8f91397dbd47d9313fe0f0e7307a774d.png" src="https://img-blog.csdnimg.cn/img_convert/8f91397dbd47d9313fe0f0e7307a774d.png"&gt;&lt;/img&gt;    &lt;h4&gt;2. 问答阶段&lt;/h4&gt;    &lt;h5&gt;1. 创建相似度计算函数&lt;/h5&gt;    &lt;p&gt;为了方便应用使用，使用 PostgreSQL 的自定义函数功能，创建内置于数据库内的函数。应用只需调用 PostgreSQL，该函数便可在应用程序中获取向量匹配结果。示例中使用“内积”来计算向量的相似性。&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;create or replace function match_chunks(chunck_embedding vector(1536), threshold float, count int, min_length int)
returns table (id bigint, content text, similarity float)
language plpgsql
as $$
begin
  return query
  select
    doc_chunks.id,
    doc_chunks.content,
    (doc_chunks.embedding &amp;lt;#&amp;gt; chunck_embedding) * -1 as similarity
  from doc_chunks

  -- chunk内容大于设定的长度
  where length(doc_chunks.content) &amp;gt;= min_length

  -- The dot product is negative because of a Postgres limitation, so we negate it
  and (doc_chunks.embedding &amp;lt;#&amp;gt; chunck_embedding) * -1 &amp;gt; threshold
  order by doc_chunks.embedding &amp;lt;#&amp;gt; chunck_embedding
  
  limit count;
end;
$$;&lt;/code&gt;&lt;/pre&gt;    &lt;h5&gt;2. 提问及回答&lt;/h5&gt;    &lt;p&gt;以下 Python 程序，可以接收提问者问题，并实现上述 Prompt Engineering 的“问答阶段”的功能，最终将具备“逻辑思考”+“深度领域知识”的解答，发送给提问者。&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;import os, psycopg2, openai

def query_handler(query = None):
    if query is None or query == &amp;quot;&amp;quot;:
        print(&amp;apos;请输入有效问题&amp;apos;)
        return

    query = query.strip().replace(&amp;apos;\n&amp;apos;, &amp;apos; &amp;apos;)
    embedding = None
    try:
        # 使用 GPT 将提问转化为 embedding 向量
        response = openai.Embedding.create(
            engine=&amp;quot;text-embedding-ada-002&amp;quot;,  # 固定为text-embedding-ada-002
            input=[query],
        )
        embedding = response.data[0].embedding
    except Exception as ex:
        print(ex)
        return

    content = &amp;quot;&amp;quot;
    con = None
    try:
        # 处理 postgres 配置，连接数据库
        # host:127.0.0.1,port:5432,user:test,password:test,database:test
        params = postgresql_url.split(&amp;apos;,&amp;apos;)
        database, user, password, host, port = &amp;quot;test&amp;quot;, &amp;quot;test&amp;quot;, &amp;quot;test&amp;quot;, &amp;quot;127.0.0.1&amp;quot;, &amp;quot;5432&amp;quot;
        for param in params:
            pair = param.split(&amp;apos;:&amp;apos;)
            if len(pair) != 2:
                print(&amp;apos;POSTGRESQL_URL error: &amp;apos; + postgresql_url)
                return
            k, v = pair[0].strip(), pair[1].strip()
            if k == &amp;apos;database&amp;apos;:
                database = v
            elif k == &amp;apos;user&amp;apos;:
                user = v
            elif k == &amp;apos;password&amp;apos;:
                password = v
            elif k == &amp;apos;host&amp;apos;:
                host = v
            elif k == &amp;apos;port&amp;apos;:
                port = v
        # connect postgres
        con = psycopg2.connect(database=database, user=user, password=password, host=host, port=port)
        cur = con.cursor()
        # 从数据库查询若干条最接近提问的 chunk
        sql = &amp;quot;select match_chunks(&amp;apos;[&amp;quot; + &amp;apos;,&amp;apos;.join([str(x) for x in embedding]) + &amp;quot;]&amp;apos;, 0.78, 5, 50)&amp;quot;
        cur.execute(sql)
        rows = cur.fetchall()
        for row in rows:
            row = row[0][1:-2].split(&amp;apos;,&amp;apos;)[-2][1:-2].strip()
            content = content + row + &amp;quot;\n---\n&amp;quot;

    except Exception as ex:
        print(ex)
        return

    finally:
        if con is not None:
            con.close()

    try:
        # 组织提问和 chunk 内容，发送给 GPT
        prompt = &amp;apos;&amp;apos;&amp;apos;Pretend you are GPT-4 model , Act an database expert.
        I will introduce a database scenario for which you will provide advice and related sql commands.
        Please only provide advice related to this scenario. Based on the specific scenario from the documentation,
        answer the question only using that information. Please note that if there are any updates to the database
        syntax or usage rules, the latest content shall prevail. If you are uncertain or the answer is not explicitly
        written in the documentation, please respond with &amp;quot;I&amp;apos;m sorry, I cannot assist with this.\n\n&amp;apos;&amp;apos;&amp;apos; + &amp;quot;Context sections:\n&amp;quot; + \
        content.strip().replace(&amp;apos;\n&amp;apos;, &amp;apos; &amp;apos;) + &amp;quot;\n\nQuestion:&amp;quot;&amp;quot;&amp;quot;&amp;quot; + query.replace(&amp;apos;\n&amp;apos;, &amp;apos; &amp;apos;) + &amp;quot;&amp;quot;&amp;quot;&amp;quot;\n\nAnswer:&amp;quot;

        print(&amp;apos;\n正在处理，请稍后。。。\n&amp;apos;)
        response = openai.ChatCompletion.create(
            engine=&amp;quot;gpt_openapi&amp;quot;,  # 固定为gpt_openapi
            messages=[
                {&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: prompt}
            ],
            model=&amp;quot;gpt-35-turbo&amp;quot;,
            temperature=0,
        )
        print(&amp;apos;回答:&amp;apos;)
        print(response[&amp;apos;choices&amp;apos;][0][&amp;apos;message&amp;apos;][&amp;apos;content&amp;apos;])

    except Exception as ex:
        print(ex)
        return

os.environ[&amp;apos;OPENAI_KEY&amp;apos;] = &amp;apos;-----------------------&amp;apos;
os.environ[&amp;apos;POSTGRESQL_URL&amp;apos;] = &amp;apos;host:127.0.0.1,port:5432,user:test,password:test,database:test&amp;apos;
openai_key = os.getenv(&amp;apos;OPENAI_KEY&amp;apos;)
postgresql_url = os.getenv(&amp;apos;POSTGRESQL_URL&amp;apos;)
# openai config
openai.api_type = &amp;quot;azure&amp;quot;
openai.api_base = &amp;quot;https://example-endpoint.openai.azure.com&amp;quot;
openai.api_version = &amp;quot;2023-XX&amp;quot;
openai.api_key = openai_key

def main():
    if openai_key is None or postgresql_url is None:
        print(&amp;apos;Missing environment variable OPENAI_KEY, POSTGRESQL_URL(host:127.XX.XX.XX,port:5432,user:XX,password:XX,database:XX)&amp;apos;)
        return
    print(&amp;apos;我是您的PostgreSQL AI助手，请输入您想查询的问题，例如：\n1、如何创建table？\n2、给我解释一下select语句？\n3、如何创建一个存储过程？&amp;apos;)
    while True:
        query = input(&amp;quot;\n输入您的问题:&amp;quot;)
        query_handler(query)
        
if __name__ == &amp;quot;__main__&amp;quot;:
    main()&lt;/code&gt;&lt;/pre&gt;    &lt;p&gt;先修改 90、91 行的 OpenAI 的 key 和 PG 的连接串，为实际 key 和连接地址：&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;os.environ[&amp;apos;OPENAI_KEY&amp;apos;] = &amp;apos;-----------------------&amp;apos;
os.environ[&amp;apos;POSTGRESQL_URL&amp;apos;] = &amp;apos;host:127.0.0.1,port:5432,user:test,password:test,database:test&amp;apos;&lt;/code&gt;&lt;/pre&gt;    &lt;p&gt;然后修改 GPT 的参数：&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;openai.api_type = &amp;quot;azure&amp;quot;
openai.api_base = &amp;quot;https://example-endpoint.openai.azure.com&amp;quot;
openai.api_version = &amp;quot;2023-XX&amp;quot;&lt;/code&gt;&lt;/pre&gt;    &lt;p&gt;其次通过修改机器人自我介绍，以让提问者快速了解问答机器人的专业特长，这里的自我介绍，说明机器人是一个数据库专家的角色。&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;prompt = &amp;apos;&amp;apos;&amp;apos;Pretend you are GPT-4 model , Act an database expert.
        I will introduce a database scenario for which you will provide advice and related sql commands.
        Please only provide advice related to this scenario. Based on the specific scenario from the documentation,
        answer the question only using that information. Please note that if there are any updates to the database
        syntax or usage rules, the latest content shall prevail. If you are uncertain or the answer is not explicitly
        written in the documentation, please respond with &amp;quot;I&amp;apos;m sorry, I cannot assist with this.\n\n&amp;apos;&amp;apos;&amp;apos; + &amp;quot;Context sections:\n&amp;quot; + \
        content.strip().replace(&amp;apos;\n&amp;apos;, &amp;apos; &amp;apos;) + &amp;quot;\n\nQuestion:&amp;quot;&amp;quot;&amp;quot;&amp;quot; + query.replace(&amp;apos;\n&amp;apos;, &amp;apos; &amp;apos;) + &amp;quot;&amp;quot;&amp;quot;&amp;quot;\n\nAnswer:&amp;quot;&lt;/code&gt;&lt;/pre&gt;    &lt;p&gt;最后安装脚本依赖：&lt;/p&gt;    &lt;pre&gt;      &lt;code&gt;pip install psycopg2-binary
pip install openai
pip install &amp;apos;openai[datalib]&amp;apos;&lt;/code&gt;&lt;/pre&gt;    &lt;p&gt;测试过程：&lt;/p&gt;    &lt;img alt="6f6332194c9fd1635100c602c9cfd57b.jpeg" src="https://img-blog.csdnimg.cn/img_convert/6f6332194c9fd1635100c602c9cfd57b.jpeg"&gt;&lt;/img&gt;    &lt;p&gt;到此为止，您就获得了一个企业级专属智能问答系统。&lt;/p&gt;    &lt;h3&gt;方案优势&lt;/h3&gt;    &lt;p&gt;相较于其他向量数据库，借助火山引擎云数据库 PostgreSQL 版提供的 pg_vector 插件构建的向量数据库具有如下优势：&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;p&gt;          &lt;strong&gt;使用便捷易上手：&lt;/strong&gt;无需专业 AI 专家介入，无需构建其他大规模复杂分布式集群，只需要一个数据库实例，便可构建专用向量数据库。使用接口兼容现有 SQL 语法，不需要定制化调度框架、终端。&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;          &lt;strong&gt;性价比高：&lt;/strong&gt;可使用已有数据库实例，不需要额外购买其他庞大的集群资源。&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;          &lt;strong&gt;数据实时更新可用：&lt;/strong&gt;向量数据可以在毫秒级实现新增、更新，并且依然具备事务属性，无需担心数据的错乱。&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;          &lt;strong&gt;支持高并发，扩展容易：&lt;/strong&gt;在向量化场景可支持数千 TPS；在性能出现瓶颈时，可以通过一键扩展只读节点，轻松实现整体吞吐的瞬间提升。&lt;/p&gt;&lt;/li&gt;      &lt;li&gt;        &lt;p&gt;          &lt;strong&gt;支持向量维度高：&lt;/strong&gt;pg_vector 还具备支持向量维度高的特点。最多可支持 16000 维向量，能够满足绝大部分向量化存储、使用场景。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62879-%E4%BC%81%E4%B8%9A-%E6%99%BA%E8%83%BD-%E9%97%AE%E7%AD%94%E7%B3%BB%E7%BB%9F</guid>
      <pubDate>Thu, 16 Nov 2023 14:01:26 CST</pubDate>
    </item>
    <item>
      <title>数据库分类分级做完了，接下来怎么用</title>
      <link>https://itindex.net/detail/62855-%E6%95%B0%E6%8D%AE%E5%BA%93-%E5%88%86%E7%B1%BB-%E5%88%86%E7%BA%A7</link>
      <description>&lt;div&gt;    &lt;h2&gt;      &lt;strong&gt;01/7    数据分类分级的难点回顾&lt;/strong&gt;&lt;/h2&gt;    &lt;p&gt;之前一篇文章内，我们大致讲述了近两年来在各大企业和机构内大热的数据分类分级运动的由来，以及数据分类分级的难点。简单总结起来其困境主要来源于企业内部系统构建的个性化程度高，如基于数据字段命名并无法推测出实质数据类型（见下图所示，text1 并不能被自动识别为姓名数据）；或者组合类的数据类型和业务关联度高的数据类型，无法抽象为技术可描述的确定规则，如财务数据、金融数据、快递数据这种大类的数据类型；或者一大部分的数据并不具备强规则特征，无法通过对数据内容的识别从而进行类型的分类，如用户姓名、金额数字等等。      &lt;img alt="" height="132" src="https://image.3001.net/images/20230922/1695359870_650d237e974c9d1b2f478.png!small" width="690"&gt;&lt;/img&gt;      &lt;br /&gt;回顾上一篇内容：      &lt;a href="http://mp.weixin.qq.com/s?__biz=Mzg2MTk4MDM1Mg==&amp;mid=2247483764&amp;idx=1&amp;sn=10d3480a4ef3de3e40b149577b7db723&amp;chksm=ce0f92dbf9781bcd6b54ed9fe7a1df11b85efebf346f551e65e53ed9e608b5fa0d26511473d6&amp;scene=21#wechat_redirect" rel="noreferrer noopener" target="_blank"&gt;        &lt;strong&gt;数据分类分级，难成通用且标准化的技术产品&lt;/strong&gt;&lt;/a&gt;      &lt;br /&gt;正是由于上述这些困境，让数据分类分级并未带来一场技术上的盛宴，而是上演了一场声势浩大的人工运动，而且是一场针对数据库而不是针对数据的运动，耗时耗力。数据到处都有，除了关系型的数据库里之外，还流动在网络请求里、展示在应用页面中、躺在各类文档上。数据分类分级在数据库层面，人工尚还能上手，到了应用、网络和文档里，那可真是连下手的机会都没有了。这也就解释了本篇文章的标题为何是“      &lt;strong&gt;数据库分类分级&lt;/strong&gt;”了。&lt;/p&gt;    &lt;h2&gt;      &lt;strong&gt;02/7    数据库分类分级的临时性产出&lt;/strong&gt;&lt;/h2&gt;    &lt;p&gt;当前的数据分类分级重在资产盘点，就如同要详细整理出自家有多少资产一样，家里有多少张桌子、几把椅子、存款几何、车几辆、衣服多少件。整理结束，得到的就是不同维度的几张清单，当然这些清单不是打印到 A4 纸上的临时性记录，而是也会以结构化的数据存在，变成描述企业数据资产的数据。那么常见的是哪些清单呢：      &lt;br /&gt;      &lt;strong&gt;1、《数据资产清单》&lt;/strong&gt;企业内有多少个应用，每个应用对应了多少个数据库，每个数据库对应了多少张数据表，每个数据表的数据量（字段数目、数据行数、数据存储空间大小）等等。      &lt;strong&gt;2、《数据分类分级清单》&lt;/strong&gt;与现有数据库一一映射的数据分类分级清单，如下面这样子的表格记录。&lt;/p&gt;    &lt;table&gt;      &lt;tr&gt;        &lt;th&gt;数据库名&lt;/th&gt;        &lt;th&gt;数据表名&lt;/th&gt;        &lt;th&gt;字段名&lt;/th&gt;        &lt;th&gt;数据类型&lt;/th&gt;        &lt;th&gt;安全等级&lt;/th&gt;&lt;/tr&gt;      &lt;tr&gt;        &lt;td valign="top"&gt;db_customer&lt;/td&gt;        &lt;td valign="top"&gt;cus_details&lt;/td&gt;        &lt;td valign="top"&gt;name&lt;/td&gt;        &lt;td valign="top"&gt;姓名&lt;/td&gt;        &lt;td valign="top"&gt;C3&lt;/td&gt;&lt;/tr&gt;      &lt;tr&gt;        &lt;td valign="top"&gt;db_customer&lt;/td&gt;        &lt;td valign="top"&gt;cus_details&lt;/td&gt;        &lt;td valign="top"&gt;sex&lt;/td&gt;        &lt;td valign="top"&gt;性别&lt;/td&gt;        &lt;td valign="top"&gt;C3&lt;/td&gt;&lt;/tr&gt;      &lt;tr&gt;        &lt;td valign="top"&gt;db_customer&lt;/td&gt;        &lt;td valign="top"&gt;cus_details&lt;/td&gt;        &lt;td valign="top"&gt;age&lt;/td&gt;        &lt;td valign="top"&gt;年龄&lt;/td&gt;        &lt;td valign="top"&gt;C3&lt;/td&gt;&lt;/tr&gt;      &lt;tr&gt;        &lt;td valign="top"&gt;db_customer&lt;/td&gt;        &lt;td valign="top"&gt;cus_details&lt;/td&gt;        &lt;td valign="top"&gt;phone&lt;/td&gt;        &lt;td valign="top"&gt;电话号码&lt;/td&gt;        &lt;td valign="top"&gt;C3&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;    &lt;p&gt;为什么这些清单叫做临时性的结果呢？因为应用或者业务系统是在不断迭代升级的，其结果就是对应的数据库和表结构会变化，数据库、表格、字段都在不停地增、删、改，对应的资产清单记录由于是人肉加工的结果，缺乏自动化的同步更新机制，势必导致资产清单的过时。对于平台型的企业，如大部分的科技企业，本身都是自研产品为主，那么只需要配合规范的内部开发流程，如应用开发者在涉及到数据库的变动的时候，必须同步更新元数据库（即上述资产清单），否则不予批准代码的推送和应用发布，如此才可保证资产清单的实时性和权威性地位。相反，对于大量依赖第三方服务商提供系统的机构，如政务部门和银行，这个问题将变得非常尖锐，每次系统的更新就意味着对历史资产清单的否定了。&lt;/p&gt;    &lt;h2&gt;      &lt;strong&gt;03/7    数据库分类分级的产出能用来做什么&lt;/strong&gt;&lt;/h2&gt;    &lt;p&gt;当每一份关于数据安全的国家标准都写明要搞数据分类分级的时候，当每一次安全研讨会议各大专家都在强调要抓紧落实数据分类分级的时候，当每个安全服务商都在宣传自己强大的数据分类分级能力的时候，谁要是唱反调说分类分级不重要，那必定成为众矢之的。但每当我提问，做完了数据分类分级，接下来做什么的时候，换来的通常是尴尬的一阵沉默。沉默的是拿着各类数据资产清单，真的不知道该如何下手去用起来，大家的愿景还是极其朴素和一致的，那就是“      &lt;strong&gt;基于分类分级的结果，针对不同安全等级的敏感数据，施加不同程度的安全管控策略&lt;/strong&gt;”。      &lt;br /&gt;在安全从业者的构想里，可以落地这样一些安全管控敏感数据的场景：      &lt;br /&gt;      &lt;strong&gt;1、&lt;/strong&gt;依据不同的数据安全等级，施行不同的数据使用审批流程，如数据表格的使用审批流程（数据库层面），应用内数据下载的审批流程（应用层面）。      &lt;strong&gt;2、&lt;/strong&gt;高敏感数据的脱敏使用（应用层面）。      &lt;strong&gt;3、&lt;/strong&gt;敏感数据的外发检测，如员工通过各类 IM、邮箱、U 盘等外发文档的时候，提取内部所含的敏感数据，判断外发行为是否有异常（文档层面）。      &lt;br /&gt;当我们判断想要实现的安全管控效果能否与分类分级结果相配合时，只需要看作用的对象是不是数据库即可，还是因为如题目揭示的那样现如今的分类分级结果是针对数据库的。因此针对数据库相关的权限审批，脱敏，有效期控制等策略，技术上是非常直观地就能实现，只需将现有的数据管理平台同分类分级查询服务进行集成即可。      &lt;br /&gt;反观其它针对应用层面和文档层面的安全控制，几乎难以有效利用数据库分类分级的成果。&lt;/p&gt;    &lt;h2&gt;      &lt;strong&gt;04/7    应用层面的数据管控，无法与数据库分类分级结果联动&lt;/strong&gt;&lt;/h2&gt;    &lt;p&gt;这是一个令人沮丧的结论，却又似乎有些反直觉，因为在一般的理解上应用的数据也都是在对应的数据库里，如下面这张图如此般清晰的逻辑和数据链路，难道应用自己不知道某个具体的数据（如图中的电话号码 1321333333）来自于哪个数据库的哪张表中的哪个字段，进而去数据分类分级的清单结果里反查出其具体的数据类型和安全等级吗？&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" height="276" src="https://image.3001.net/images/20230922/1695359967_650d23dfbb9db3cb48d34.png!small" width="690"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;答案是真的做不到，沮丧就沮丧在这里。我们稍做一下解释，应用后端服务一定知道这个电话号码来自于数据库的哪个位置，因为查询数据的 SQL 语句就是应用后端服务自己组装出来的。但是一旦数据通过网络接口传递给了下一层的网关，数据的上下文信息也就丢失了，网关能看到的就是赤裸裸的数据本身。同样当数据被传递到浏览器，浏览器和应用自身的前端页面也只是简单的负责数据的渲染和展示即可，对后端数据库完全没有任何感知。由此就可看出，数据链路只能保持一跳，即数据库到应用后端服务这一跳而已，再往后的环节就完全丧失了数据库的元信息，从而也就无法利用基于数据库分类分级的结果了。&lt;/p&gt;    &lt;h2&gt;      &lt;strong&gt;05/7    应用层面的数据管控，只能依靠应用层面的数据分类分级&lt;/strong&gt;&lt;/h2&gt;    &lt;p&gt;当我们想要动态的依据应用内的敏感数据类型和等级，进行个性化的数字水印、数据脱敏、数据下载和导出管控、以及数据审批的时候，我们必须以某种特定的方式实现应用层面的数据识别和分类分级的能力，因为我们别无选择，我们无法利用数据库层面的分类分级结果。但我们是否也需要仿照建立数据库的资产清单那样，去建立一个针对应用的分类分级结果集合吗？针对一个常规的应用，并不需要，也不必要，因为相对于数据库有比较稳定的结构（数据量在不断增长，但数据结构变化并不一定很大），应用具有极强的动态性，应用的页面、接口都可能不断变化，那么建立一个相对不变的应用级别的数据清单就如同要去给沙滩上的沙粒画一张位置图谱。应用，需要具备动态的数据识别和分类分级的能力。拆解其技术模型，位于最核心地位的当属应用数据的解析和敏感数据的识别。&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" height="212" src="https://image.3001.net/images/20230922/1695359988_650d23f4d9cfa2a2ccbed.png!small" width="213"&gt;&lt;/img&gt;针对应用，需要具备动态的分类分级能力；针对数据库，需要具备预先分类分级的资产清单。两者的本质差异还在于，应用得先获得数据才能处理数据。而针对数据库的操作（如申请数据表权限），总不能先把数据全给你，再基于数据判断回收不能给的数据，而是要先明确给什么数据再把数据给过去。&lt;/p&gt;    &lt;h2&gt;      &lt;strong&gt;06/7    应用层面的数据分类分级可行方案选择&lt;/strong&gt;&lt;/h2&gt;    &lt;p&gt;依照数据的流转路径，敏感数据识别的节点在逻辑上可以有如下多种选择，当然有些方案在逻辑上成立，但是却不一定具有很好现实可操作性和落地性。&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" height="307" src="https://image.3001.net/images/20230922/1695360023_650d24171ec0eef8da029.png!small" width="690"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;1、应用后端服务&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;针对自研应用，在后端服务实现数据的识别，主要在于研发成本，不能一蹴而就，随着业务系统的变化要不断添加数据识别代码。后端识别逻辑难以抽象公共模块组件，进行统一的数据识别研发成本大。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;2&lt;/strong&gt;      &lt;strong&gt;、网关层面数据识别&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;在应用前端（客户端或者浏览器）与后端服务之间，串联一个网关，在网关内过滤网络流量，进行流量内的数据识别。网关面临着应用性能和稳定性的担忧，常常成为该方案被采用的最大阻碍。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;3、浏览器层面数据识别&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;无论是采用专用浏览器，还是特定浏览器插件的模式，其实现逻辑都是在应用页面被渲染出来之前进行自动的数据识别。当然从其形式来看适用场景也是受限的，仅限于Web系统。浏览器研发成本高，一般企业没有能力去构建这样的解决方案，只能寻找第三方，目前宣称有这样安全能力的在国内只有数影星球一家。&lt;/p&gt;    &lt;h2&gt;      &lt;strong&gt;07/7    数据分类分级的终极局面&lt;/strong&gt;&lt;/h2&gt;    &lt;p&gt;数据分类分级本身并不是目的，真正的目标还是在于有针对性地去保护真正重要的数据，既保护企业自身的数据资产也保护公民的数据和隐身权益。当前各大企业都在如火如荼的开展数据库层面的分类分级工作，而尚未开始应用层面的数据分类分级，一来由于数据库更容易被拖库从而造成大量的数据泄露，二来也是由于相对于应用来说，数据库的分类分级工作更容易开展。&lt;/p&gt;    &lt;p&gt;但是回头再一想，真正的分类分级保护其实最终针对的还是“正常”的用户，如企业自家员工、外包人员、合作机构等展开的不同安全等级的控制，而并非针对以非法入侵手段进行数据窃取和破坏的高级黑客。由此判断，应用层面的数据分类分级工作应该更为重要才是。&lt;/p&gt;    &lt;p&gt;最终针对数据分类分级的落地和实现，作者判断大致会呈现出这样的架构。&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" height="349" src="https://image.3001.net/images/20230922/1695360047_650d242fca44e4dc3de82.png!small" width="690"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62855-%E6%95%B0%E6%8D%AE%E5%BA%93-%E5%88%86%E7%B1%BB-%E5%88%86%E7%BA%A7</guid>
      <pubDate>Tue, 26 Sep 2023 17:24:47 CST</pubDate>
    </item>
    <item>
      <title>MySQL单表最大2千万？我装了1亿数据还贼好用…… - MySQL</title>
      <link>https://itindex.net/detail/62823-mysql-%E5%8D%83%E4%B8%87-%E6%95%B0%E6%8D%AE</link>
      <description>故事从好多年前说起，想必大家也听说过数据库单表建议最大2kw条数据这个说法。如果超过了，性能就会下降得比较厉害。 &lt;p&gt; &lt;/p&gt; &lt;p&gt;巧了，我也听说过，但我不接受它的建议，硬是单表装了1亿条数据。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;这时候，我们组里新来的实习生看到了之后，天真无邪地问我：“单表不是建议最大两千万吗？为什么这个表都放了1个亿还不分库分表？“&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;我能说我是因为懒吗？我当初设计时哪里想到这表竟然能涨这么快……&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;我不能。说了等于承认自己是开发组里的“毒瘤”，虽然我确实是，但我不能承认。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;我如坐针毡，如芒刺背，如鲠在喉。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;“我这么做是有道理的。”&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;“虽然这个表很大，但你有没有发现它查询其实还是很快。”&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;“这个2kw是个建议值，我们要来看下这个2kw是怎么来的。”&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;一、数据库单表行数最大多大？&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;我们先看下单表行数理论最大值是多少。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;建表的SQL是这么写的：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;CREATE TABLE `user` (&lt;/code&gt;  &lt;code&gt;  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT &amp;apos;主键&amp;apos;,&lt;/code&gt;  &lt;code&gt;  `name` varchar(100) NOT NULL DEFAULT &amp;apos;&amp;apos; COMMENT &amp;apos;名字&amp;apos;,&lt;/code&gt;  &lt;code&gt;  `age` int(11) NOT NULL DEFAULT &amp;apos;0&amp;apos; COMMENT &amp;apos;年龄&amp;apos;,&lt;/code&gt;  &lt;code&gt;  PRIMARY KEY (`id`),&lt;/code&gt;  &lt;code&gt;  KEY `idx_age` (`age`)&lt;/code&gt;  &lt;code&gt;) ENGINE=InnoDB AUTO_INCREMENT=100037 DEFAULT CHARSET=utf8;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;其中id就是主键。主键本身唯一，也就是说主键的大小可以限制表的上限。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;如果主键声明为int大小，也就是32位，那么能支持2^32-1，也就是21个亿左右。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;如果是bigint，那就是2^64-1，但这个数字太大，一般还没到这个限制之前，磁盘先受不了。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;如果我把主键声明为 tinyint，一个字节，8位，最大2^8-1，也就是255。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;CREATE TABLE `user` (&lt;/code&gt;  &lt;code&gt;  `id` tinyint(2) unsigned NOT NULL AUTO_INCREMENT COMMENT &amp;apos;主键&amp;apos;,&lt;/code&gt;  &lt;code&gt;  `name` varchar(100) NOT NULL DEFAULT &amp;apos;&amp;apos; COMMENT &amp;apos;名字&amp;apos;,&lt;/code&gt;  &lt;code&gt;  `age` int(11) NOT NULL DEFAULT &amp;apos;0&amp;apos; COMMENT &amp;apos;年龄&amp;apos;,&lt;/code&gt;  &lt;code&gt;  PRIMARY KEY (`id`),&lt;/code&gt;  &lt;code&gt;  KEY `idx_age` (`age`)&lt;/code&gt;  &lt;code&gt;) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;如果我想插入一个id=256的数据，那就会报错。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;mysql&amp;gt; INSERT INTO `tmp` (`id`, `name`, `age`) VALUES (256, &amp;apos;&amp;apos;, 60);&lt;/code&gt;  &lt;code&gt;ERROR 1264 (22003): Out of range value for column &amp;apos;id&amp;apos; at row 1&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;也就是说，tinyint主键限制表内最多255条数据。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;那除了主键，还有哪些因素会影响行数？&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;二、索引的结构&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;索引内部是用的B+树，这个也是八股文老股了，大家估计也背得很熟了。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;为了不让大家有过于强烈的审丑疲劳，今天我尝试从另外一个角度给大家讲讲这玩意。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; 1.页的结构 &lt;p&gt; &lt;/p&gt; &lt;p&gt;假设我们有这么一张user数据表。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://dbaplus.cn/uploadfile/2023/0731/20230731095348166.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;user表&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;其中id是唯一主键。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;这看起来的一行行数据，为了方便，我们后面就叫它们record吧。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;这张表看起来就跟个excel表格一样。excel的数据在硬盘上是一个xx.excel的文件。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;而上面user表数据，在硬盘上其实也是类似，放在了user.ibd文件下。含义是user表的innodb data文件，专业点，又叫表空间。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;虽然在数据表里，它们看起来是挨在一起的。但实际上在user.ibd里他们被分成很多小份的数据页，每份大小16k，类似于下面这样。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://dbaplus.cn/uploadfile/2023/0731/20230731095401767.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;ibd文件内部有大量的页&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;我们把视角聚焦一下，放到页上面。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;整个页16k，不大，但record这么多，一页肯定放不下，所以会分开放到很多页里。并且这16k，也不可能全用来放record对吧。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;因为record们被分成好多份，放到好多页里了，为了唯一标识具体是哪一页，那就需要引入页号（其实是一个表空间的地址偏移量）。同时为了把这些数据页给关联起来，于是引入了前后指针，用于指向前后的页。这些都被加到了页头里。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;页是需要读写的，16k说小也不小，写一半电源线被拔了也是有可能发生的，所以为了保证数据页的正确性，还引入了校验码。这个被加到了页尾。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;那剩下的空间，才是用来放我们的record的。而record如果行数特别多的话，进入到页内时挨个遍历，效率也不太行，所以为这些数据生成了一个页目录，具体实现细节不重要。只需要知道，它可以通过二分查找的方式将查找效率从O(n) 变成O(lgn)。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://dbaplus.cn/uploadfile/2023/0731/20230731095411256.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;页结构&lt;/p&gt; &lt;p&gt; &lt;/p&gt; 2.从页到索引 &lt;p&gt; &lt;/p&gt; &lt;p&gt;如果想查一条record，我们可以把表空间里每一页都捞出来，再把里面的record捞出来挨个判断是不是我们要找的。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;行数量小的时候，这么操作也没啥问题。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;行数量大了，性能就慢了，于是为了加速搜索，我们可以在每个数据页里选出主键id最小的record，而且只需要它们的主键id和所在页的页号。组成新的record，放入到一个新生成的一个数据页中，这个新数据页跟之前的页结构没啥区别，而且大小还是16k。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;但为了跟之前的数据页进行区分。数据页里加入了页层级（page level）的信息，从0开始往上算。于是页与页之间就有了上下层级的概念，就像下面这样。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://dbaplus.cn/uploadfile/2023/0731/20230731095423430.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;两层B+树结构&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;突然页跟页之间看起来就像是一棵倒过来的树了。也就是我们常说的B+树索引。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;最下面那一层，page level 为0，也就是所谓的叶子结点，其余都叫非叶子结点。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;上面展示的是两层的树，如果数据变多了，我们还可以再通过类似的方法，再往上构建一层。就成了三层的树。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://dbaplus.cn/uploadfile/2023/0731/20230731095434558.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;三层B+树结构&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;那现在我们就可以通过这样一棵B+树加速查询。举个例子。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;比方说我们想要查找行数据5。会先从顶层页的record们入手。record里包含了主键id和页号（页地址）。看下图黄色的箭头，向左最小id是1，向右最小id是7。那id=5的数据如果存在，那必定在左边箭头。于是顺着的record的页地址就到了6号数据页里，再判断id=5&amp;gt;4，所以肯定在右边的数据页里，于是加载105号数据页。在数据页里找到id=5的数据行，完成查询。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://dbaplus.cn/uploadfile/2023/0731/20230731095445201.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;B+树查询过程&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;另外需要注意的是，上面的页的页号并不是连续的，它们在磁盘里也不一定是挨在一起的。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;这个过程中查询了三个页，如果这三个页都在磁盘中（没有被提前加载到内存中），那么最多需要经历三次磁盘IO查询，它们才能被加载到内存中。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;三、B+树承载的记录数量&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;从上面的结构里可以看出B+树的最末级叶子结点里放了record数据。而非叶子结点里则放了用来加速查询的索引数据。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;也就是说，同样一个16k的页，非叶子节点里每一条数据都指向一个新的页，而新的页有两种可能。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;如果是末级叶子节点的话，那么里面放的就是一行行record数据。&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;如果是非叶子节点，那么就会循环继续指向新的数据页。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;假设：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;非叶子结点内指向其他内存页的指针数量为x&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;叶子节点内能容纳的record数量为y&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;B+树的层数为z&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://dbaplus.cn/uploadfile/2023/0731/20230731095459227.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;总行数的计算方法&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;那这棵B+树放的行数据总量等于 (x ^ (z-1)) * y。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; 1.x怎么算 &lt;p&gt; &lt;/p&gt; &lt;p&gt;我们回去看数据页的结构。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://dbaplus.cn/uploadfile/2023/0731/20230731095518264.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;页结构&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;非叶子节点里主要放索引查询相关的数据，放的是主键和指向页号。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;主键假设是bigint（8Byte），而页号在源码里叫FIL_PAGE_OFFSET（4Byte），那么非叶子节点里的一条数据是12Byte左右。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;整个数据页16k， 页头页尾那部分数据全加起来大概128Byte，加上页目录毛估占1k吧。那剩下的15k除以12Byte，等于1280，也就是可以指向x=1280页。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;我们常说的二叉树指的是一个结点可以发散出两个新的结点。m叉树一个节点能指向m个新的结点。这个指向新节点的操作就叫扇出（fanout）。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;而上面的B+树，它能指向1280个新的节点，恐怖如斯，可以说扇出非常高了。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; 2.y的计算 &lt;p&gt; &lt;/p&gt; &lt;p&gt;叶子节点和非叶子节点的数据结构是一样的，所以也假设剩下15kb可以发挥。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;叶子节点里放的是真正的行数据。假设一条行数据1kb，所以一页里能放y=15行。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; 3.行总数计算 &lt;p&gt; &lt;/p&gt; &lt;p&gt;回到  (x ^ (z-1)) * y   这个公式。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;已知x=1280，y=15。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;假设B+树是两层，那z=2。则是(1280 ^ (2-1)) * 15 ≈ 2w&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;假设B+树是三层，那z=3。则是(1280 ^ (3-1)) * 15 ≈ 2.5kw&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;这个2.5kw，就是我们常说的单表建议最大行数2kw的由来。毕竟再加一层，数据就大得有点离谱了。三层数据页对应最多三次磁盘IO，也比较合理。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;四、行数超一亿就慢了吗？&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;上面假设单行数据用了1kb，所以一个数据页能放个15行数据。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;如果我单行数据用不了这么多，比如只用了250byte。那么单个数据页能放60行数据。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;那同样是三层B+树，单表支持的行数就是 (1280 ^ (3-1)) * 60 ≈ 1个亿。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;你看我一个亿的数据，其实也就三层B+树，在这个B+树里要查到某行数据，最多也是三次磁盘IO。所以并不慢。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;这就很好解释了文章开头，为什么我单表1个亿，但查询性能没啥大毛病。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;五、B树承载的记录数量&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;既然都聊到这里了，我们就顺着这个话题多聊一些吧。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;我们都知道，现在mysql的索引都是B+树，而有一种树，跟B+树很像，叫B树，也叫B-树。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;它跟B+树最大的区别在于，B+树只在末级叶子结点处放数据表行数据，而B树则会在叶子和非叶子结点上都放。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;于是，B树的结构就类似这样：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://dbaplus.cn/uploadfile/2023/0731/20230731095533809.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;B树结构&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;B树将行数据都存在非叶子节点上，假设每个数据页还是16kb，掐头去尾每页剩15kb，并且一条数据表行数据还是占1kb，就算不考虑各种页指针的情况下，也只能放个15条数据。数据页扇出明显变少了。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;计算可承载的总行数的公式也变成了一个等比数列。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;15 + 15^2 +15^3 + ... + 15^z&lt;/p&gt; &lt;p&gt;其中z还是层数的意思。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;为了能放2kw左右的数据，需要z&amp;gt;=6。也就是树需要有6层，查一次要访问6个页。假设这6个页并不连续，为了查询其中一条数据，最坏情况需要进行6次磁盘IO。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;而B+树同样情况下放2kw数据左右，查一次最多是3次磁盘IO。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;磁盘IO越多则越慢，这两者在性能上差距略大。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;为此，B+树比B树更适合成为mysql的索引。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;总结&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;B+树叶子和非叶子结点的数据页都是16k，且数据结构一致，区别在于叶子节点放的是真实的行数据，而非叶子结点放的是主键和下一个页的地址。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;B+树一般有两到三层，由于其高扇出，三层就能支持2kw以上的数据，且一次查询最多1~3次磁盘IO，性能也还行。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;存储同样量级的数据，B树比B+树层级更高，因此磁盘IO也更多，所以B+树更适合成为mysql索引。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;索引结构不会影响单表最大行数，2kw也只是推荐值，超过了这个值可能会导致B+树层级更高，影响查询性能。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;单表最大值还受主键大小和磁盘大小限制。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;最后&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;虽然我在单表里塞了1亿条数据，但这个操作的前提是，我很清楚这不会太影响性能。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;这波解释，毫无破绽，无懈可击。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;到这里，连我自己都被自己说服了。想必实习生也是。&lt;/p&gt; &lt;p&gt; &lt;/p&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;  &lt;p&gt;参考资料&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;《MYSQL内核：INNODB存储引擎 卷1》&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt;作者丨小白&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62823-mysql-%E5%8D%83%E4%B8%87-%E6%95%B0%E6%8D%AE</guid>
      <pubDate>Tue, 01 Aug 2023 13:56:15 CST</pubDate>
    </item>
    <item>
      <title>建设数据中台到底有啥用？</title>
      <link>https://itindex.net/detail/62822-%E5%BB%BA%E8%AE%BE-%E6%95%B0%E6%8D%AE-%E4%B8%AD%E5%8F%B0</link>
      <description>&lt;p&gt;最近专注在数据和人工智能领域，从数据仓库、商业智能、主数据管理到大数据平台的建设，经过很多项目的沉淀和总结，最后我和团队一起总结了精益数据创新的体系。一直战斗在企业信息化一线。&lt;/p&gt;
 &lt;p&gt;企业为什么要建设数据中台，数据中台对于企业的价值到底是什么。从概念和框架的角度，给你提供一个更全面的视角。做好任何一件事情的前提就是弄清楚为什么。&lt;/p&gt;
 &lt;h2&gt;1 数据中台的诉求&lt;/h2&gt;
 &lt;p&gt;百度搜索指数&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="img" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8b2ccb7df0d94546a724d6dc5dd84ccf~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;数据中台的百度搜索指数最终超越了数字化转型和数据仓库。很多企业已经在落地，没启动的企业也在考虑中。显然，数据中台能满足企业的一些诉求。&lt;/p&gt;
 &lt;p&gt;数据中台行业调研得出的词云图。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/80a95a5690664144aa43cbccebe4b705~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;大家对数据中台最多的期待：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;距业务更近&lt;/li&gt;
  &lt;li&gt;为企业提供直接业务价值&lt;/li&gt;
  &lt;li&gt;提供数据服务而不止报表&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;1.1 传统企业的数据系统距离用户和业务较远&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;数据系统只是技术支撑，不能直接产生业务价值。做一个业务系统，如电商平台可直接带来收入。但传统的数据应用，如数据仓库不能带来直接价值&lt;/li&gt;
  &lt;li&gt;当业务人员要在报表里修改一些内容时，得到的响应慢，因为业务人员无法自己直接使用数据来产生洞察，需要去找数据团队&lt;/li&gt;
  &lt;li&gt;过去在数据方面的投资，大量花费在数据采集、处理和建模部分，而真正利用到业务领域的也不多&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;换个角度看，业务开发团队对数据利用有很大需求，体现在希望数据中台能解决企业数据开发的效率问题，协作问题和能力问题。&lt;/p&gt;
 &lt;p&gt;数据中台给应用开发人员这样的希望：他们无需关注具体取数逻辑，只需关注客户需求，像搭乐高一样组合各种数据中台的数据服务到自己的应用，数据准确且一致。&lt;/p&gt;
 &lt;p&gt;所以，数据中台的价值就是改变原来企业利用数据的形式。&lt;/p&gt;
 &lt;p&gt;过去，数据的利用形式主要是BI，说直接点就是做报表，做报表就是让管理者知道现在的业务在发生什么，为啥会发生这些事，接下来可能发生啥，这一切都是提供给我们的管理者去看的，帮管理者去做出一个业务决策。&lt;/p&gt;
 &lt;p&gt;随业务复杂度提升，一个决策背后的因素很多，一个现象需要多维解读才能体现业务全貌。于是，管理者需要的报表越来越多，很多企业会有多个不同业务线的数据仓库，每个数据仓库里都有千张以上的报表，最后就陷入了报表的迷宫。&lt;/p&gt;
 &lt;p&gt;回头来看这过程，发现报表并不是我们需要的，而数据本身也不是我们需要的，我们需要的是一个业务决策，一个业务行为。如用户打开电商产品目录时，将他最可能购买的产品展示在第一页，而原来OLTP、OLAP分离的数据处理流程做不到，在业务交易过程中，也无法从历史数据和全域数据的分析结果中获得行动的指引。&lt;/p&gt;
 &lt;p&gt;市场对数据中台的期待，是提供直接驱动业务流程的数据服务，而不仅是需经过人去转化和解读的数据可视化报表，原来商业智能时代已去，市场和用户期待数据智能时代。&lt;/p&gt;
 &lt;h2&gt;2 建设数据中台的根本目的&lt;/h2&gt;
 &lt;p&gt;建设数据中台似乎能提供这种诉求的解决方案。但建设中台不容易，需在技术、组织架构都做对应调整，落地过程也面临种种挑战。企业为啥还兴师动众落地数据中台？数据中台的愿景是打造数据驱动的智能企业。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/015452309b9642bf85c92fe8294a1c05~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;企业建设数据中台，成为数据驱动的智能企业&lt;/p&gt;
 &lt;h2&gt;3 对企业的收益&lt;/h2&gt;
 &lt;ul&gt;
  &lt;li&gt;优化现有业务&lt;/li&gt;
  &lt;li&gt;实现新业务的转型&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2cdcd0c618924c339f2027ce267cbc1a~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h3&gt;3.1 优化现有业务&lt;/h3&gt;
 &lt;p&gt;通过数据分析和人工智能技术的应用，优化原业务流程。&lt;/p&gt;
 &lt;h4&gt;1 增加现有业务的收入&lt;/h4&gt;
 &lt;p&gt;如通过分析产品的价格、销量、用户数据来优化产品定价、优化产品组合、进行精准营销，从而能够促进产品的销售，增加现有产品的收入。&lt;/p&gt;
 &lt;h5&gt;案例&lt;/h5&gt;
 &lt;p&gt;给一个能源类企业做的数据中台。建成后能够根据历史销量、市场份额、市场容量等数据进行建模，从而帮助企业的销售部门去优化销售任务的分配，提升销售额。这小项目能给企业啥价值？&lt;/p&gt;
 &lt;p&gt;过去，企业每年年初给全国几十个销售定业绩并持续跟踪，很痛苦，目标不好锚定，每个销售管理一堆经销商，经销商销量、退货都不拉通，无法客观地量化和追踪销售的业绩。&lt;/p&gt;
 &lt;p&gt;过去这一切靠的都是销售总监经验去拍数，更多靠谈判力，不确定性很高。有了数据中台后，把行业数据、市场竞争数据、往年销售数据以及经销商的数据都拉通来看，一下给到销售总监全貌，还可模拟，让销售业绩分配这个工作变成一个可量化、可预测的确定性工作。&lt;/p&gt;
 &lt;h4&gt;2 促进生产效率&lt;/h4&gt;
 &lt;p&gt;通过数据中台建设，能促进生产效率的提升。&lt;/p&gt;
 &lt;p&gt;如某大型电信服务商，通过对勘测、规划、设计工作的建模，实现数据自动化处理，减少人工干预和问题的出现，大幅提升工程师设计效率和准确性，将工程设计周期缩短一半。&lt;/p&gt;
 &lt;p&gt;分析原因。电信服务商的投标是一个很复杂的工作，从客户发出需求到根据需求去勘测、做出规划、具体实施设计再到把实施设计转化成物料设计、工程设计、财务设计，最后再形成投标方案，这个过程过去至少需要一个月，需要众多不同业务部门和专业技能的协作，其中大部分工作都花在了不同数据的合并、拉通、对齐和映射上。&lt;/p&gt;
 &lt;p&gt;企业建设数据中台后，所有数据能自动处理，大家在同一数据服务里获取、修改、加工同样一套数据，且每次做方案的过程都沉淀成新的服务，后面项目可复用，大大缩短工期，有些标准化较高的项目类型，可从原来一月缩到三天。&lt;/p&gt;
 &lt;h4&gt;降低运营成本，提升运营的利润&lt;/h4&gt;
 &lt;p&gt;目前利用场景最多的，主要通过数据分析优化业务流程、缩短运营周期，从而提升运营利润。&lt;/p&gt;
 &lt;p&gt;如给一家大型钢铁厂进行配方规划优化，通过对配方数据、市场价格、销量数据的综合分析建模，给到成本最优、产值最高的生产组合，降低运营成本，提升利润。&lt;/p&gt;
 &lt;p&gt;钢铁行业里配矿决策是很复杂但很重要环节，不同配矿方案，成本和工艺都不一样，对利润影响很大。如何根据技术和商业的众多因素选择最优配方？过去都根据经验维护和计算配矿规则，效率低、周期长。&lt;/p&gt;
 &lt;p&gt;有数据中台，将原材料的性能、化学工艺、产品质量等技术因素和价格、成分、运营成本及销售收入等商业因素的数据统一进行建模，统一计算后最终做出综合规划，这大大提升利润、降低运营成本。&lt;/p&gt;
 &lt;p&gt;如下图所示，这是一个典型的钢粉配方的和制造成本的表格，这里面每一项的变化都会带来成本的变化，而影响利润的除了制造成本外，还有销售价格，运营成本等，这样一来如何设计出最优化的配矿决策就是非常重要的因素。通过数据建模，ML的智能配矿模型能全方位规划最优方案，达到特定商业目标，如缩短生产周期或提升利润，优化库存。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/172a13be84794660aeb4279b2dcb019b~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h4&gt;提升用户体验&lt;/h4&gt;
 &lt;p&gt;提升用户体验的核心是企业要理解自己的用户，知道用户对自己产品、服务的认知，然后对应优化自己的产品和服务，这就需要建设用户数据平台，构建统一的用户视图，建立起用户画像。&lt;/p&gt;
 &lt;p&gt;这里我举个富国银行的例子，他们在数据转型中，利用数据中台分析用户的行为数据，来重构在线银行的网站，提升用户体验。富国银行在2016年的时候面临很大的业绩挑战，为了更好地了解用户，他们建立了企业级的数据中台，把全行的用户信息都打通，做成用户画像，打上各种标签，并根据这些用户画像和标签，重新设计了电子银行网站，让网站的服务和风格以用户为中心。&lt;/p&gt;
 &lt;p&gt;为期几年的数据转型之旅，富国银行也因此项目成为行业“零售之王”，更多细节  &lt;a href="https://mp.weixin.qq.com/s/dg30hCV9mZ95NyNVVs3TmQ"&gt;《富国银行的数据转型之旅》&lt;/a&gt;。&lt;/p&gt;
 &lt;h4&gt;提升资产利用率&lt;/h4&gt;
 &lt;p&gt;分析、优化高价值资产，提升资产的利用率。&lt;/p&gt;
 &lt;h5&gt;物流领域路径优化&lt;/h5&gt;
 &lt;p&gt;物流企业做路径优化项目，提升人员和车辆使用率。过去，每天早上每区都有个经验丰富员工，统一规划前一天收到的派件和收件订单，把这些订单分给对应的小组。&lt;/p&gt;
 &lt;p&gt;这过程的目的就是最大化利用车辆、快递员两个核心资产。但这规划很复杂，因为不仅要考虑成本，还要考虑每个件积压时间不一、紧急程度不一、不同的地点路况对于车辆的要求也不一样等等，这些数据的采集、拉通、建模是很重要的基础工作而这一切都依赖与数据的打通。&lt;/p&gt;
 &lt;p&gt;建设数据中台，拉通数据后，派单收单的路径更优化了，更好分配给快递员，提升车辆使用率20%。&lt;/p&gt;
 &lt;p&gt;这场景就很典型，体现数据中台所支撑的智能规划业务的价值。&lt;/p&gt;
 &lt;h3&gt;3.2 业务创新和转型&lt;/h3&gt;
 &lt;p&gt;建设数据中台的第二个收益，实现业务创新和转型。四个主要的价值。&lt;/p&gt;
 &lt;h4&gt;① 数字化产品创新&lt;/h4&gt;
 &lt;p&gt;一个合作十多年海外房地产交易网站客户，定期和他们做黑客马拉松。&lt;/p&gt;
 &lt;p&gt;有次我们黑客马拉松的一个小组，通过数据分析发现一个小模式，有一群用户，在一段时间内高频访问网站，但不产生任何看房、卖房行为。最后数据分析发现这样的用户都有共同特点，大部分女性，基本访问链接停留时间最长的，很多都是图片，且是室内图片。&lt;/p&gt;
 &lt;p&gt;推测这群人是来看装修，于是小组孵化新产品，专门提供装修服务，这产品最后还成功了，成为公司除房地产中介服务之外的新业务线。&lt;/p&gt;
 &lt;p&gt;这也是典型的通过数据洞察发现业务新价值，从而实现数字化产品创新的场景。&lt;/p&gt;
 &lt;h4&gt;② 数字化资产销售&lt;/h4&gt;
 &lt;p&gt;将已积累的数据，通过组合、包装、分析、脱敏，形成对一部分用户有价值的数据资产，如行业报告或优质内容，直接销售产生收入。&lt;/p&gt;
 &lt;p&gt;典型场景搜索引擎，搜索引擎将用户的信息进行统计分析、脱敏处理后，变成一系列的知识和分析报告，然后以会员提供给需要用户。&lt;/p&gt;
 &lt;p&gt;百度指数里面，用户可定义和购买自己感兴趣的关键词，一年198元，然后百度就会把所有搜索过这个关键词的记录统计，变成这关键词的搜索指数。如数据中台的关键词就是我去年购买的，我就能实时追踪这个关键词在中文市场被搜索的热度。这就是数据化资产销售的价值模式。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="img" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9f286f0d17924d42b2ef3aab2ff6b327~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h4&gt;③ 业务平台化收益&lt;/h4&gt;
 &lt;p&gt;有一句话在去年很流行，“未来的企业，要么自己做平台，要么被别人平台化”。平台经济成为了这几年数字化领域炙手可热的概念。总的来说，平台化就是你搭建一个平台，让需求方和供给方上来交易，最后你来收取服务费。&lt;/p&gt;
 &lt;p&gt;如何建立平台呢？拉通一个领域数据，形成数字化平台，再通过平台运营一个特定的业务和客户群体，从而通过平台来产生收益。&lt;/p&gt;
 &lt;p&gt;典型场景 - 交易撮合平台，如比特币交易平台。这和数据中台啥关系？&lt;/p&gt;
 &lt;p&gt;这过程其实也是领域数据中台的建设过程，因为平台方主要做的就是数据的生意，对接信息、对接交易双方。数据中台在企业内部，就相当一个数据采集、加工、交易的平台，业务方既可能是数据服务的消费者，又可能是生产者，最终产品是数据服务。&lt;/p&gt;
 &lt;h4&gt;④ 数字化生态业务&lt;/h4&gt;
 &lt;p&gt;从更高维度来看，就是在平台化基础之上，通过打穿产业供应链，帮助企业建设自己数字化生态，从而在生态中产生新的业务价值和收入。如Google应用商店。&lt;/p&gt;
 &lt;p&gt;当有足够多的伙伴在这平台进行交易，它就能在这些海量的交易和行为数据发现特别多规律，然后产生更多产品创新，利用数据来牵引这生态朝自己设计方向发展。&lt;/p&gt;
 &lt;p&gt;这生态里，有很多角色参与，开发者、自由开发者、广告商、应用购买者等，而Google掌握所有方数据，用户浏览、下载、付费、交易，一切数据都能够被分析利用，帮助Google Play运营方发现新业务价值，创造收入。&lt;/p&gt;
 &lt;h2&gt;4 总结&lt;/h2&gt;
 &lt;p&gt;建设数据中台到底啥用，一个数据中台收益框架包括两大维度、九个细分项。最核心的就是给我们建设数据中台这件事找到目标，可把这9项作为指导，先明确价值和方向，再找到应用场景，以此作为牵引来建设自己的数据中台。&lt;/p&gt;
 &lt;p&gt;大部分企业要经历一个转型的，朝着数智化方向演进。企业的转型，从最早的信息化走向数字化，下一个目标是数智化。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2570858c4e1e46269cedd588d38bb374~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;信息化解决的是企业内部的管理问题，让企业能够以一个有组织、有流程的方式高效地运转起来。&lt;/p&gt;
 &lt;p&gt;数字化解决的是企业与外部的连接问题，让企业能够直接触达客户，并且建立线上的业务。 数智化解决的是让企业成为智能企业，业务更智慧的问题，这个过程的核心生产要素就是数据。&lt;/p&gt;
 &lt;p&gt;数智化转型能给企业带来颠覆性变革，但如何发现数据价值，构建数据智能的能力，规模化赋能业务？企业需要一个抓手，利用它对齐业务和技术，不断前进。数据中台就像这抓手，谁能围绕以上的业务优化和转型两个方面的价值来建设数据中台，谁就能在数智化转型中获得领先优势。&lt;/p&gt;
 &lt;p&gt;数据中台这股浪潮给我们提供机会，但这机会也提出很多、很高能力要求。&lt;/p&gt;
 &lt;h2&gt;5 FAQ&lt;/h2&gt;
 &lt;p&gt;成为数智化企业，都需要哪些能力呢？我做了众多个国内外领先企业的转型研究，发现了一些规律和有意思的事情。&lt;/p&gt;
 &lt;p&gt;数据中台概念出来时，有很多说法，从不同层面去分析，会发现所有问题的根源都来自“定位”这两个字。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;对程序员，数据中台可能是解决数据规范和数据钻取问题的一个良方&lt;/li&gt;
  &lt;li&gt;对产品经理，数据中台可能是解决业务与数据融合的关键&lt;/li&gt;
  &lt;li&gt;对中层管理者，数据中台是打通部门之间数据共享的重要依据&lt;/li&gt;
  &lt;li&gt;对企业家来说，紧跟行业趋势，顺势而为，是讲一个好故事必不可少的部分&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;但有一点大势所趋，信息化-&amp;gt;数字化-&amp;gt;智能化，即数智化。&lt;/p&gt;
 &lt;p&gt;就像5G来临势必带动一些新独角兽。互联网中变化莫测的打法更像是古代军事战争。谁能敏锐察觉敌情，就能敏捷做出最快的反应。又像《三体》黑暗森林中所描述的那样。黑暗森林中的猎人，谁最先发现猎物，开枪。带来的是一系列的连锁效应。&lt;/p&gt;
 &lt;p&gt;我们公司是做数据采集（从各信息系统的关系数据库、大数据组件等多样存储介质抽取、转换、共享数据）服务；属于功能性产品，不了解业务，那我们能参与数据中台那部分工作？因为公司内部在讨论的时候，提到的更多观点也是，连数据模型定义都不清楚，怎么介入。&lt;/p&gt;
 &lt;p&gt;你所在公司主要做的数据集成工作，位于整个数据研发链路中，研发阶段的第一环节。&lt;/p&gt;
 &lt;p&gt;整个数据研发链路划分：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6414b3594b6e41b7bd38e461079a1792~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;明白你从事的工作在数据中台数据研发链路中的位置后，来看你们如何参与数据中台中。&lt;/p&gt;
 &lt;p&gt;数据集成产品，参与到数据中台的链路:&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;在数据导入时，建立数据源到数据中台表的数据链路关系，这样可将数据中台中表的血缘关系扩展到业务系统的数据源，当数据源发生变更时，我们可以第一时间获取到变更信息&lt;/li&gt;
  &lt;li&gt;数据传输要与元数据中心打通，从元数据中心获取各种数据源信息&lt;/li&gt;
  &lt;li&gt;数据集成，要注意既要支持批量数据的集成，也要支持实时数据的集成&lt;/li&gt;
  &lt;li&gt;数据传输，要能够与数据开发任务，建立任务依赖关系，后续的数据清洗任务依赖于数据集成任务&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;至于数据模型定义不清楚，数据传输须接入元数据中心，在元数据中心中，对每张表，都有数据字典的定义，数据传输可以基于字段的格式，进行自适配。&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62822-%E5%BB%BA%E8%AE%BE-%E6%95%B0%E6%8D%AE-%E4%B8%AD%E5%8F%B0</guid>
      <pubDate>Sat, 29 Jul 2023 17:45:25 CST</pubDate>
    </item>
    <item>
      <title>交换机原理与应用（附数据链路层封装）</title>
      <link>https://itindex.net/detail/62797-%E4%BA%A4%E6%8D%A2%E6%9C%BA-%E5%8E%9F%E7%90%86-%E5%BA%94%E7%94%A8</link>
      <description>&lt;h2&gt;交换机原理&lt;/h2&gt;
 &lt;p&gt;  &lt;strong&gt;交换机的作用&lt;/strong&gt;:  &lt;br /&gt;
连接多个以太网物理段，隔离冲突域  &lt;br /&gt;
对以太网帧进行高速而透明的交换转发  &lt;br /&gt;
自行学习和维护MAC地址信息  &lt;br /&gt;
交换机工作在二层，可以用来隔离冲突域，在OSI参考模型中，二层的作用是寻址，这边寻址指的是MAC地址，而交换机就是对MAC地址进行转发，在每个交换机中，都有一张MAC地址表，这个表是交换机自动学习的。  &lt;br /&gt;
所以，总得来说交换机的作用是寻址和转发  ，但是要注意交换机用的是MAC地址  &lt;br /&gt;
  &lt;strong&gt;交换机的特点&lt;/strong&gt;:  &lt;br /&gt;
主要工作在OSI模型的物理层、数据链路层，提供以太网间的透明桥接和交换，依据链路层的MAC地址，将以太网数据帧在端口间进行转发  &lt;br /&gt;
  &lt;strong&gt;交换机的四个功能&lt;/strong&gt;：  &lt;br /&gt;
0.  学习功能---------数据帧经过交换机，交换机会自动学习数据帧的源mac地址
0.  转发功能---------数据帧经过交换机，会在mac表中查找数据帧的目的mac，查找成功，会从相应的接口转发数据
0.  查询功能（泛洪）---------数据帧经过交换机，会在mac表中查找数据帧的目的mac，查找失败，会从所有接口转发相同数据（泛洪）
0.  刷新功能---------交换机默认300s刷新一次mac地址表&lt;/p&gt;
 &lt;h3&gt;交换机运行原理&lt;/h3&gt;
 &lt;p&gt;第一次通信的时候，交换机处于 初始状态，mac 地址表的表项为空当主机 A 想和 主机B 进行通信的时候主机A 会发送 一个数据，设 数据帧的内容:  &lt;br /&gt;
源mac: 11-11-11  &lt;br /&gt;
目的mac: 22-22-22  &lt;br /&gt;
当这个数据帧经过交换机时，交换机会拆开 数据，分析源目mac地址交换机会自动 将源mac 地址和 交换机接口号 写入到表项中然后 去表项中查找 从接口 去往 目的mac ，发现表项中没有直接广播(除了发送接口)， 只有目的mac地址的 设备会回包，其余接口的 设备会丢弃回复方 主机B 也会发送一个数据帧，数据帧的内容  &lt;br /&gt;
源mac: 22-22-22  &lt;br /&gt;
目的mac: 11-11-11  &lt;br /&gt;
该数据帧经过交换机，交换机会将源mac地址和接口号写入 mac 地址表，自动学习。
然后会去 交换机的 mac地址表查找 去往目的mac地址的接口，发现表项 中有 并且是1号接口,接从 1号接口出去。  &lt;br /&gt;
由于 交换机mac地址表中有了A B主机的相关信息，所以下次AB 通信直接单播&lt;/p&gt;
 &lt;h2&gt;交换机应用&lt;/h2&gt;
 &lt;h5&gt;例一：不同域名计算机通过网关进行链接&lt;/h5&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/278ce631e62e4452b7f562e332ae0ffd~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;  &lt;br /&gt;
打开该软件ensp&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9f8977cb8e184a2a81f5f76c7ee7df61~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;  &lt;br /&gt;
选择新建拓扑，选择路由器，第三个&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9f14c77d6aeb486c9e712776389225f5~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;  &lt;br /&gt;
选择终端选择pc&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0326d33eb5d84e8c9b7f7250c9c97341~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;  &lt;br /&gt;
启动设备&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ed8af84065e84736978c667b84179fdf~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;  &lt;br /&gt;
配置PC地址和网关（注网关必须真实存在，所以后续需要路由器配置网关）&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b9a89014e91045afbb5362665f180514~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/be225bcd0ceb42178154e4c8e49548fe~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;  &lt;br /&gt;
接下来链接两台主机和路由器&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ea6c10cd79c44050bf67963b88269684~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4bba58490d0e4884b50491b618973cb1~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2a335a177fc64b4fb58baf17d718f62a~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;  &lt;br /&gt;
开始配置路由器网关&lt;/p&gt;
 &lt;h5&gt;命令：&lt;/h5&gt;
 &lt;p&gt;  &lt;strong&gt;sys &amp;lt;&amp;gt;-[]&lt;/strong&gt;
  &lt;strong&gt;sysname 改名&lt;/strong&gt;  &lt;br /&gt;
  &lt;strong&gt;u t m 关闭接口信息报告&lt;/strong&gt;  &lt;br /&gt;
  &lt;strong&gt;int gX/X/X 进入接口管理&lt;/strong&gt;  &lt;br /&gt;
  &lt;strong&gt;ip add 网关 掩码&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6ebc148a6e8a457390e806607c261cc6~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;  &lt;br /&gt;
进入配置后更改视图模式，然后更改名字（方便知道是哪台设备），int进入接口管理端，添加网关。接下来就进入了相同的网关建立链接。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0818827e6d6249dcbafd83efc7816d5c~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h5&gt;例二 交换机工作过程&lt;/h5&gt;
 &lt;p&gt;添加交换机&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ae7079e075a9486991ec3e676a1b7101~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;  &lt;br /&gt;
添加终端&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2a00b0ac50484d259c078016a3ad9bfa~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;  &lt;br /&gt;
链接交换机&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1a678837700a49f0a3e93ea404ceb878~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;  &lt;br /&gt;
配置计算机地址，因为同一ip下不用配置网关，为直观显示，更改MAC地址。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8efe3c22737b4b1a85b49ce0feeeb3d5~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/33548977253e45dfb6393a3641eb5428~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;
  &lt;img alt="image.png" src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e3b9b068d16a403c9d05981f6f06bfe8~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;  &lt;br /&gt;
  &lt;strong&gt;命令：&lt;/strong&gt;  &lt;br /&gt;
  &lt;strong&gt;display mac-address mac地址表项&lt;/strong&gt;  &lt;br /&gt;
ping通后&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e496c83819f34f8f89f16f5270a1094f~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;  &lt;br /&gt;
在交换机可查看mac地址表项&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2a45517df3bd4018be53d5eb73314618~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;  &lt;br /&gt;
  &lt;strong&gt;该表格会默认保存300秒，如无继续使用会自动清除&lt;/strong&gt;&lt;/p&gt;
 &lt;h2&gt;数据链路层&lt;/h2&gt;
 &lt;p&gt;  &lt;img alt="image.png" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1de8b518388746bc9dda2b6445ffac4d~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;前导码(Preamble) 包含八字节。前七字节的值为0xAA，最后一个字节的值为0xAB。在DIX以太网中，前导码被认为是物理层封装的一部分，而不是数据链路层的封装。&lt;/li&gt;
  &lt;li&gt;目的地址(DA) 包含六字节。DA标识了顿的目的站点的MAC地址。DA可以是单播地址 (单个目的组播地址 (组目的地)或广播地址。&lt;/li&gt;
  &lt;li&gt;源地址(SA) 包含六字节。SA标识了发送的站点的MAC地址。SA一定是单播地址(即第8位是0)。&lt;/li&gt;
  &lt;li&gt;类型域包含两字节，用来标识上层协议的类型，如0800H标识IP协议。&lt;/li&gt;
  &lt;li&gt;数据域包含46~1500字节。数据域封装了通过以太网传输的高层协议信息。高层协议要确保这个域至少包含46字节，如果实际数据不足46字节，则高层协议必须执行某些填充算法。数据域长度的上限是任意的，但目前已经被设置为1500字节，所以暂定46至1500字节。&lt;/li&gt;
  &lt;li&gt;顺校验序列(FCS)包合四字节。FCS是从DA开始到数据域结束这部分的校验和。&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62797-%E4%BA%A4%E6%8D%A2%E6%9C%BA-%E5%8E%9F%E7%90%86-%E5%BA%94%E7%94%A8</guid>
      <pubDate>Wed, 05 Jul 2023 17:38:05 CST</pubDate>
    </item>
    <item>
      <title>什么？！Elasticsearch也可以用作向量数据库？</title>
      <link>https://itindex.net/detail/62791-elasticsearch-%E5%90%91%E9%87%8F-%E6%95%B0%E6%8D%AE%E5%BA%93</link>
      <description>&lt;p&gt;本文将探讨如何在 Elasticsearch 中优化向量搜索，并提供了一个详细的教程。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;一、Elasticsearch 神经搜索流程&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;Elasticsearch 从 2022 年 2 月发布的 8.0 版本开始，提供了基于向量的搜索和自然语言处理（NLP）功能。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;下图清楚地展示了向量搜索引擎的工作原理。它涉及以下几个步骤：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;将原始实体（如歌曲、图像或文本）转换为数字表示（向量 Embedding）；&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;使用距离度量来表示向量之间的相似性；&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;使用近似最近邻算法（ANN）搜索与查询相关的数据。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://dbaplus.cn/uploadfile/2023/0616/20230616100145551.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;向量搜索图&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;与 Apache Solr 类似，Elasticsearch 在内部也使用 Apache Lucene 作为其搜索引擎，因此许多底层概念、数据结构和算法同样适用于两者。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;在这种情况下，基于向量的搜索是构建在 Apache Lucene HNSW（Hierarchical Navigable Small World graph）上的，也就是 Lucene 9 中的原生 ANN（近似最近邻）。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;实施基于 Elasticsearch 的神经搜索的端到端流程如下：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;下载 Elasticsearch&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;外部生成向量&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;为向量搜索创建 Elasticsearch 索引&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;索引文档&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;利用向量字段进行搜索&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;现在，我们将详细描述每一步，以便你可以轻松掌握本教程。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;让我们开始吧！&lt;/p&gt; &lt;p&gt; &lt;/p&gt; 1、下载 Elasticsearch &lt;p&gt; &lt;/p&gt; &lt;p&gt;如前所述，基于向量的搜索已经集成到 Elasticsearch 8.0 中，在本教程中，我们使用的 Elasticsearch 版本为 8.5.3。你可以从下面链接下载：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;https://www.elastic.co/downloads/past-releases#elasticsearch&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;请验证已下载文件的完整性，包括 SHA 和 ASC 密钥。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;由于 Elasticsearch 是使用 Java 构建的，所以你需要确保系统中安装了 Java 开发工具包（JDK）。如果已经安装了 Java，请检查其版本是否为 17 或更高版本。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;将下载的文件解压到你要使用的位置，然后从该文件夹打开终端，并在本地运行 Elasticsearch：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;bin/elasticsearch&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;当你首次启动 Elasticsearch 时，安全性会自动启用。&lt;/p&gt; &lt;p&gt;更多信息请看：https://www.elastic.co/guide/en/elasticsearch/reference/current/configuring-stack-security.html&lt;/p&gt; &lt;p&gt;为了简化起见，在本教程中，我们通过在 elasticsearch.yml 文件（位于 /elasticsearch-8.5.3/config/ 目录下）中设置 xpack.security.enabled: false 来禁用安全性，并重新启动 Elasticsearch 节点。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;你可以通过输入以下命令来验证 Elasticsearch 是否正确运行：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;curl localhost:9200&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;现在，我们已经准备好使用 Elasticsearch 并与其 REST API 进行交互。可以通过以下几种工具来实现：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;命令行（cURL），如本教程所示&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;Kibana 的开发工具控制台（也需要下载和部署 Kibana） &lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;API 平台，如 Postman&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt; 2、外部生成向量 &lt;p&gt; &lt;/p&gt; &lt;p&gt;Elastic 8.0 允许用户在 Elasticsearch 中使用自定义或第三方的基于 PyTorch 开发的语言模型进行推断，但需要 Platinum 或 Enterprise 订阅才能体验到完整的机器学习功能。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22270;&amp;#29255;" src="https://dbaplus.cn/uploadfile/2023/0616/20230616100156152.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;Elastic Stack 订阅：https://www.elastic.co/subscriptions&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;如果你对探索这一强大的自然语言处理功能感兴趣，可以查看这篇文章 [1] 的第二部分，以简单明了的方式解释了企业版的所有步骤。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;如果你只有基本许可证，要运行 kNN 搜索，你需要在 Elasticsearch 之外将数据转换为有意义的向量值，并将其作为 dense_vector 字段值添加到文档中。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;为了将文本转换为相应的向量，我们使用了一个 Python 项目，你可以从我们的 GitHub 页面 [2] 轻松克隆和研究。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;以下是自动从语料库创建向量 Embedding 的 Python 脚本：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;https://github.com/SeaseLtd/vector-search-elastic-tutorial/blob/main/from_text_to_vectors/batch-sentence-transformers.py&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;from sentence_transformers import SentenceTransformer&lt;/code&gt;  &lt;code&gt;import torch&lt;/code&gt;  &lt;code&gt;import sys&lt;/code&gt;  &lt;code&gt;from itertools import islice&lt;/code&gt;  &lt;code&gt;import time&lt;/code&gt;  &lt;code&gt;BATCH_SIZE = 100&lt;/code&gt;  &lt;code&gt;INFO_UPDATE_FACTOR = 1&lt;/code&gt;  &lt;code&gt;MODEL_NAME = &amp;apos;all-MiniLM-L6-v2&amp;apos;&lt;/code&gt;  &lt;code&gt;# Load or create a SentenceTransformer model.&lt;/code&gt;  &lt;code&gt;model = SentenceTransformer(MODEL_NAME)&lt;/code&gt;  &lt;code&gt;# Get device like &amp;apos;cuda&amp;apos;/&amp;apos;cpu&amp;apos; that should be used for computation.&lt;/code&gt;  &lt;code&gt;if torch.cuda.is_available():&lt;/code&gt;  &lt;code&gt;    model = model.to(torch.device(&amp;quot;cuda&amp;quot;))&lt;/code&gt;  &lt;code&gt;print(model.device)&lt;/code&gt;  &lt;code&gt;def batch_encode_to_vectors(input_filename, output_filename):&lt;/code&gt;  &lt;code&gt;    # Open the file containing text.&lt;/code&gt;  &lt;code&gt;    with open(input_filename, &amp;apos;r&amp;apos;) as documents_file:&lt;/code&gt;  &lt;code&gt;        # Open the file in which the vectors will be saved.&lt;/code&gt;  &lt;code&gt;        with open(output_filename, &amp;apos;w+&amp;apos;) as out:&lt;/code&gt;  &lt;code&gt;            processed = 0&lt;/code&gt;  &lt;code&gt;            # Processing 100 documents at a time.&lt;/code&gt;  &lt;code&gt;            for n_lines in iter(lambda: tuple(islice(documents_file, BATCH_SIZE)), ()):&lt;/code&gt;  &lt;code&gt;                processed += 1&lt;/code&gt;  &lt;code&gt;                if processed % INFO_UPDATE_FACTOR == 0:&lt;/code&gt;  &lt;code&gt;                    print(&amp;quot;Processed {} batch of documents&amp;quot;.format(processed))&lt;/code&gt;  &lt;code&gt;                # Create sentence embedding&lt;/code&gt;  &lt;code&gt;                vectors = encode(n_lines)&lt;/code&gt;  &lt;code&gt;                # Write each vector into the output file.&lt;/code&gt;  &lt;code&gt;                for v in vectors:&lt;/code&gt;  &lt;code&gt;                    out.write(&amp;apos;,&amp;apos;.join([str(i) for i in v]))&lt;/code&gt;  &lt;code&gt;                    out.write(&amp;apos;\n&amp;apos;)&lt;/code&gt;  &lt;code&gt;def encode(documents):&lt;/code&gt;  &lt;code&gt;    embeddings = model.encode(documents, show_progress_bar=True)&lt;/code&gt;  &lt;code&gt;    print(&amp;apos;Vector dimension: &amp;apos; + str(len(embeddings[0])))&lt;/code&gt;  &lt;code&gt;    return embeddings&lt;/code&gt;  &lt;code&gt;def main():&lt;/code&gt;  &lt;code&gt;    input_filename = sys.argv[1]&lt;/code&gt;  &lt;code&gt;    output_filename = sys.argv[2]&lt;/code&gt;  &lt;code&gt;    initial_time = time.time()&lt;/code&gt;  &lt;code&gt;    batch_encode_to_vectors(input_filename, output_filename)&lt;/code&gt;  &lt;code&gt;    finish_time = time.time()&lt;/code&gt;  &lt;code&gt;    print(&amp;apos;Vectors created in {:f} seconds\n&amp;apos;.format(finish_time - initial_time))&lt;/code&gt;  &lt;code&gt;if __name__ == &amp;quot;__main__&amp;quot;:&lt;/code&gt;  &lt;code&gt;    main()&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;我们使用以下命令执行该脚本：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;python batch-sentence-transformers.py &amp;quot;./example_input/documents_10k.tsv&amp;quot; &amp;quot;./example_output/vector_documents_10k.tsv&amp;quot;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;回复：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;Processed 1 batch of documents&lt;/code&gt;  &lt;code&gt;Batches: 100%|██████████| 4/4 [00:04&amp;lt;00:00,  1.08s/it]&lt;/code&gt;  &lt;code&gt;Vector dimension: 384&lt;/code&gt;  &lt;code&gt;...&lt;/code&gt;  &lt;code&gt;...&lt;/code&gt;  &lt;code&gt;Processed 100 batch of documents&lt;/code&gt;  &lt;code&gt;Batches: 100%|██████████| 4/4 [00:02&amp;lt;00:00,  1.35it/s]&lt;/code&gt;  &lt;code&gt;Vector dimension: 384&lt;/code&gt;  &lt;code&gt;Vectors created in 402.041406 seconds&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;SentenceTransformers 是一个 Python 框架，你可以使用它计算句子 / 文本的 Embedding。它提供了许多预训练模型，针对不同任务进行了调优。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;在本教程中，我们使用了 all-MiniLM-L6-v2（BERT）模型，它将句子映射到一个 384 维的稠密向量空间。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;我们从 MS MARCO（一个用于深度学习的大规模信息检索数据集集合）下载了一个包含大约 10，000 个文档的检索集合，并对其进行了索引。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;该 Python 脚本的输入是一个包含 10,000 个文档的文件（即 MS MARCO 检索集合的一小部分）：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;sys.argv[1] = “/path/to/documents_10k.tsv”&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;案例 1 文档：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;The presence of communication amid scientific minds was equally important to the success of the Manhattan Project as scientific intellect was. The only cloud hanging over the impressive achievement of the atomic researchers and engineers is what their success truly meant; hundreds of thousands of innocent lives obliterated.&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;它将输出一个包含相应向量的文件：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;sys.argv[2] = “/path/to/vector_documents_10k.tsv”&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;案例 1 文档：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;0.0367823,0.072423555,0.04770486,0.034890372,0.061810732,0.002282318,0.05258357,0.013747136,...,0.0054274425&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;为了阅读方便，我们通过在回答中插入省略号来缩短向量的长度。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;接下来，需要手动将获取的 Embedding 向量加载到 Elasticsearch 中（我们将在文档索引的部分详细介绍这个过程）。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; 3、为向量搜索创建 Elasticsearch 索引 &lt;p&gt; &lt;/p&gt; &lt;p&gt;在安装和启动 Elasticsearch 之后，我们可以开始创建一个索引，使用显式映射来精确定义数据的结构。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;以下是创建 “neural_index” 索引的 API 请求：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;curl http://localhost:9200/neural_index/ -XPUT -H &amp;apos;Content-Type: application/json&amp;apos; -d &amp;apos;{&lt;/code&gt;  &lt;code&gt;&amp;quot;mappings&amp;quot;: {&lt;/code&gt;  &lt;code&gt;    &amp;quot;properties&amp;quot;: {&lt;/code&gt;  &lt;code&gt;        &amp;quot;general_text_vector&amp;quot;: {&lt;/code&gt;  &lt;code&gt;            &amp;quot;type&amp;quot;: &amp;quot;dense_vector&amp;quot;,&lt;/code&gt;  &lt;code&gt;            &amp;quot;dims&amp;quot;: 384,&lt;/code&gt;  &lt;code&gt;            &amp;quot;index&amp;quot;: true,&lt;/code&gt;  &lt;code&gt;            &amp;quot;similarity&amp;quot;: &amp;quot;cosine&amp;quot;&lt;/code&gt;  &lt;code&gt;        },&lt;/code&gt;  &lt;code&gt;        &amp;quot;general_text&amp;quot;: {&lt;/code&gt;  &lt;code&gt;            &amp;quot;type&amp;quot;: &amp;quot;text&amp;quot;&lt;/code&gt;  &lt;code&gt;        },&lt;/code&gt;  &lt;code&gt;        &amp;quot;color&amp;quot;: {&lt;/code&gt;  &lt;code&gt;            &amp;quot;type&amp;quot;: &amp;quot;text&amp;quot;&lt;/code&gt;  &lt;code&gt;        }&lt;/code&gt;  &lt;code&gt;    }&lt;/code&gt;  &lt;code&gt;}}&amp;apos;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;为了检查索引的创建情况，以下是返回有关索引信息的 API 请求：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;curl -XGET http://localhost:9200/neural_index&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;根据我们的映射定义，文档包含三个简单的字段：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;general_text_vector：存储由前面部分中的 Python 脚本生成的 Embedding 向量。&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;文档文本：source 字段，包含要转换为向量的文本。&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;color：一个附加字段，仅用于展示筛选查询的行为（我们将在搜索部分看到）。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;最后两个字段被定义为文本类型，而第一个字段被定义为稠密向量字段。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;Elasticsearch 目前通过 dense_vector 字段类型支持存储向量（浮点值），并使用它们计算文档得分。在这种情况下，我们使用以下定义：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;dims：（整数）稠密向量的维度，需要与模型的维度相等。在此例中为 384。&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;index：（布尔值）默认为 false，但你需要将其设置为 &amp;quot;index&amp;quot;:true 以使用 kNN 搜索 API 搜索向量字段。&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;similarity：（字符串）用于返回最相似的前 K 个向量的向量相似性函数。在此例中，我们选择了余弦相似度（而不是 L2 范数或点积）。仅在 index 为 true 时需要指定。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;我们将 index_options 保留为默认值；这一部分配置了与当前算法（HNSW）密切相关的高级参数，它们会影响索引时图形的构建方式。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;目前的限制是：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;1）已索引向量（&amp;quot;index&amp;quot;:true）的基数限制为 1024，未索引向量的基数限制为 2048。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;2）dense_vector 字段不支持以下功能：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;排序或聚合&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;多值&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;在嵌套映射中索引向量&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt; 4、索引文档 &lt;p&gt; &lt;/p&gt; &lt;p&gt;一旦我们创建了向量 Embedding 和索引，就可以开始推送一些文档了。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;以下是可以使用的_bulk 请求 API 将文档推送到你的 neural_index。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;例如，使用一个文档：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;curl http://localhost:9200/neural_index/_bulk -XPOST -H &amp;apos;Content-Type: application/json&amp;apos; -d &amp;apos;&lt;/code&gt;  &lt;code&gt;{&amp;quot;index&amp;quot;: {&amp;quot;_id&amp;quot;: &amp;quot;0&amp;quot;}}&lt;/code&gt;  &lt;code&gt;{&amp;quot;general_text&amp;quot;: &amp;quot;The presence of communication amid scientific minds was equally important to the success of the Manhattan Project as scientific intellect was. The only cloud hanging over the impressive achievement of the atomic researchers and engineers is what their success truly meant; hundreds of thousands of innocent lives obliterated.&amp;quot;, &amp;quot;general_text_vector&amp;quot;: [0.0367823, 0.072423555, ..., 0.0054274425], &amp;quot;color&amp;quot;: &amp;quot;black&amp;quot;}&amp;apos;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;为了方便阅读，我们在请求中插入了省略号，以缩短向量的长度。&lt;/p&gt; &lt;p&gt;自动创建_bulk API 请求体的方法：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;https://github.com/SeaseLtd/vector-search-elastic-tutorial/blob/main/indexing_phase/create_body_for_bulk.py&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;由于向量 Embedding 非常长，我们建议使用另一种方法来索引多个文档，即使用 Elasticsearch 的官方 Python 客户端 elasticsearch。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;以下是我们用于一次性索引文档批次的自定义 Python 脚本：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;https://github.com/SeaseLtd/vector-search-elastic-tutorial/blob/main/indexing_phase/indexer_elastic.py&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;import sys&lt;/code&gt;  &lt;code&gt;import time&lt;/code&gt;  &lt;code&gt;import random&lt;/code&gt;  &lt;code&gt;from elasticsearch import Elasticsearch&lt;/code&gt;  &lt;code&gt;from elasticsearch.helpers import bulk&lt;/code&gt;  &lt;code&gt;BATCH_SIZE = 1000&lt;/code&gt;  &lt;code&gt;# Elastic configuration.&lt;/code&gt;  &lt;code&gt;ELASTIC_ADDRESS = &amp;quot;http://localhost:9200&amp;quot;&lt;/code&gt;  &lt;code&gt;INDEX_NAME = &amp;quot;neural_index&amp;quot;&lt;/code&gt;  &lt;code&gt;def index_documents(documents_filename, embedding_filename, index_name, client):&lt;/code&gt;  &lt;code&gt;    # Open the file containing text.&lt;/code&gt;  &lt;code&gt;    with open(documents_filename, &amp;quot;r&amp;quot;) as documents_file:&lt;/code&gt;  &lt;code&gt;        # Open the file containing vectors.&lt;/code&gt;  &lt;code&gt;        with open(embedding_filename, &amp;quot;r&amp;quot;) as vectors_file:&lt;/code&gt;  &lt;code&gt;            documents = []&lt;/code&gt;  &lt;code&gt;            # For each document creates a JSON document including both text and related vector.&lt;/code&gt;  &lt;code&gt;            for index, (document, vector_string) in enumerate(zip(documents_file, vectors_file)):&lt;/code&gt;  &lt;code&gt;                vector = [float(w) for w in vector_string.split(&amp;quot;,&amp;quot;)]&lt;/code&gt;  &lt;code&gt;                # Generate color value randomly (additional feature to show FILTER query behaviour).&lt;/code&gt;  &lt;code&gt;                color = random.choice([&amp;apos;red&amp;apos;, &amp;apos;green&amp;apos;, &amp;apos;white&amp;apos;, &amp;apos;black&amp;apos;])&lt;/code&gt;  &lt;code&gt;                doc = {&lt;/code&gt;  &lt;code&gt;                    &amp;quot;_id&amp;quot;: str(index),&lt;/code&gt;  &lt;code&gt;                    &amp;quot;general_text&amp;quot;: document,&lt;/code&gt;  &lt;code&gt;                    &amp;quot;general_text_vector&amp;quot;: vector,&lt;/code&gt;  &lt;code&gt;                    &amp;quot;color&amp;quot;: color,&lt;/code&gt;  &lt;code&gt;                }&lt;/code&gt;  &lt;code&gt;                # Append JSON document to a list.&lt;/code&gt;  &lt;code&gt;                documents.append(doc)&lt;/code&gt;  &lt;code&gt;                # To index batches of documents at a time.&lt;/code&gt;  &lt;code&gt;                if index % BATCH_SIZE == 0 and index != 0:&lt;/code&gt;  &lt;code&gt;                    # How you&amp;apos;d index data to Elastic.&lt;/code&gt;  &lt;code&gt;                    indexing = bulk(client, documents, index=index_name)&lt;/code&gt;  &lt;code&gt;                    documents = []&lt;/code&gt;  &lt;code&gt;                    print(&amp;quot;Success - %s , Failed - %s&amp;quot; % (indexing[0], len(indexing[1])))&lt;/code&gt;  &lt;code&gt;            # To index the rest, when &amp;apos;documents&amp;apos; list &amp;lt; BATCH_SIZE.&lt;/code&gt;  &lt;code&gt;            if documents:&lt;/code&gt;  &lt;code&gt;                bulk(client, documents, index=index_name)&lt;/code&gt;  &lt;code&gt;            print(&amp;quot;Finished&amp;quot;)&lt;/code&gt;  &lt;code&gt;def main():&lt;/code&gt;  &lt;code&gt;    document_filename = sys.argv[1]&lt;/code&gt;  &lt;code&gt;    embedding_filename = sys.argv[2]&lt;/code&gt;  &lt;code&gt;    &lt;/code&gt;  &lt;code&gt;    # Declare a client instance of the Python Elasticsearch library.&lt;/code&gt;  &lt;code&gt;    client = Elasticsearch(hosts=[ELASTIC_ADDRESS])&lt;/code&gt;  &lt;code&gt;   &lt;/code&gt;  &lt;code&gt;    initial_time = time.time()&lt;/code&gt;  &lt;code&gt;    index_documents(document_filename, embedding_filename, INDEX_NAME, client)&lt;/code&gt;  &lt;code&gt;    finish_time = time.time()&lt;/code&gt;  &lt;code&gt;    print(&amp;apos;Documents indexed in {:f} seconds\n&amp;apos;.format(finish_time - initial_time))&lt;/code&gt;  &lt;code&gt;if __name__ == &amp;quot;__main__&amp;quot;:&lt;/code&gt;  &lt;code&gt;    main()&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;我们使用以下命令执行脚本：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;python indexer_elastic.py &lt;/code&gt;  &lt;code&gt;&amp;quot;../from_text_to_vectors/example_input/documents_10k.tsv&amp;quot; &lt;/code&gt;  &lt;code&gt;&amp;quot;../from_text_to_vectors/example_output/vector_documents_10k.tsv&amp;quot;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;回复：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;Success - 1001 , Failed - 0&lt;/code&gt;  &lt;code&gt;Success - 1000 , Failed - 0&lt;/code&gt;  &lt;code&gt;...&lt;/code&gt;  &lt;code&gt;Finished&lt;/code&gt;  &lt;code&gt;Documents indexed in 19.828323 seconds&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;Python 脚本将输入 2 个文件，一个包含文本，一个包含相应的向量：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;sys.argv[1] = “/path/to/documents_10k.tsv”&lt;/p&gt; &lt;p&gt;sys.argv[2] = “/path/to/vector_documents_10k.tsv”&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;对于两个文件的每个元素，脚本将创建一个包含 id、文本、向量和 color 的单个 JSON 文档，并将其添加到一个列表中。当列表达到设置的 BATCH_SIZE 时，脚本会将 JSON 文档批量推送到 Elasticsearch。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;例如 JSON：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;{**&amp;apos;_id&amp;apos;**: &amp;apos;0&amp;apos;, **&amp;apos;general_text&amp;apos;**: &amp;apos;The presence of communication amid scientific minds was equally important to the success of the Manhattan Project as scientific intellect was. The only cloud hanging over the impressive achievement of the atomic researchers and engineers is what their success truly meant; hundreds of thousands of innocent lives obliterated.\n&amp;apos;, **&amp;apos;general_text_vector&amp;apos;**: [0.0367823, 0.072423555, 0.04770486, 0.034890372, 0.061810732, 0.002282318, 0.05258357, 0.013747136, -0.0060595, 0.020382827, 0.022016432, 0.017639274, ..., 0.0054274425], **&amp;apos;color&amp;apos;**: &amp;apos;black&amp;apos;}&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;在这一步之后，已经在 Elasticsearch 中索引了 10,000 个文档，并且我们已经准备好根据查询检索这些文档。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;要检查文档数量，你可以使用 cat indices API，该 API 可以显示集群中每个索引的高级信息：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;curl -XGET http://localhost:9200/_cat/indices&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;或者：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;curl -XGET http://localhost:9200/_cat/count/neural_index?v&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; 5、利用向量字段进行搜索 &lt;p&gt;稠密向量字段可以通过以下方式使用：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;精确的暴力 kNN：使用 script_score 查询&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;近似的 kNN：使用搜索 API 中的 knn 选项，找到与查询向量最相似的前 k 个向量&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;为了进行一些查询，我们从 MS Marco 下载了查询集：queries.tar.gz[3]&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;下面示例中的查询是：“what is a bank transit number”。为了将其转换为向量，我们运行了一个自定义的 Python 脚本：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;from sentence_transformers import SentenceTransformer&lt;/code&gt;  &lt;code&gt;# The sentence we like to encode.&lt;/code&gt;  &lt;code&gt;sentences = [&amp;quot;what is a bank transit number&amp;quot;]&lt;/code&gt;  &lt;code&gt;# Load or create a SentenceTransformer model.&lt;/code&gt;  &lt;code&gt;model = SentenceTransformer(&amp;apos;sentence-transformers/all-MiniLM-L6-v2&amp;apos;)&lt;/code&gt;  &lt;code&gt;# Compute sentence embeddings.&lt;/code&gt;  &lt;code&gt;embeddings = model.encode(sentences)&lt;/code&gt;  &lt;code&gt;# Create a list object, comma separated.&lt;/code&gt;  &lt;code&gt;vector_embeddings = list(embeddings)&lt;/code&gt;  &lt;code&gt;print(vector_embeddings)&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;让我们使用以下命令执行脚本：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;python single-sentence-transformers.py&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;输出是一个浮点数组：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;[array([-9.01364535e-03, -7.26634488e-02, -1.73818860e-02, ..., ..., -1.16323479e-01],dtype=float32)]&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;现在你可以复制并使用在 kNN 查询中获得的向量。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;以下是 Elasticsearch 中神经搜索查询的几个示例。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;精确的 kNN&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;通过运行包含向量函数的 script_score 查询，可以计算查询向量与索引中每个向量的相似度，并按照 script_score 进行排名。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;请求：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;curl http://localhost:9200/neural_index/_search -XPOST -H &amp;apos;Content-Type: application/json&amp;apos; -d &amp;apos;{&lt;/code&gt;  &lt;code&gt;&amp;quot;query&amp;quot;: {&lt;/code&gt;  &lt;code&gt;    &amp;quot;script_score&amp;quot;: {&lt;/code&gt;  &lt;code&gt;        &amp;quot;query&amp;quot; : {&lt;/code&gt;  &lt;code&gt;            &amp;quot;match_all&amp;quot;: {}&lt;/code&gt;  &lt;code&gt;        },&lt;/code&gt;  &lt;code&gt;        &amp;quot;script&amp;quot;: {&lt;/code&gt;  &lt;code&gt;            &amp;quot;source&amp;quot;: &amp;quot;cosineSimilarity(params.queryVector, &amp;apos;\&amp;apos;&amp;apos;general_text_vector&amp;apos;\&amp;apos;&amp;apos;) + 1.0&amp;quot;,&lt;/code&gt;  &lt;code&gt;            &amp;quot;params&amp;quot;: {&lt;/code&gt;  &lt;code&gt;                &amp;quot;queryVector&amp;quot;: [-9.01364535e-03, -7.26634488e-02, ..., -1.16323479e-01]&lt;/code&gt;  &lt;code&gt;            }&lt;/code&gt;  &lt;code&gt;        }&lt;/code&gt;  &lt;code&gt;    }&lt;/code&gt;  &lt;code&gt;}}&amp;apos;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;在这种情况下，我们使用了 match_all 查询来匹配所有文档，但是除非你处理的是非常小的索引，否则这个查询并不具备可扩展性，可能会显著增加搜索延迟。&lt;/p&gt; &lt;p&gt;如果你想在大型数据集上使用此查询，建议在 script_score 中指定一个过滤查询，以限制传递给向量函数的匹配文档数量。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;近似的 kNN&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;为什么是近似呢？因为 Elasticsearch 使用了一种近似方法来执行 kNN 搜索（即 HNSW），它为了提高搜索速度和减少计算复杂性（尤其是在大型数据集上），牺牲了结果的准确性；因此，搜索结果可能并不总是真正的 k 个最近邻。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;请求：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;curl http://localhost:9200/neural_index/_search -XPOST -H &amp;apos;Content-Type: application/json&amp;apos; -d &amp;apos;{&lt;/code&gt;  &lt;code&gt;&amp;quot;knn&amp;quot;: {&lt;/code&gt;  &lt;code&gt;    &amp;quot;field&amp;quot;: &amp;quot;general_text_vector&amp;quot;,&lt;/code&gt;  &lt;code&gt;    &amp;quot;query_vector&amp;quot;: [-9.01364535e-03, -7.26634488e-02, ..., -1.16323479e-01],&lt;/code&gt;  &lt;code&gt;    &amp;quot;k&amp;quot;: 3,&lt;/code&gt;  &lt;code&gt;    &amp;quot;num_candidates&amp;quot;: 10&lt;/code&gt;  &lt;code&gt;},&lt;/code&gt;  &lt;code&gt;&amp;quot;_source&amp;quot;: [&lt;/code&gt;  &lt;code&gt;    &amp;quot;general_text&amp;quot;,&lt;/code&gt;  &lt;code&gt;    &amp;quot;color&amp;quot;&lt;/code&gt;  &lt;code&gt;]}&amp;apos;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;在 _search API 中集成了 ANN（近似最近邻），通过在请求体中添加 knn 选项来使用。knn 对象具有以下定义属性：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;field：（字符串）存储向量嵌入的字段&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;query_vector：（浮点数数组）表示查询的方括号内的浮点数列表；必须具有与向量字段相同的维度（即 384）&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;k：（整数）要检索的最近邻数量；必须小于 num_candidates&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;num_candidates：（整数）在每个分片中要考虑的近似最近邻候选数量（&amp;lt;= 10000）；增加此数字可以提高准确性，但会降低搜索速度&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;响应：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;{&lt;/code&gt;  &lt;code&gt;    ...,&lt;/code&gt;  &lt;code&gt;    &amp;quot;hits&amp;quot;: {&lt;/code&gt;  &lt;code&gt;        &amp;quot;total&amp;quot;: {&lt;/code&gt;  &lt;code&gt;     &amp;quot;value&amp;quot;: 3,&lt;/code&gt;  &lt;code&gt;     &amp;quot;relation&amp;quot;: &amp;quot;eq&amp;quot;&lt;/code&gt;  &lt;code&gt; },&lt;/code&gt;  &lt;code&gt; &amp;quot;max_score&amp;quot;: 0.69120896,&lt;/code&gt;  &lt;code&gt; &amp;quot;hits&amp;quot;: [{&lt;/code&gt;  &lt;code&gt;     &amp;quot;_index&amp;quot;: &amp;quot;neural_index&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_id&amp;quot;: &amp;quot;7686&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_score&amp;quot;: 0.69120896,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_source&amp;quot;: {&lt;/code&gt;  &lt;code&gt;         &amp;quot;color&amp;quot;: &amp;quot;green&amp;quot;,&lt;/code&gt;  &lt;code&gt;  &amp;quot;general_text&amp;quot;: &amp;quot;A. A federal tax identification number ... of business.\n&amp;quot;&lt;/code&gt;  &lt;code&gt;     }&lt;/code&gt;  &lt;code&gt; }, {&lt;/code&gt;  &lt;code&gt;     &amp;quot;_index&amp;quot;: &amp;quot;neural_index&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_id&amp;quot;: &amp;quot;7691&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_score&amp;quot;: 0.6840044,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_source&amp;quot;: {&lt;/code&gt;  &lt;code&gt;         &amp;quot;color&amp;quot;: &amp;quot;white&amp;quot;,&lt;/code&gt;  &lt;code&gt;  &amp;quot;general_text&amp;quot;: &amp;quot;A. A federal tax identification number ... by the IRS.\n&amp;quot;&lt;/code&gt;  &lt;code&gt;     }&lt;/code&gt;  &lt;code&gt; }, {&lt;/code&gt;  &lt;code&gt;     &amp;quot;_index&amp;quot;: &amp;quot;neural_index&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_id&amp;quot;: &amp;quot;7692&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_score&amp;quot;: 0.6787193,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_source&amp;quot;: {&lt;/code&gt;  &lt;code&gt;         &amp;quot;color&amp;quot;: &amp;quot;white&amp;quot;,&lt;/code&gt;  &lt;code&gt;  &amp;quot;general_text&amp;quot;: &amp;quot;Letâs start at the beginning. A tax ID number ... for a person.\n&amp;quot;&lt;/code&gt;  &lt;code&gt;     }&lt;/code&gt;  &lt;code&gt; }]&lt;/code&gt;  &lt;code&gt;    }&lt;/code&gt;  &lt;code&gt;}&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;设置 topK=3 后，我们获取了对于查询 “what is a bank transit number” 最佳的三个文档。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;搜索会计算每个分片中 num_candidates 个向量与查询向量的相似度（确定文档的 _score），从每个分片中选择 k 个最相似的结果，然后合并结果（来自每个分片），返回全局最相似的 k 个邻近文档。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;近似 kNN + 预过滤&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;从 Elasticsearch 8.2 版本开始，支持预过滤功能。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;下面的请求执行了一个带有 color 字段过滤器的近似 kNN 搜索：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;请求：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;curl http://localhost:9200/neural_index/_search -XPOST -H &amp;apos;Content-Type: application/json&amp;apos; -d &amp;apos;{&lt;/code&gt;  &lt;code&gt;&amp;quot;knn&amp;quot;: {&lt;/code&gt;  &lt;code&gt;    &amp;quot;field&amp;quot;: &amp;quot;general_text_vector&amp;quot;,&lt;/code&gt;  &lt;code&gt;    &amp;quot;query_vector&amp;quot;: [-9.01364535e-03, -7.26634488e-02, ..., -1.16323479e-01],&lt;/code&gt;  &lt;code&gt;    &amp;quot;k&amp;quot;: 3,&lt;/code&gt;  &lt;code&gt;    &amp;quot;num_candidates&amp;quot;: 10,&lt;/code&gt;  &lt;code&gt;    &amp;quot;filter&amp;quot;: {&lt;/code&gt;  &lt;code&gt;        &amp;quot;term&amp;quot;: {&lt;/code&gt;  &lt;code&gt;            &amp;quot;color&amp;quot;: &amp;quot;white&amp;quot;&lt;/code&gt;  &lt;code&gt;        }&lt;/code&gt;  &lt;code&gt;    }&lt;/code&gt;  &lt;code&gt;},&lt;/code&gt;  &lt;code&gt;&amp;quot;fields&amp;quot;: [&amp;quot;color&amp;quot;],&lt;/code&gt;  &lt;code&gt;&amp;quot;_source&amp;quot;: false&lt;/code&gt;  &lt;code&gt;}&amp;apos;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;回复：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;{&lt;/code&gt;  &lt;code&gt;    ...,&lt;/code&gt;  &lt;code&gt;    &amp;quot;hits&amp;quot;: {&lt;/code&gt;  &lt;code&gt;        &amp;quot;total&amp;quot;: {&lt;/code&gt;  &lt;code&gt;     &amp;quot;value&amp;quot;: 3,&lt;/code&gt;  &lt;code&gt;     &amp;quot;relation&amp;quot;: &amp;quot;eq&amp;quot;&lt;/code&gt;  &lt;code&gt; },&lt;/code&gt;  &lt;code&gt; &amp;quot;max_score&amp;quot;: 0.6840044,&lt;/code&gt;  &lt;code&gt; &amp;quot;hits&amp;quot;: [{&lt;/code&gt;  &lt;code&gt;     &amp;quot;_index&amp;quot;: &amp;quot;neural_index&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_id&amp;quot;: &amp;quot;7691&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_score&amp;quot;: 0.6840044,&lt;/code&gt;  &lt;code&gt;     &amp;quot;fields&amp;quot;: {&lt;/code&gt;  &lt;code&gt;         &amp;quot;color&amp;quot;: [&amp;quot;white&amp;quot;]&lt;/code&gt;  &lt;code&gt;     }&lt;/code&gt;  &lt;code&gt; }, {&lt;/code&gt;  &lt;code&gt;     &amp;quot;_index&amp;quot;: &amp;quot;neural_index&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_id&amp;quot;: &amp;quot;7692&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_score&amp;quot;: 0.6787193,&lt;/code&gt;  &lt;code&gt;     &amp;quot;fields&amp;quot;: {&lt;/code&gt;  &lt;code&gt;         &amp;quot;color&amp;quot;: [&amp;quot;white&amp;quot;]&lt;/code&gt;  &lt;code&gt;     }&lt;/code&gt;  &lt;code&gt; }, {&lt;/code&gt;  &lt;code&gt;     &amp;quot;_index&amp;quot;: &amp;quot;neural_index&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_id&amp;quot;: &amp;quot;7685&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_score&amp;quot;: 0.6716478,&lt;/code&gt;  &lt;code&gt;     &amp;quot;fields&amp;quot;: {&lt;/code&gt;  &lt;code&gt;         &amp;quot;color&amp;quot;: [&amp;quot;white&amp;quot;]&lt;/code&gt;  &lt;code&gt;     }&lt;/code&gt;  &lt;code&gt; }]&lt;/code&gt;  &lt;code&gt;    }&lt;/code&gt;  &lt;code&gt;}&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;设置 topK=3 后，我们获取了查询 “what is a bank transit number” 和 color 为 “white” 的最佳三个文档。&lt;/p&gt; &lt;p&gt;这个查询确保返回 k 个匹配的文档，因为过滤器查询是在近似 kNN 搜索期间应用的，而不是之后应用的。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;近似 kNN + 其他功能&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;从 8.4 版本开始，还可以执行混合搜索。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;在此请求中，我们通过一个 OR 条件将 knn 选项和查询组合起来。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;请求：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;curl http://localhost:9200/neural_index/_search -XPOST -H &amp;apos;Content-Type: application/json&amp;apos; -d &amp;apos;{&lt;/code&gt;  &lt;code&gt;&amp;quot;query&amp;quot;: {&lt;/code&gt;  &lt;code&gt;    &amp;quot;match&amp;quot;: {&lt;/code&gt;  &lt;code&gt;        &amp;quot;general_text&amp;quot;: {&lt;/code&gt;  &lt;code&gt;            &amp;quot;query&amp;quot;: &amp;quot;federal&amp;quot;&lt;/code&gt;  &lt;code&gt;        }&lt;/code&gt;  &lt;code&gt;    }&lt;/code&gt;  &lt;code&gt;},&lt;/code&gt;  &lt;code&gt;&amp;quot;knn&amp;quot;: {&lt;/code&gt;  &lt;code&gt;    &amp;quot;field&amp;quot;: &amp;quot;general_text_vector&amp;quot;,&lt;/code&gt;  &lt;code&gt;    &amp;quot;query_vector&amp;quot;: [-9.01364535e-03, -7.26634488e-02, ..., -1.16323479e-01],&lt;/code&gt;  &lt;code&gt;    &amp;quot;k&amp;quot;: 3,&lt;/code&gt;  &lt;code&gt;    &amp;quot;num_candidates&amp;quot;: 10&lt;/code&gt;  &lt;code&gt;},&lt;/code&gt;  &lt;code&gt;&amp;quot;size&amp;quot;: 5,&lt;/code&gt;  &lt;code&gt;&amp;quot;_source&amp;quot;: [&lt;/code&gt;  &lt;code&gt;    &amp;quot;general_text&amp;quot;&lt;/code&gt;  &lt;code&gt;]&lt;/code&gt;  &lt;code&gt;}&amp;apos;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;回复：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;  &lt;li&gt; &lt;/li&gt;&lt;/ul&gt; &lt;pre&gt;  &lt;code&gt;{&lt;/code&gt;  &lt;code&gt;    ...,&lt;/code&gt;  &lt;code&gt;    &amp;quot;hits&amp;quot;: {&lt;/code&gt;  &lt;code&gt;        &amp;quot;total&amp;quot;: {&lt;/code&gt;  &lt;code&gt;     &amp;quot;value&amp;quot;: 143,&lt;/code&gt;  &lt;code&gt;     &amp;quot;relation&amp;quot;: &amp;quot;eq&amp;quot;&lt;/code&gt;  &lt;code&gt; },&lt;/code&gt;  &lt;code&gt; &amp;quot;max_score&amp;quot;: 7.4108567,&lt;/code&gt;  &lt;code&gt; &amp;quot;hits&amp;quot;: [{&lt;/code&gt;  &lt;code&gt;     &amp;quot;_index&amp;quot;: &amp;quot;neural_index&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_id&amp;quot;: &amp;quot;7555&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_score&amp;quot;: 7.4108567,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_source&amp;quot;: {&lt;/code&gt;  &lt;code&gt;         &amp;quot;general_text&amp;quot;: &amp;quot;Filed under: OPM Disability Process | Tagged: appeal deadlines during the fers disability process, average time frame for fers disability retirement, civil service disability, federal disability law blog, federal disability process timelines, federal disability retirement application and process, federal disabled employees and the patience needed, ...\n&amp;quot;&lt;/code&gt;  &lt;code&gt;     }&lt;/code&gt;  &lt;code&gt; }, {&lt;/code&gt;  &lt;code&gt;     &amp;quot;_index&amp;quot;: &amp;quot;neural_index&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_id&amp;quot;: &amp;quot;8014&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_score&amp;quot;: 7.395675,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_source&amp;quot;: {&lt;/code&gt;  &lt;code&gt;         &amp;quot;general_text&amp;quot;: &amp;quot;Federal law (5 U.S.C. 6103) establishes the public holidays listed in these pages for Federal employees. Please note that most Federal employees work on a Monday through Friday schedule.\n&amp;quot;&lt;/code&gt;  &lt;code&gt;     }&lt;/code&gt;  &lt;code&gt; }, {&lt;/code&gt;  &lt;code&gt;     &amp;quot;_index&amp;quot;: &amp;quot;neural_index&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_id&amp;quot;: &amp;quot;2659&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_score&amp;quot;: 7.235115,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_source&amp;quot;: {&lt;/code&gt;  &lt;code&gt;         &amp;quot;general_text&amp;quot;: &amp;quot;The authority of the Federal Reserve Banks to issue notes comes from the Federal Reserve Act of 1913. Legally, they are liabilities of the Federal Reserve Banks and obligations of the United States government.\n&amp;quot;&lt;/code&gt;  &lt;code&gt;     }&lt;/code&gt;  &lt;code&gt; }, {&lt;/code&gt;  &lt;code&gt;     &amp;quot;_index&amp;quot;: &amp;quot;neural_index&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_id&amp;quot;: &amp;quot;3337&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_score&amp;quot;: 7.1420827,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_source&amp;quot;: {&lt;/code&gt;  &lt;code&gt;         &amp;quot;general_text&amp;quot;: &amp;quot;Federal Employee Retirement System - FERS. DEFINITION of &amp;apos;Federal Employee Retirement System - FERS&amp;apos;. A system that became effective in 1987 and replaced the Civil Service Retirement System (CSRS) as the primary retirement plan for U.S. federal civilian employees.\n&amp;quot;&lt;/code&gt;  &lt;code&gt;     }&lt;/code&gt;  &lt;code&gt; }, {&lt;/code&gt;  &lt;code&gt;     &amp;quot;_index&amp;quot;: &amp;quot;neural_index&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_id&amp;quot;: &amp;quot;580&amp;quot;,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_score&amp;quot;: 7.111601,&lt;/code&gt;  &lt;code&gt;     &amp;quot;_source&amp;quot;: {&lt;/code&gt;  &lt;code&gt;         &amp;quot;general_text&amp;quot;: &amp;quot;Federal Laws vs. State Laws. Federal laws, or statutes, are created by the United States Congress to safeguard the citizens of this country. Some criminal acts are federal offenses only and must be prosecuted in U.S. District Court.\n&amp;quot;&lt;/code&gt;  &lt;code&gt;     }&lt;/code&gt;  &lt;code&gt; }]&lt;/code&gt;  &lt;code&gt;    }&lt;/code&gt;  &lt;code&gt;}&lt;/code&gt;&lt;/pre&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;这个搜索操作：&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;p&gt;从每个分片中收集 knn num_candidates（10）个结果；&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;找到全局的前 k=3 个向量匹配；&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;将它们与 match 查询（=federal）的匹配结果合并；&lt;/p&gt;&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;最终返回得分排名前 5 个（size=5）结果（即使总共有 143 个命中）。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;得分是通过将 knn 分数和查询分数相加来计算的，还可以指定 boost 值以赋予每个分数不同的权重。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;knn 选项还可以与聚合一起使用，即在前 k 个最近的文档上计算聚合，而不是在所有匹配搜索的文档上进行聚合。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;二、总结&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;我们希望这个教程能帮助你了解如何在 Elasticsearch 中使用基于向量的搜索。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;还有一些工作可以做，比如支持多值字段，改进重新排序以及与 BERT 和 Transformer 的整合。实际上，这是一个开放的 GitHub 问题 [4]，他们正在进行 ANN 搜索的各种改进（包括新功能、增强功能、性能改进等）。&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;如果对你于密集向量的 Elasticsearch 基准测试感兴趣，你可以在这里 [5] 找到一些已发布的结果。&lt;/p&gt; &lt;p&gt; &lt;/p&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;    &lt;p&gt;参考资料&lt;/p&gt; &lt;p&gt;【1】https://sease.io/wp-admin/post.php?post=56082&amp;amp;action=edit&lt;/p&gt; &lt;p&gt;【2】https://github.com/SeaseLtd/vector-search-elastic-tutorial&lt;/p&gt; &lt;p&gt;【3】https://msmarco.blob.core.windows.net/msmarcoranking/queries.tar.gz&lt;/p&gt; &lt;p&gt;【4】https://github.com/elastic/elasticsearch/issues/84324&lt;/p&gt; &lt;p&gt;【5】https://elasticsearch-benchmarks.elastic.co/#tracks/dense_vector/nightly/default/30d&lt;/p&gt; &lt;p&gt; &lt;/p&gt;作者丨李鹏&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62791-elasticsearch-%E5%90%91%E9%87%8F-%E6%95%B0%E6%8D%AE%E5%BA%93</guid>
      <pubDate>Sun, 25 Jun 2023 14:05:22 CST</pubDate>
    </item>
    <item>
      <title>超大规模数据库集群保稳系列之三：美团数据库容灾体系建设实践 - 美团技术团队</title>
      <link>https://itindex.net/detail/62776-%E8%B6%85%E5%A4%A7-%E6%A8%A1%E6%95%B0-%E9%9B%86%E7%BE%A4</link>
      <description>&lt;div&gt;    &lt;h2&gt;1 容灾介绍&lt;/h2&gt;    &lt;p&gt;我们通常会把故障分为三大类，一是主机故障，二是机房故障，三是地域故障。每类故障都有各自的诱发因素，而从主机到机房再到地域，故障发生概率依次越来越小，而故障的影响却越来越大。&lt;/p&gt;    &lt;p&gt;容灾能力的建设目标是非常明确的，就是要能够应对和处理这种机房级和地域级的大规模故障，从而来保障业务的连续性。近几年，业界也发生了多次数据中心级别的故障，对相关公司的业务和品牌产生了非常大的负面影响。当前容灾能力已经成为众多IT企业建设信息化系统的必选项。&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://p0.meituan.net/travelcube/fb4e27cd9aafa3e2c76606ea86cca19a475290.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;h2&gt;2 业务容灾架构&lt;/h2&gt;    &lt;h3&gt;2.1 容灾架构演进&lt;/h3&gt;    &lt;p&gt;容灾架构从最早期的单活形态（同城主备）到同城多活形态，再演化到异地多活，根据这个路径可以将容灾分为容灾1.0、容灾2.0、容灾3.0三个阶段。&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;strong&gt;容灾1.0&lt;/strong&gt;：容灾体系围绕数据建设，多以主-备的方式部署，但备用机房不承担流量，基本上都是单活结构。&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;容灾2.0&lt;/strong&gt;：容灾视角从数据转换为应用系统，业务具有同城双活或同城多活能力，采用同城双活或同城双活加异地冷备（两地三中心）的部署架构，除冷备以外的每个机房都有流量处理能力。&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;容灾3.0&lt;/strong&gt;：以业务为中心，多采用单元化架构，容灾基于单元间的两两互备实现，根据单元的部署位置可以实现同城多活和异地多活。采用单元化架构的应用本身具有很好的容灾能力和扩展能力。&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;img alt="" src="https://p0.meituan.net/travelcube/5a6472577564e07f6570c0d521e003df526010.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;由于各公司所处发展阶段不同，采用的方案也会有所区别，美团大部分业务处于2.0阶段（即同城双活或多活架构），但对于大体量、有地域容灾及有地域扩展性要求的业务则处在容灾3.0阶段。下面会介绍一下美团的容灾架构。&lt;/p&gt;    &lt;h3&gt;2.2 美团容灾架构&lt;/h3&gt;    &lt;p&gt;美团的容灾架构主要包括两种，一种是N+1容灾架构，一种是SET化架构。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;N+1架构&lt;/strong&gt;：在业界也称散部或者多AZ部署⽅案，将容量为C的系统部署在N+1个机房，每个机房能提供至少C/N的容量，挂掉任何一个机房时，剩余系统仍能支撑C的容量。该方案的核心是把容灾能力下沉到PaaS组件来完成，在出现机房级或者地域级故障的时候，由各个PaaS组件独立完成容灾切换，实现业务恢复。整体架构如下图所示，业务上表现是多机房、多活形态，数据库采用这种主从架构，单机房处理写流量、多机房的负载均摊读流量。下面要讲“数据库容灾体系建设实践” 就是面向N+1架构的。&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://p1.meituan.net/travelcube/c36bcca2ee86e62009ffd11e1883f0f3190677.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;单元化架构&lt;/strong&gt;：也叫SET化架构，这是一种偏应用层的容灾架构，它将应用，数据，基础组件按照统一的维度切分成多个单元，每个单元处理一部分闭环流量。业务以单元作为部署单位，通过单元互备方式实现同城容灾或者异地容灾。一般金融业务或者超大规模的业务会选择此类架构，它的好处就是流量可以闭环且资源隔离，具有很强的容灾能力和跨域扩展能力，不过SET化架构的落地需要业务系统做大量的改造，运维管理也较为复杂。简化示意图如下：&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://p0.meituan.net/travelcube/73b76a17cbcba274789e571a12834c7a363087.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;美团内部的大部分业务都是N+1架构，外卖和金融等业务采用了单元化架构。总体上美团内部既有同城多活，也有异地多活，两种容灾方案并存。&lt;/p&gt;    &lt;h2&gt;3 数据库容灾建设&lt;/h2&gt;    &lt;h3&gt;3.1 面临的挑战&lt;/h3&gt;    &lt;p&gt;      &lt;strong&gt;超大规模的集群带来的挑战&lt;/strong&gt;：公司业务高速发展，服务器规模指数级增⻓，数据中心规模越来越大，大机房已有大几千数据库集群，上万个实例。&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;strong&gt;性能问题&lt;/strong&gt;：高可用系统的故障并发处理能力出现明显瓶颈。&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;容灾失效风险&lt;/strong&gt;：管控链路随集群数量的增加变的越来越复杂，一个环节出问题就会导致整体容灾能力失效。&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;故障频发&lt;/strong&gt;：集群数量和规模变大，使原来概率很低的大规模故障变成了稀松平常的故障，其发生的频次和概率越来越高。&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;strong&gt;演练成本高、频次低&lt;/strong&gt;：核心能力验证不充分，大规模故障的应对能力处于不可知状态，已知容灾能力“保鲜”困难。拿应对机房级大规模故障的相关能力来讲，很大一部分是处于不可知状态或者仅存在于“纸面”分析中，而对于已验证过的能力随着架构演进迭代，“保鲜”也很困难。&lt;/p&gt;    &lt;p&gt;数据库作为有状态的服务之一，本身建设应对大规模故障能力的难度和挑战都相对更大。&lt;/p&gt;    &lt;h3&gt;3.2 基础高可用&lt;/h3&gt;    &lt;p&gt;数据库架构 在美团主要有两种一种是主从架构，一种是MGR架构。&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://p0.meituan.net/travelcube/2621c1b5737fad2c4a5800606c818e5f719952.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;strong&gt;主从架构&lt;/strong&gt;：应用通过数据库中间件访问数据库，在故障发生时，高可用做故障探测、拓扑调整、配置下发，进而应用恢复。&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;MGR架构&lt;/strong&gt;：应用也是通过中间件访问数据库，不过中间件对MGR做了适配，内部叫Zebra for MGR，中间件自动进行拓扑探测感知，一旦MGR发生了切换，新拓扑会被探测到，数据源会进行调整，进而业务恢复。&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;美团的高可用架构&lt;/strong&gt;：美团主从集群的高可用是基于Orchestrator二次开发的，本质上是一个中心化的管控架构，如下图所示，有多个高可用分组，每个分组托管一部分数据库集群，分组在北京和上海实现两Region部署，底层核心组件只在北京部署，比如我们的核心CMBD、WorkflowDB等，一旦北上专线出现问题，上海侧的高可用会失效不可用。&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;img alt="" src="https://p1.meituan.net/travelcube/38b23a112b97f2928e68b598f5cb1451451449.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;h3&gt;3.3 容灾建设路径&lt;/h3&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;strong&gt;容灾建设路径&lt;/strong&gt;：确定容灾目标、制定容灾标准、建设容灾平台、夯实基础能力、演练验证和风险运营。&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;容灾建设飞轮&lt;/strong&gt;：内环是平台能力建设，从容灾需求的提出到研发上线，体验提升，用户使用，发现问题提出新需求，不断的迭代提升。另一个方面就是完善演练平台建设，开展高频演练（或者真实故障驱动），发现问题、提出改进，促近平台能力持续迭代提升。&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;img alt="" src="https://p0.meituan.net/travelcube/7c9532564bd5bf7344878341d8f0d841434076.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;h3&gt;3.4 平台能力建设&lt;/h3&gt;    &lt;p&gt;为了建设提升数据库服务的容灾能力，内部成立了容灾管控项目DDTP（Database Disaster Tolerance Platform），专注提升数据库应对大规模故障的能力，核心包括基础容灾管控和故障演练两大能力，分别对应两个平台产品：一是容灾管控平台，一个是数据库演练平台。&lt;/p&gt;    &lt;p&gt;容灾管控平台主要专注于防守，它的核心功能主要包括事前逃生、事中观测以及止损、事后恢复等，数据库演练平台则专注于进攻，支持多种故障类型和多种故障注入方式，具备故障编排，故障复盘等核心能力。这个系列的第二篇      &lt;a href="https://tech.meituan.com/2023/05/26/database-attack-and-defense-practice.html"&gt;《数据库攻防演练建设实践》&lt;/a&gt;就是对演练平台的详细介绍。接下来，我们将重点介绍一下容灾管控平台的主要内容，首先看一下全景图：&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://p0.meituan.net/travelcube/c1a347778b22d1a4dec722011f5c8607299314.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;strong&gt;数据库服务&lt;/strong&gt;：包括MySQL、Blade、MGR等基础数据库服务。&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;基础能力层&lt;/strong&gt;：主要是备份恢复、资源管理、弹性伸缩、主从高可用以及指标监控能力，这些能力是稳定性保障的基本部分，但在容灾场景下需要进一步加强，以处理大规模故障场景。&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;管控编排层&lt;/strong&gt;：核心是运维编排服务OOS（Operation Orchestration Service），会把基础能力按需编排生成对应的处理流程也叫服务化预案，每个预案对应一个或者多个具体的运维场景。容灾预案也在这个范畴。&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;平台服务层&lt;/strong&gt;：是容灾管控平台的能力层，包括：1）        &lt;strong&gt;容灾管控&lt;/strong&gt;，容灾计算评估和隐患治理，还有故障前容灾逃生、故障中的兜底切换，故障摘流等。2）        &lt;strong&gt;容灾观测&lt;/strong&gt;，明确故障范围，支持故障中的容灾决策。3）        &lt;strong&gt;容灾恢复&lt;/strong&gt;，故障后通过实例修复、集群扩容等功能快速恢复集群的容灾能力。4）        &lt;strong&gt;预案服务&lt;/strong&gt;，包含了常见故障应急预案的管理和执行等等。&lt;/li&gt;&lt;/ul&gt;    &lt;h4&gt;3.4.1 容量达标&lt;/h4&gt;    &lt;p&gt;数据库建立了一套N+1容灾计算标准，分为6个等级，如果集群容灾等级≥4级则容灾达标，否则容灾不达标。&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://p0.meituan.net/travelcube/c841b10764c877020a2af7e35eafd759300460.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;从标准可以看出，从等级3开始就是多机房部署了。3级和4、5级的区别是，3级不满足N+1要求，即如果一个机房的节点都出问题，剩余节点无法承担峰值流量。等级4、5都是具备N+1要求的，等级5会满足region间容量对等。除基础标准以外，SET化集群有特殊规则，比如路由策略要闭环、SET集群的绑定机房要统一、互备SET容量要对等、集群内机型要统一等。这些规则都会纳入容灾计算来确定集群的最终容灾等级。&lt;/p&gt;    &lt;p&gt;在基础容灾数据建设中，会把上述规则代码化、计算流程化，通过近实时的方式做基础数据“保鲜”。容灾数据是容灾管控平台上用于逃生切换和事中止损的基础数据，同时还会基于容灾数据建设风险隐患（即容灾不达标隐患），并通过一定的运营治理来消除这种隐患。&lt;/p&gt;    &lt;h4&gt;3.4.2 故障前逃生&lt;/h4&gt;    &lt;p&gt;故障前逃逸能力就是批量主库切换和从库摘流，主要用于在故障前收到预警，提前感知灾难来临，快速将一个机房的所有数据库服务切走或者下线从库流量，以降低真实故障带来的影响。&lt;/p&gt;    &lt;p&gt;我们知道对于主从架构的集群，如果因为断电或者断网发生故障切换，很可能会发生数据丢失。数据一旦丢失，业务需要进行确认并做善后工作，有时候会非常繁琐。如果能够在事前逃走就会把这些风险都规避掉。同时除了主库逃走以外，从库也可以提前把流量“摘掉”，从而做到故障对业务方“无感”。&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://p0.meituan.net/travelcube/ce887fd7cd6a3c1e3465d46ed91236fc530699.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://p0.meituan.net/travelcube/0340dd86245b70819ad3244fc009b8c7384027.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;h4&gt;3.4.3 故障中观测&lt;/h4&gt;    &lt;p&gt;在大规模故障发生的时候，一般会出现告警轰炸，电话咨询轰炸等情况，如果没有全局的故障感知能力，就会使故障处理比较混乱，处理时间比较长，让故障影响放大，所以我们建设了容灾观测大盘，它能够实时、准确、可靠地对故障进行观测，以确保值班同学能够掌握故障的实时情况。&lt;/p&gt;    &lt;p&gt;如下图所示，如果发生了故障，可以快速拿到故障集群或者实例列表，并在对应的页面上发起兜底切换动作，进而实现快速止损。对观测大盘的核心诉求就是要实时、准确、可靠。可以通过减少服务依赖来提升自身的可用性。&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://p0.meituan.net/travelcube/e60dd94c861c909a2128fc8fc88ed100540674.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;h4&gt;3.4.4 故障中止损&lt;/h4&gt;    &lt;p&gt;在介绍故障中的止损之前，先了解一下预案服务。预案服务的核心功能就是管理常见故障以及对应的各种处理预案，并提供执行控制能力，让预案可以方便、可控地运行。&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://p0.meituan.net/travelcube/561a918615073403c930c95a9312c5ac265039.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;故障止损&lt;/strong&gt;：在有了预案以后，我们就可以进行兜底止损。如下图所示，当大规模故障发生的时候，HA会自动进行故障处理。如果集群切换失败或者漏切，那么它就会进入兜底阶段。首先从DDTP平台化兜底，如果平台受故障影响不可用，可以在运维编排层进行兜底。如果运维编排服务也失效，则需要人工通过CLI工具进行兜底。CLI是DBA最底层的工具，它和高可用是两个独立的链路。CLI会进行集群拓扑探测、选主选举、拓扑调整、配置修改、配置下发等逻辑，等同于手工集群切换步骤。&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://p1.meituan.net/travelcube/805f625d5d04bbfe8592c5665e32d85f164310.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://p0.meituan.net/travelcube/996aa357410aceef14126b7790311ac5502146.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;总体原则优先提升高可用自动切换的成功率，减少透传到兜底阶段的集群数量。其次提升预案可靠性，优先选择白屏，逐级下沉，易用性下降，可靠性提升。&lt;/p&gt;    &lt;h4&gt;3.4.5 故障后恢复&lt;/h4&gt;    &lt;p&gt;虽然集群具备N+1能力，一个机房故障的时候，集群剩余节点是能够支撑峰值流量，但它不具备再一次AZ故障的容灾能力，所以在故障后会根据各机房的资源情况，通过容灾决策中心快速进行集群扩容来补齐核心集群的容灾容量，使其重新具备AZ容灾能力。&lt;/p&gt;    &lt;p&gt;上述方案有一个比较大的弊端就是需要有足够的资源来进行扩容，这是非常困难的，目前我们在建设更快速的恢复能力，如实例原地修复，集群原地扩容等，在AZ恢复之后，可以快速复用发生故障的机房内的机器资源，实现容灾快速恢复。&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://p1.meituan.net/travelcube/95a9626104207eb46337ec93e1ac27cb625774.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;h3&gt;3.5 演练体系建设&lt;/h3&gt;    &lt;p&gt;各项基础容灾能力不能只存在于架构设计、理论评估层面，必须实打实的可用，这就要需要通过演练进行验证。容灾管控项目之初，就制定了以演练为抓手的策略，验证并驱动各项基础能力的提升。 截止目前，已经初步建成了多环境、高频次、大规模、长链路的演练体系。&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://p0.meituan.net/travelcube/e382dc79f8271564c54a723f40c3e9ec230951.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;strong&gt;多环境&lt;/strong&gt;：我们建设了多种演练环境，满足各个PaaS组件的各类容灾演练需求。一是容灾管控平台的⻓稳环境，二是线下专用于演练的隔离环境，三是生产环境，有演练专区以及正常生产环境。&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;高频次&lt;/strong&gt;：目前能做到天、周级别。天级别属于常态化的演练，主要是在长稳环境下自动发起，几百个集群的演练规模；周级别主要是在隔离环境、演练专区定期组织的断网、断电真实演练等。&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;大规模&lt;/strong&gt;：是在生产环境开展的演练，用于验证基础高可用、兜底预案、逃生预案、容灾恢复等功能的大规模、高并发处理能力，确定管控系统的服务容量。&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;长链路&lt;/strong&gt;：整个容灾链路涉及到很多组件，包括CMDB数据库、流程数据库，高可用组件，配置中心、预案服务等，我们会逐步把这些组件都纳入演练，可以让一个或者多个组件服务同时故障，发现潜在问题，验证多服务的多节点同时故障对于整个故障处理能力的影响。&lt;/li&gt;&lt;/ul&gt;    &lt;h4&gt;3.5.1 隔离环境演练&lt;/h4&gt;    &lt;p&gt;隔离环境演练顾名思义，它是一套和生产机房完全隔离的演练环境，有自己独立的TOR、机柜，风险能做到完全隔离，可以开展独立断网或断电操作。参与演练的PaaS组件和业务服务要在该环境独立部署。在隔离环境除了会定期开展各种容灾演练发现容灾问题外，还可以验证各PaaS的独立部署能力，为国际化业务支撑提供基础。&lt;/p&gt;    &lt;h4&gt;3.5.2 生产环境演练&lt;/h4&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;strong&gt;常态化、大规模故障演练&lt;/strong&gt;：此类演练是日常持续开展的，通过演练平台对数据库集群注入故障，高可用进行故障切换。通过不同的演练规模来验证高可用的并发切换能力。此外，在容灾管控平台上，可以验证逃生能力、止损预案、及大规模故障的观测等。总而言之，它是利用“攻”和“防”相结合的形式，实现能力的验证验收和优化提升。&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;这类演练主要特点：一是参演集群都是由生产环境的高可用分组进行托管，就是说演练验证的都是生产环境的高可用的能力；二是参演的大规模集群是非业务集群，是每次演练前新创建的专门用于演练的集群，规模可以做到很大，目前可以常态化的进行1500+集群同时进行演练；三是有一定的仿真效果，为使演练更为真实并对RTO做精准评估，对演练集群增加了带载能力。&lt;/p&gt;    &lt;p&gt;      &lt;img alt="" src="https://p1.meituan.net/travelcube/143e9a2ea237e36c557ba9cbc4aee086797626.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;strong&gt;真实专区演练&lt;/strong&gt;：上文介绍的隔离环境演练、大规模演练都是偏模拟性质的，和真实的故障场景有比较大的区别。为了弥补和真实故障主键的GAP，我们基于公有云构建了一个专用演练AZ，可以理解为就是一个独立的机房。参演业务和组PaaS件将部分承载业务流量的服务节点部署到演练AZ中，实际演练的时候会进行真实的断网，业务和组件可以在断网的时候观测和评估自己的容灾情况。这种通过真实机房、真实组件集群、真实的业务流量来验证组件和业务的实际容灾情况，会更加真实。&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;img alt="" src="https://p1.meituan.net/travelcube/3e34908029a5e3a999c8574baaa9e563145798.png"&gt;&lt;/img&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;strong&gt;Game Day&lt;/strong&gt;：此外我们还在评估论证在真实机房开展演练的可行性，随着隔离环境演练、专区演练的常态化开展，各个组件的基础容灾能力会越来越强，在真实机房进行常态化机房演练的终极目标也会随之达成。&lt;/li&gt;&lt;/ul&gt;    &lt;h2&gt;4 未来思考&lt;/h2&gt;    &lt;p&gt;经过两年多的建设，虽然在高可用自动切换、容灾能力运营治理、大规模故障观测、故障止损预案、容灾恢复等方面取得了一定的成果。但是还有很多能力短板需要建设补齐，业务新的发展也带来了新的需求和挑战。未来我们会补齐短板、迭代技术架构两个方向上进行持续的提升。&lt;/p&gt;    &lt;h3&gt;4.1 补齐短板&lt;/h3&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;strong&gt;超大规模逃生能力、止损能力不足&lt;/strong&gt;：随着我们自建数据中心的落地，我们自建的AZ规模会更大，这对能力的要求会更高，我们主要通过平台迭代和演练验证逐步提升能力。&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;跨域专线故障导致Region级高可用失效&lt;/strong&gt;：接下来我们会探索单元化方案或者独立部署方案，实现Region级或者更细粒度的闭环管理。&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;业务出海新挑战&lt;/strong&gt;：出海会给容灾架构带来一些新需求和挑战，是采用“长臂管辖”还是独立部署，是复用现有技术体系还是打造一套全新架构，这些问题都还需要进一步的探索和论证。&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;容灾效率问题&lt;/strong&gt;：平台基础功能已经相对完善，不过容灾决策以及处理协同等还需要人工进行，效率相对较低，未来会把容灾管控、应急止损等能力逐步向自动化演进；多环境演练成本比较高，也要逐步做自动化演练，把核心的演练场景逐步纳到长稳环境，通过定时或一定的策略让它自动去跑故障场景，我们只需要关注核心指标运营即可。&lt;/li&gt;&lt;/ul&gt;    &lt;h3&gt;4.2 迭代架构&lt;/h3&gt;    &lt;p&gt;数据库相关技术发展很快，比如Database Mesh、Serverless等新技术形态会逐步落地，届时中间件、高可用、内核等会有比较大的变化，新型客户端HA方案的建设成熟及新Proxy架构，存计分离产品的引入都会使容灾的能力发生比较大的变化。容灾能力建设会随着这些确定的产品演进进行迭代。&lt;/p&gt;    &lt;p&gt;容灾建设是一件非常有挑战的事，也是所有公司业务发展壮大后必须面对的一件事。欢迎大家在文末留言，跟我们一起交流。&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62776-%E8%B6%85%E5%A4%A7-%E6%A8%A1%E6%95%B0-%E9%9B%86%E7%BE%A4</guid>
      <pubDate>Fri, 09 Jun 2023 23:59:45 CST</pubDate>
    </item>
    <item>
      <title>探索性数据分析详解</title>
      <link>https://itindex.net/detail/62737-%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90</link>
      <description>&lt;h2&gt;什么是探索性数据分析？&lt;/h2&gt;
 &lt;p&gt;探索性数据分析（Exploratory Data Analysis，简称EDA） 是指对已有的数据（特别是调查或观察得来的原始数据）在尽量少的先验假定下进行探索，通过作图、制表、方程拟合、计算特征量等手段探索数据的结构和规律的一种数据分析方法。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="181" src="https://www.biaodianfu.com/wp-content/uploads/2023/04/eda.png" width="480"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;探索性数据分析（EDA）与传统统计分析（Classical Analysis）的区别：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;传统的统计分析方法通常是先假设样本服从某种分布，然后把数据套入假设模型再做分析。但由于多数数据并不能满足假设的分布，因此，传统统计分析结果常常不能让人满意。&lt;/li&gt;
  &lt;li&gt;探索性数据分析方法注重数据的真实分布，强调数据的可视化，使分析者能一目了然看出数据中隐含的规律，从而得到启发，以此帮助分析者找到适合数据的模型。“探索性”是指分析者对待解问题的理解会随着研究的深入不断变化。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;img alt="" height="446" src="https://www.biaodianfu.com/wp-content/uploads/2023/04/eda-diff.png" width="480"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;探索性数据分析除了日常的数据分析外，也是算法模型搭建过程中的必要环节。特别适合数据比较杂乱，不知所措的场景。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="66" src="https://www.biaodianfu.com/wp-content/uploads/2023/04/eda-1.png" width="780"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;探索性分析用一句话概况就是：折磨数据，它会坦白任何事情。&lt;/p&gt;
 &lt;h2&gt;探索性数据分析的一般流程&lt;/h2&gt;
 &lt;p&gt;探索性分析的一般流程：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;数据总览&lt;/li&gt;
  &lt;li&gt;探索性分析每个变量&lt;/li&gt;
  &lt;li&gt;探索性分析变量与target标签的关系&lt;/li&gt;
  &lt;li&gt;探索性分析变量之间的关系&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;img alt="" height="647" src="https://www.biaodianfu.com/wp-content/uploads/2023/04/eda-flow.png" width="480"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h3&gt;数据总览&lt;/h3&gt;
 &lt;p&gt;在数据处理前首先要充分了解数据，了解数据包含以下两部分：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;了解数据的外部信息。即数据的现实意义。可通过业务知识与流量计获取采集方式进行了解。&lt;/li&gt;
  &lt;li&gt;了解数据的内部信息。即数据的自身情况。可通过统计学的相关知识，如计算均值，标准差，峰度，偏度等。另外，也可以通过绘图，来深入了解数据，为创建有效特征提供思路。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;对于数据总览一般可借助Pandas的一些函数对数据有些大概了解：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;describe() # 查看所有数据平均值，四分位数等信息&lt;/li&gt;
  &lt;li&gt;info() # 查看所有数据的数据类型和非空值个数。&lt;/li&gt;
  &lt;li&gt;shape # 查看数据行列数&lt;/li&gt;
  &lt;li&gt;isnull().sum() # 查看数据各个特征为空值的个数&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;探索性分析每个变量&lt;/h3&gt;
 &lt;p&gt;需要了解的内容包括：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;变量是什么类型&lt;/li&gt;
  &lt;li&gt;变量是否有缺失值&lt;/li&gt;
  &lt;li&gt;变量是否有异常值&lt;/li&gt;
  &lt;li&gt;变量是否有重复值&lt;/li&gt;
  &lt;li&gt;变量是否均匀&lt;/li&gt;
  &lt;li&gt;变量是否需要转换&lt;/li&gt;
  &lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;在分析每个变量可通过描述统计量和图表进行描述。数据类型分为数值型，类别型，文本型，时间序列等。这里主要指的是数值型（定量数据）和类别型（定性数据），其中数值型又可以分为连续型和离散型。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="197" src="https://www.biaodianfu.com/wp-content/uploads/2023/04/data.png" width="480"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h4&gt;1）连续数据分析&lt;/h4&gt;
 &lt;p&gt;数据分析分为两个方面，一是统计汇总，二是可视化。离散也是这样。&lt;/p&gt;
 &lt;p&gt;统计计算：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;在统计学中，想要描述一个数据，要从三个方面进行说明：
   &lt;ul&gt;
    &lt;li&gt;集中趋势：均值，中位数，众数。对于正太分布的数据，均值的效果比较好，而对于有偏数据，因为存在极值，所有会对均值产生影响，此时，用中位数去进行集中趋势的描述。&lt;/li&gt;
    &lt;li&gt;离散程度：方差和标准差。这两个用哪个都可，不过标准差是具有实际意义的。另外，还可以用极差，平均差，四分位差，离散系数（针对多组数据离散程度的对比）。&lt;/li&gt;
    &lt;li&gt;分布形状：偏度skew()，衡量数据偏斜情况。峰度kurt()，衡量数据分布的平坦度。检验数据正态性。一般可绘制P-P图，Q-Q图来进行判断。或者通过计算偏度，峰度进行判断，也有其他别的方法，但了解的较少。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;数据转化。这步一般在特征工程中，这里提一下，通过box-cox可以将非正态数据转为正态数据。&lt;/li&gt;
  &lt;li&gt;游程检验。非参数统计的一种方法，判断数据是否是随机出现的。连续，离散都可以用。&lt;/li&gt;
  &lt;li&gt;通过describe()，可观察数据的大致情况。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;可视化：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;对连续数据可视化主要有以下几个图形：
   &lt;ul&gt;
    &lt;li&gt;直方图。可以大致看出数据的分布情况，但会受限于bins的取值并且图形不光滑。可在直方图上再画出核密度图(KDE)，进行更详细的查看。&lt;/li&gt;
    &lt;li&gt;核密度估计&lt;/li&gt;
    &lt;li&gt;核密度图&lt;/li&gt;
    &lt;li&gt;箱线图。反映原始数据的分布特征，还能进行多组数据的比较。可看出数据的离群点。&lt;/li&gt;
    &lt;li&gt;散点图。利用索引和连续数据作散点图，直观看数据是否随机。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;类型转换
   &lt;ul&gt;
    &lt;li&gt;将连续型数据转为离散型数据。比如，年龄，可以将其分组为少年，青年，壮年，老年等。这种处理方式的关键是如何分组，在数据噪声处理中有过描述，介绍了人为区分，等深等宽分组，无监督算法分组，聚类等方法。&lt;/li&gt;
    &lt;li&gt;关于为什么要把连续型数据转为离散型数据，大概的好处有：去噪声，易理解，算法需要。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;针对连续变量&lt;/strong&gt;常见的描述统计量：平均值，中位数，众数，最小值，最大值，四分位数，标准差等&lt;/p&gt;
 &lt;p&gt;图表：频数分布表（需进行分箱操作），直方图，箱形图（查看分布情况）&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="139" src="https://www.biaodianfu.com/wp-content/uploads/2023/04/data-1.png" width="780"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h4&gt;2）离散数据分析&lt;/h4&gt;
 &lt;p&gt;统计计算&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;主要查看数据的结构。用众数看哪类数据出现的最多。利用value_counts()函数，查看各个类别出现的次数。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;可视化&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;饼图。对于查看数据结构比较直观，所占百分比。&lt;/li&gt;
  &lt;li&gt;柱形图。对各类别出现次数进行可视化。可排序，这样观察数据更直观。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;针对  &lt;strong&gt;无序型离散变量&lt;/strong&gt;常见的描述统计量：各个变量出现的频数和占比&lt;/p&gt;
 &lt;p&gt;图表：频数分布表（绝对频数，相对频数，百分数频数），柱形图，条形图，茎叶图，饼图&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="229" src="https://www.biaodianfu.com/wp-content/uploads/2023/04/data-2.png" width="480"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;针对  &lt;strong&gt;有序型离散变量&lt;/strong&gt;常见的描述统计量：各个变量出现的频数和占比&lt;/p&gt;
 &lt;p&gt;图表：频数分布表，堆积柱形图，堆积条形图（比较大小）&lt;/p&gt;
 &lt;h3&gt;变量间关系分析&lt;/h3&gt;
 &lt;p&gt;当对单个数据分析完后，还要看各个数据与目标特征的关系，和除目标特征外，其他数据间的关系。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;探索性分析变量与target标签的关系&lt;/li&gt;
  &lt;li&gt;探索性分析变量之间的关系&lt;/li&gt;
&lt;/ul&gt;
 &lt;h4&gt;1）连续型变量与连续型变量关系&lt;/h4&gt;
 &lt;p&gt;统计计算：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;协方差，可以得到两个变量间的相关性。但协方差越大，并不表明越相关。因为协方差的定义中没有考虑属性值本身大小的影响。&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://www.biaodianfu.com/pearson-kendall-spearman.html"&gt;相关系数&lt;/a&gt;考虑了属性值本身大小的影响，因此是一个更合适的统计量。取值在[-1,1]上，-1表示负相关，即变换相反，1表示正相关，0则表示不相关。相关系数是序数型的，只能比较相关程度大小(绝对值比较),并不能做四则运算。而相关系数一般常用的有三种：
   &lt;ul&gt;
    &lt;li&gt;Pearson相关系数：这个比较常用，主要用于正态的连续型数据间的比较。但在使用时，限制的条件比较多，对于偏态数据，效果不是很好。&lt;/li&gt;
    &lt;li&gt;Spearman相关系数：相比于Pearson，这个的限制条件比较少，不受异常值影响。可以应用在多种场合。但若对正太正态数据使用，则效果一般。&lt;/li&gt;
    &lt;li&gt;Kendall相关系数：限制条件同Spearman。一般用在分类数据的相关性上。&lt;/li&gt;
    &lt;li&gt;注：Pearson和协方差，主要看数据间的关系是不是线性的，如不是线性，但有其他联系，这两个系数是判断不出来的。比如指数函数这种。而Spearman和Kendall则可以进行一定的判断，主要是单调增函数。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;可视化&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;散点图。可看出两个特征间的关系大致是什么样的。如果要具体探究数据间的关系，需要进行一定的计算。&lt;/li&gt;
  &lt;li&gt;相关性热力图。如果是一个数据与另一个时间序列进行搭配，则这个图可以很好地看出变化趋势。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;img alt="" height="364" src="https://www.biaodianfu.com/wp-content/uploads/2023/04/cross.jpg" width="480"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;对于连续变量与连续变量之间的关系，可以通过散点图进行查看。对于多个连续变量，可使用散点图矩阵，相关系数矩阵，热图。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="140" src="https://www.biaodianfu.com/wp-content/uploads/2023/04/data-3.png" width="700"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;量化指标：皮尔逊相关系数（线性关系），互信息（非线性关系）&lt;/p&gt;
 &lt;h4&gt;2）离散变量和离散变量关系&lt;/h4&gt;
 &lt;p&gt;对于离散变量与离散变量之间的关系，可以通过交叉分组表（crosstab），复合柱形图，堆积柱形图，饼图进行查看。对于多个离散变量，可以使用网状图，通过各个要素之间是否有线条，以及线条的粗线来显示是否有关系以及关系的强弱。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="179" src="https://www.biaodianfu.com/wp-content/uploads/2023/04/data-4.png" width="1000"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;量化指标：卡方独立性检验—&amp;gt;Cramer’s φ (Phi) or Cramer’s V&lt;/p&gt;
 &lt;h4&gt;3）离散变量和连续变量关系&lt;/h4&gt;
 &lt;p&gt;对于离散变量和连续变量之间的关系，可以使用直方图，箱线图，小提琴图进行查看，将离散变量在图形中用不同的颜色显示，来直观地观察变量之间的关系。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="254" src="https://www.biaodianfu.com/wp-content/uploads/2023/04/data-5.png" width="780"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;量化指标：独立样本t检验中的t统计量和相应的p值（两个变量），单因素方差分析中的η²（三个变量及以上）&lt;/p&gt;
 &lt;h4&gt;4） 其他&lt;/h4&gt;
 &lt;p&gt;检查数据的正态性：直方图，箱线图，Q-Q图（Quantile-Quantile Plot ）&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;直方图，箱线图：看图形是否对称&lt;/li&gt;
  &lt;li&gt;Q-Q图：比较数据的分位数与某个理论分布的分位数是否匹配&lt;/li&gt;
&lt;/ul&gt;
 &lt;h2&gt;探索性数据分析的的产出&lt;/h2&gt;
 &lt;p&gt;根据EDA我们可以得出以下结论：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;变量是否需要筛选、替换和清洗&lt;/li&gt;
  &lt;li&gt;变量是否需要转换&lt;/li&gt;
  &lt;li&gt;变量之间是否需要交叉&lt;/li&gt;
  &lt;li&gt;变量是否需要采样&lt;/li&gt;
&lt;/ul&gt;
 &lt;h2&gt;探索性数据分析的辅助工具&lt;/h2&gt;
 &lt;ul&gt;
  &lt;li&gt;DataPrep&lt;/li&gt;
  &lt;li&gt;Pandas Profiling&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://github.com/fbdesignpro/sweetviz"&gt;Sweetviz&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://github.com/AutoViML/AutoViz"&gt;AutoViz&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://klib.readthedocs.io/en/latest/"&gt;Klib&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://amueller.github.io/dabl/dev/"&gt;Dabl&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://github.com/Speedml/speedml"&gt;SpeedML&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;参考链接：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;a href="https://towardsdatascience.com/exploratory-data-analysis-in-python-a-step-by-step-process-d0dfa6bf94ee"&gt;Exploratory Data Analysis in Python — A Step-by-Step Process&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://medium.com/epfl-extension-school/advanced-exploratory-data-analysis-eda-with-python-536fa83c578a"&gt;Advanced exploratory data analysis (EDA) with Python&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="https://medium.com/geekculture/10-automated-eda-libraries-at-one-place-ea5d4c162bbb"&gt;10 automated EDA libraries in one place | by Satyam Kumar | Geek Culture | Medium&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;其他参考：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" height="579" src="https://www.biaodianfu.com/wp-content/uploads/2023/04/data-plot.jpg" width="894"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;div&gt;
  &lt;h3&gt;相关文章:&lt;/h3&gt;  &lt;ol&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/dataprep-eda.html" rel="bookmark" title="&amp;#25968;&amp;#25454;&amp;#25506;&amp;#32034;&amp;#24037;&amp;#20855;Dataprep.eda"&gt;数据探索工具Dataprep.eda &lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/elasticsearch-install-chinese-segmenter-plugin.html" rel="bookmark" title="Elasticsearch&amp;#20013;&amp;#25991;&amp;#20998;&amp;#35789;&amp;#25554;&amp;#20214;&amp;#23433;&amp;#35013;"&gt;Elasticsearch中文分词插件安装 &lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;    &lt;a href="https://www.biaodianfu.com/survival-analysis.html" rel="bookmark" title="&amp;#29983;&amp;#23384;&amp;#20998;&amp;#26512;&amp;#20174;&amp;#27010;&amp;#24565;&amp;#21040;&amp;#23454;&amp;#25112;"&gt;生存分析从概念到实战 &lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>数据 术→技巧 数据分析</category>
      <guid isPermaLink="true">https://itindex.net/detail/62737-%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90</guid>
      <pubDate>Tue, 18 Apr 2023 22:54:59 CST</pubDate>
    </item>
    <item>
      <title>ChatGPT要把数据标注行业干掉了？比人便宜20倍，而且还更准</title>
      <link>https://itindex.net/detail/62715-chatgpt-%E6%95%B0%E6%8D%AE-%E8%A1%8C%E4%B8%9A</link>
      <description>&lt;section data-darkmode-bgcolor-16095509242984="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16095509242984="rgb(255, 255, 255)" data-mpa-powered-by="yiban.io" data-style='white-space: normal; max-width: 100%; letter-spacing: 0.544px; text-size-adjust: auto; background-color: rgb(255, 255, 255); font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif; box-sizing: border-box !important; overflow-wrap: break-word !important;'&gt;&lt;section data-darkmode-bgcolor-16095509242984="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16095509242984="rgb(255, 255, 255)"&gt;&lt;section data-darkmode-bgcolor-16095509242984="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16095509242984="rgb(255, 255, 255)"&gt;&lt;section data-color="rgb(117, 117, 118)" data-custom="rgb(117, 117, 118)" data-darkmode-bgcolor-16095509242984="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16095509242984="rgb(255, 255, 255)" data-id="85660"&gt;&lt;section data-darkmode-bgcolor-16095509242984="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16095509242984="rgb(255, 255, 255)"&gt;&lt;section data-darkmode-bgcolor-16095509242984="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16095509242984="rgb(255, 255, 255)"&gt;&lt;section data-darkmode-bgcolor-16095509242984="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16095509242984="rgb(255, 255, 255)"&gt;&lt;section data-darkmode-bgcolor-16095509242984="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16095509242984="rgb(255, 255, 255)"&gt;&lt;section data-darkmode-bgcolor-16095509242984="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16095509242984="rgb(255, 255, 255)"&gt;&lt;section data-color="rgb(117, 117, 118)" data-custom="rgb(117, 117, 118)" data-darkmode-bgcolor-16095509242984="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16095509242984="rgb(255, 255, 255)" data-id="85660"&gt;&lt;section data-darkmode-bgcolor-16095509242984="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16095509242984="rgb(255, 255, 255)" data-style="margin-top: 2em; padding-top: 0.5em; padding-bottom: 0.5em; max-width: 100%; border-style: solid none; text-decoration: inherit; border-top-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-top-width: 1px; border-bottom-width: 1px; box-sizing: border-box !important; overflow-wrap: break-word !important;"&gt;&lt;section&gt;没想到，AI 进化之后淘汰掉的第一批人，就是帮 AI 训练的人。&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;很多 NLP 应用程序需要为各种任务手动进行大量数据注释，特别是训练分类器或评估无监督模型的性能。根据规模和复杂程度，这些任务可能由众包工作者在 MTurk 等平台上以及训练有素的标注人（如研究助理）执行。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;我们知道，语言大模型（LLM）在规模到达一定程度之后可以「涌现」&amp;mdash;&amp;mdash; 即获得此前无法预料的新能力。作为推动 AI 新一轮爆发的大模型，ChatGPT 在很多任务上的能力也超出了人们的预期，其中就包括给数据集做标注这种自己训练自己的工作。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;近日，来自苏黎世大学的研究者证明了 ChatGPT 在多项注释任务（包括相关性、立场、主题和框架检测）上优于众包工作平台和人类工作助理。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;此外，研究人员还做了计算：ChatGPT 的每条注释成本不到 0.003 美元 &amp;mdash;&amp;mdash; 大约比 MTurk 便宜 20 倍。这些结果显示了大型&lt;mark data-type=tech_tasks data-id=bf35ef94-d956-4033-a533-0c0828308c36&gt;语言模型&lt;/mark&gt;在大幅提高&lt;mark data-type=tech_tasks data-id=3fe4290f-6dd3-43ed-9324-cf23aa588830&gt;文本分类&lt;/mark&gt;效率方面的潜力。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;img data-ratio="0.3756727664155005" src="https://image.jiqizhixin.com/uploads/editor/0de17eff-0b66-44a1-b296-01e360597930/640.png" data-type="png" data-w="929" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;论文链接：https://arxiv.org/abs/2303.15056&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;strong&gt;研究细节&lt;/strong&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;许多 NLP 应用程序需要高质量的标注数据，特别是用于训练分类器或评估无监督模型的性能。例如，研究人员有时需要过滤嘈杂的社交媒体数据以获得相关性，将文本分配给不同的主题或概念类别，或者衡量他们的情绪立场。无论用于这些任务的具体方法是什么（监督、半监督或无&lt;mark data-type=tech_methods data-id=94fdbfed-9ebb-491b-b54e-9c2aae512f70&gt;监督学习&lt;/mark&gt;），都需要准确地标注数据来构建训练集，或用其作为评估性能的黄金标准。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;对此，人们通常的处理方式是招募研究助理，或者使用 MTurk 这样的众包平台。OpenAI 在打造 ChatGPT 时，也将负面内容问题&lt;a data-linktype="2" href="https://mp.weixin.qq.com/s?__biz=MzA3MzI4MjgzMw==&amp;mid=2650866707&amp;idx=2&amp;sn=2b5be590da7e521e3c3519ddf1c1d5fd&amp;scene=21#wechat_redirect" target="_blank"&gt;分包给了肯尼亚的数据标注机构&lt;/a&gt;，进行了大量标注训练才敢正式上线。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;由瑞士苏黎世大学提交的这篇报告探讨了大&lt;mark data-type=tech_tasks data-id=bf35ef94-d956-4033-a533-0c0828308c36&gt;语言模型&lt;/mark&gt;（LLM）在文本标注任务中的潜力，并重点关注了 2022 年 11 月发布的 ChatGPT。它证明了零样本（即没有任何额外训练）ChatGPT 在分类任务上优于 MTurk 标注 ，而成本仅需人工的几十分之一。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;研究人员使用了之前的研究收集的 2382 条推文样本。这些推文由训练有素的注释者（研究助理）标记为五种不同的任务：相关性、立场、主题和两种框架检测。实验中，研究者将任务作为零样本分类提交给 ChatGPT，并同时给 MTurk 上的众包工作者，然后根据两个&lt;mark data-type=concepts data-id=308c3a45-0fee-4ec6-858e-85b15f440fc0&gt;基准&lt;/mark&gt;评估了 ChatGPT 的性能：相对于众包平台上人类工作者的准确性，以及相对于研究助理注释者的准确性。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;结果发现，在五分之四的任务上，ChatGPT 的零样本&lt;mark data-type=concepts data-id=8be77eae-12da-4e9e-9a88-b7f5bae98c2e&gt;准确率&lt;/mark&gt;高于 MTurk。对于所有任务，ChatGPT 的编码器协议都超过了 MTurk 和训练有素的注释者。此外在成本上，ChatGPT 比 MTurk 便宜得多：五个分类任务在 ChatGPT（25264 个注释）上的成本约为 68 美元，在 MTurk（12632 个注释）上的成本约为 657 美元。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;这么一算，ChatGPT 的每条注释成本约为 0.003 美元，即三分之一美分 &amp;mdash;&amp;mdash; 比 MTurk 便宜约 20 倍，而且质量更高。鉴于此，我们现在已有可能对更多样本进行注释，或者为&lt;mark data-type=tech_methods data-id=94fdbfed-9ebb-491b-b54e-9c2aae512f70&gt;监督学习&lt;/mark&gt;创建大型训练集。根据现有的测试，10 万个注释的成本约为 300 美元。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;研究人员表示，虽然需要进一步研究以更好地了解 ChatGPT 和其他 LLM 如何在更广泛的环境中发挥作用，但这些结果表明它们有可能改变研究人员进行数据注释的方式，并破坏 MTurk 等平台的部分业务模型。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;strong&gt;实验过程&lt;/strong&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;研究人员使用了包含 2382 条推文的数据集，这些推文是之前针对内容审核相关任务的研究手动注释的。具体来说，训练有素的注释者（研究助理）为五个具有不同类别数量的概念类别构建了黄金标准：推文与内容审核问题的相关性（相关 / 不相关）；关于第 230 条（美国 1996 年《通信规范法》的一部分）的立场，这是美国互联网立法的一个关键部分；主题识别（六类）；第一组框架（内容审核作为问题、解决方案或中性）；以及第二组框架（十四类）。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;然后，研究人员使用 ChatGPT 和在 MTurk 上招募的众包工作者进行了这些完全相同的分类。对于 ChatGPT 进行了四组标注。为了探索控制输出随机程度的 ChatGPT 温度&lt;mark data-type=concepts data-id=2e982b73-88e2-41e8-a430-f7ae5a9af4bf&gt;参数&lt;/mark&gt;的影响，这里使用默认值 1 和 0.2 进行注释，这意味着随机性较小。对于每个温度值，研究人员进行了两组注释来计算 ChatGPT 的编码器协议。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;对于专家，该研究找到了两名政治学研究生，对所有五项任务对推文进行注释。对于每项任务，编码员都获得了相同指令集，其被要求逐个任务独立地注释推文。为了计算 ChatGPT 和 MTurk 的准确性，对比只考虑了两个训练有素的注释者都同意的推文。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;对于 MTurk，研究的目标是选择最好的工作者群体，特别是通过筛选被亚马逊归类为「MTurk 大师」、好评超过 90% 且在美国的工作者。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;该研究使用「gpt-3.5-turbo」版本的 ChatGPT API 对推文进行分类。注释于 2023 年 3 月 9 日至 3 月 20 日之间进行。对于每个注释任务，研究人员有意避免添加任何特定于 ChatGPT 的提示（prompt），例如「让我们逐步思考」，以确保 ChatGPT 和 MTurk 众包工作者之间的可比性。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;在测试了几种变体之后，人们决定使用这样的提示将推文一条一条地提供给 ChatGPT：「这是我选择的推文，请将其标记为 [任务特定说明（例如，说明中的主题之一）]。此外，该研究中每条推文收集了四个 ChatGPT 响应，也为每条推文创建一个新的聊天会话，以确保 ChatGPT 结果不受注释历史记录的影响。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;img data-ratio="0.4287037037037037" src="https://image.jiqizhixin.com/uploads/editor/d3a76953-55f2-40a8-a179-757a06f5f10e/640.png" data-type="png" data-w="1080" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/section&gt;&lt;section&gt;&lt;em&gt;图 1. 与 MTurk 上高分标注人相比，ChatGPT zero-shot 的文本标注能力。ChatGPT 在五项任务中的四项中的准确性优于 MTurk。&lt;/em&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;在上图中 ChatGPT 有优势的四项任务中，在一种情况下（相关性）ChatGPT 略有优势，但其性能与 MTurk 非常相似。其他三种情况下（frams I、frams II 和 Stance），ChatGPT 的性能比 MTurk 高 2.2 到 3.4 倍。此外，考虑到任务的难度、类的数量以及注释是零样本的事实，ChatGPT 的准确度总体来说绰绰有余。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;对于相关性，有两个类别（相关 / 不相关），ChatGPT 的&lt;mark data-type=concepts data-id=8be77eae-12da-4e9e-9a88-b7f5bae98c2e&gt;准确率&lt;/mark&gt;为 72.8%，而对于立场，有三个类别（正面 / 负面 / 中性）的&lt;mark data-type=concepts data-id=8be77eae-12da-4e9e-9a88-b7f5bae98c2e&gt;准确率&lt;/mark&gt;为 78.7%。随着类别数量的增加，准确性会降低，尽管任务的内在难度也有影响。关于编码器协议，图 1 显示 ChatGPT 的性能非常高，当温度&lt;mark data-type=concepts data-id=2e982b73-88e2-41e8-a430-f7ae5a9af4bf&gt;参数&lt;/mark&gt;设置为 0.2 时，所有任务的性能都超过 95%。这些值高于任何人类，包括训练有素的注释者。即使使用默认温度值 1（这意味着更多的随机性），编码器间一致性始终超过 84%。编码器间一致性和准确性之间的关系是正的，但很弱（皮尔逊相关系数：0.17）。尽管相关性仅基于五个数据点，但它表明较低的温度值可能更适合注释任务，因为它似乎可以提高结果的一致性而不会大幅降低准确性。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;必须强调的是，对 ChatGPT 进行测试非常困难。内容审核是一个复杂的主题，需要大量资源。除了立场之外，研究人员还为特定研究目的开发了概念类别。此外，一些任务涉及大量类别，然而 ChatGPT 仍然达到了很高的&lt;mark data-type=concepts data-id=8be77eae-12da-4e9e-9a88-b7f5bae98c2e&gt;准确率&lt;/mark&gt;。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;使用模型来注释数据并不是什么新鲜事，在使用大规模数据集的计算机科学研究中，人们经常会标注少量样本然后用&lt;mark data-type=tech_methods data-id=1a0e9c5e-6502-4cd7-8683-6b5ca6c48be2&gt;机器学习&lt;/mark&gt;进行扩增。不过在表现超过人类之后，未来我们或许可以更加信任来自 ChatGPT 的判断了。&lt;/section&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62715-chatgpt-%E6%95%B0%E6%8D%AE-%E8%A1%8C%E4%B8%9A</guid>
      <pubDate>Sat, 01 Apr 2023 10:36:29 CST</pubDate>
    </item>
    <item>
      <title>【干货】你还在为分布式系统数据一致性而烦恼吗，来来来！！！</title>
      <link>https://itindex.net/detail/62708-%E5%B9%B2%E8%B4%A7-%E5%88%86%E5%B8%83-%E7%B3%BB%E7%BB%9F</link>
      <description>&lt;p&gt;觉得不错请按下图操作，掘友们，哈哈哈！！！
  &lt;img alt="image.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d19d1e322c984fa5b0653caed8683d71~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h1&gt;概述&lt;/h1&gt;
 &lt;p&gt;博主最近在做分布式事务这块业务，所以在选型的过程中，对比了当下比较流行的解决方案，在这里坐下记录，欢迎jym提出更好的方案哦。&lt;/p&gt;
 &lt;h1&gt;一：分布式消息怎么保证数据的最终一致性：&lt;/h1&gt;
 &lt;h2&gt;1.1 添加消息中间表方案：&lt;/h2&gt;
 &lt;p&gt;为了保证原子性，我们可以变通一下，添加一个消息表，A不直接往消息中间件中发消息，而是把消息写入消息表，然后通过一个后台程序不断的把消息写入消息中间件。比如转账流程，如下图：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="&amp;#20998;&amp;#24067;&amp;#24335;&amp;#28040;&amp;#24687;&amp;#26368;&amp;#32456;&amp;#19968;&amp;#33268;&amp;#24615;1.png" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/155e09a49a4e4e41a2dfc2e485b83ab1~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;这个后台应用会把消息表中的数据发送到消息中间件中，当然这里边我们要有一个字段标识出消息的状态，然后提供接口给消息中间件回调（ACK）来知道消息是否发送成功，如果失败就重试，可以保证：消息不会丢失顺序不乱但会有消息重复的情况，因为消息发送失败可能是写入失败，也可能是写入成功但响应失败，所以消息可能会重复，这个问题需要系统   &lt;strong&gt;B来处理。&lt;/strong&gt;&lt;/p&gt;
 &lt;h2&gt;1.2 那么系统B要考虑那些问题呢：&lt;/h2&gt;
 &lt;h3&gt;1.2.1 消息丢失&lt;/h3&gt;
 &lt;p&gt;系统B从消息中间件中拿到消息，还没处理完就宕机了，这条消息怎么办？
需要通过   &lt;strong&gt;ACK机制处理，消费成功的发送ACK，对于没有ACK的消息，消息中间件会再次推送&lt;/strong&gt;。&lt;/p&gt;
 &lt;h3&gt;1.2.2 消息重复：&lt;/h3&gt;
 &lt;p&gt;即使有ACK机制也存在消息重复的情况，比如B已经处理完一条消息，发ACK时失败了，那么这条消息就还会被推过来。还有就是上面说的后台程序发消息时可能重复。对于重复消息问题，可以加一个判重操作，记录处理成功的消息，每次收到消息时，先通过判重操作判断一下，如果重复了就不处理，实现幂等性。&lt;/p&gt;
 &lt;p&gt;判重操作 可以放一张表里，也可以放到redis里，存储一定时间，在相应时间里如果有重复消息进来，就认为消息重复，但是也要来考虑业务，比如订单有好多操作，可能要加各种场景的校验，为而不是简单的以订单号来判断重复，具体要细到什么维度就要看自己实际的真实业务来设定了。改造后流程图如下：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="&amp;#28040;&amp;#24687;&amp;#21028;&amp;#37325;1.png" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/31cf4653387348a083521084d118d5e5~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h1&gt;二：分布式事务保证数据一致性&lt;/h1&gt;
 &lt;p&gt;常见分布式事务有 2PC、3PC、TCC、Saga、本地事务表、MQ事务消息、最大努力通知，我们这里重点介绍下主流的TCC和最大努力通知这两个&lt;/p&gt;
 &lt;h2&gt;2.1  TCC&lt;/h2&gt;
 &lt;p&gt;如果要用TCC 分布式事务的话：首先需要选择某种 TCC 分布式事务框架，各个服务里就会有这个 TCC 分布式事务框架在运行。&lt;/p&gt;
 &lt;blockquote&gt;
  &lt;ul&gt;
   &lt;li&gt;所以你原本的一个接口，要改造为 3 个逻辑，Try-Confirm-Cancel：先是服务调用链路依次执行 Try 逻辑。如果都正常的话，TCC 分布式事务框架推进执行 Confirm 逻辑，完成整个事务。如果某个服务的 Try 逻辑有问题，TCC 分布式事务框架感知到之后就会推进执行各个服务的 Cancel 逻辑，撤销之前执行的各种操作这就是所谓的CC 分布式事务。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
 &lt;blockquote&gt;
  &lt;ul&gt;
   &lt;li&gt;TCC 分布式事务的核心思想大白话的来说就是当遇到下面这些情况时：某个服务的数据库宕机了；某个服务自己挂了；那个服务的 Redis、Elasticsearch、MQ 等基础设施故障了。某些资源不足了，比如说库存或者限购不够这些。先来 Try 试一下，不要把业务逻辑完成，先试试看，看各个服务能不能基本正常运转，能不能先冻结我需要的资源。如果 说Try的过程都 OK，也就是说，底层的数据库、Redis、Elasticsearch、MQ 都是可以写入数据的，并且你保留好了需要使用的一些资源（比如冻结了一部分库存或者限购）。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
 &lt;blockquote&gt;
  &lt;ul&gt;
   &lt;li&gt;接着，再执行各个服务的 Confirm 逻辑，基本上 Confirm 就可以很大概率保证一个分布式事务的完成了。那如果 Try 阶段某个服务就失败了，比如说底层的数据库挂了，或者 Redis 挂了，等等。
此时就自动执行各个服务的 Cancel 逻辑，把之前的 Try 逻辑都回滚，所有服务都不要执行任何设计的业务逻辑。保证大家要么一起成功，要么一起失败。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
 &lt;blockquote&gt;
  &lt;ul&gt;
   &lt;li&gt;这里还有一个问题？如果有一些意外的情况发生了，比如说下单服务突然挂了，然后再次重启，    &lt;strong&gt;TCC 分布式事务框架是如何保证之前没执行完的分布式事务继续执行的呢？&lt;/strong&gt; 所以，TCC 事务框架都是要记录一些分布式事务的活动日志的，可以在磁盘上的日志文件里记录，也可以在数据库里记录。保存下来分布式事务运行的各个阶段和状态。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
 &lt;blockquote&gt;
  &lt;ul&gt;
   &lt;li&gt;另外一个问题，万一某个服务的 Cancel 或者 Confirm 逻辑执行一直失败怎么办呢？那也很简单，TCC 事务框架会通过活动日志记录各个服务的状态。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
 &lt;blockquote&gt;
  &lt;ul&gt;
   &lt;li&gt;就比如下边例子，比如发现某个服务的 Cancel 或者 Confirm 一直没成功，会不停的重试调用它的 Cancel 或者 Confirm 逻辑，务必要它成功！如果是有相应bug，那无限重试也是不行的，这时候我们就要添加相应报警，然后就要人工介入了。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
 &lt;p&gt;  &lt;strong&gt;TCC- Try confirm 阶段 正常情况：&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="Try-Confirm1.png" src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f5e587aaabb347a8b8d58d4ca291c4a1~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;TCC- Try cancel 阶段，异常情况&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="Try-Cannel1.png" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ee4f80715e6143f68bdcfdab8d762e85~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h2&gt;2.2 TCC如何保证最终一致性&lt;/h2&gt;
 &lt;ul&gt;
  &lt;li&gt;TCC 事务机制最重要的还是Try，Confirm 确认操作和 Cancel 取消操作都是围绕 Try 而展开的。因此，Try中的操作其保障性是最好的，即使失败了，仍然有 Cancel 取消操作将已经执行的操作撤销。&lt;/li&gt;
  &lt;li&gt;Try阶段执行成功并开始执行 Confirm 阶段时，一致认为 Confirm 阶段是不会出错的，也就是说只要 Try 成功，Confirm 一定成功，这是设计之初的定义。&lt;/li&gt;
  &lt;li&gt;Confirm 与 Cancel 如果失败，由TCC框架进行重试补偿 存在极低概率在Confirm和Cancel 环节彻底失败，则需要上边说的报警和人为介入了。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h2&gt;2.3 TCC的要注意的事项&lt;/h2&gt;
 &lt;blockquote&gt;
  &lt;p&gt;   &lt;strong&gt;允许空回滚&lt;/strong&gt; ：什么是空回滚，比如 Try 超时或者丢包，导致 TCC 分布式事务二阶段的回滚触发 Cancel 操作，此时事务参与者未收到Try，但是却收到了Cancel 请求。也就是由于网络原因，下游服务没有收到Try 操作，后续比如网络正常后 收到了Cancel请求了。&lt;/p&gt;
  &lt;p&gt;   &lt;strong&gt;做好幂等&lt;/strong&gt; ：由于网络原因或者重试操作都有可能导致 Try ，Confirm ， Cancel 3个操作重复执行，所以在使用 TCC 时要考虑到这三个操作相应的幂等控制，通常我们可以使用事务 xid 或业务主键判重来控制，避免影响业务。&lt;/p&gt;
&lt;/blockquote&gt;
 &lt;h2&gt;2.4  TCC方案的优缺点&lt;/h2&gt;
 &lt;p&gt;优点：&lt;/p&gt;
 &lt;blockquote&gt;
  &lt;ul&gt;
   &lt;li&gt;性能提升：由业务来实现，资源的控制粒度变小，不会锁定整个资源。&lt;/li&gt;
   &lt;li&gt;保证了数据最终一致性：基于 Confirm 和 Cancel 的幂等性，保证事务最终完成确认或者取消，保证数据的一致性。&lt;/li&gt;
   &lt;li&gt;可靠性：由主业务方发起并控制整个业务活动，业务活动管理器也变成多点，引入集群概念。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
 &lt;p&gt;缺点：&lt;/p&gt;
 &lt;blockquote&gt;
  &lt;p&gt;TCC 中 Try、Confirm 和 Cancel 操作功都是基于业务来实现，业务耦合度较高，提高了开发成本。&lt;/p&gt;
&lt;/blockquote&gt;
 &lt;h1&gt;三：基于本地消息的最终一致性：&lt;/h1&gt;
 &lt;h2&gt;3.1 解释：&lt;/h2&gt;
 &lt;p&gt;本地消息表的核心思想就是将分布式事务拆成本地事物来处理，在方案执行中束腰有两种角色：事务发起方和事务被动接收方。事务主动发起方需要额外新建事务消息储存表，并在本地事务中完成业务处理和记录事务消息，并轮询事务消息表的数据发送事务消息，事务被动接收方则是基于消息中间件消费事务消息表中的事务，处理自己的业务。&lt;/p&gt;
 &lt;p&gt;这样可以避免以下两种情况导致的数据不一致性：&lt;/p&gt;
 &lt;p&gt;业务处理成功、事务消息发送失败
业务处理失败、事务消息发送成功&lt;/p&gt;
 &lt;h2&gt;3.2 简化流程图&lt;/h2&gt;
 &lt;p&gt;  &lt;img alt="&amp;#26368;&amp;#32456;&amp;#28040;&amp;#24687;&amp;#19968;&amp;#33268;&amp;#24615;&amp;#31616;&amp;#21270;1.png" src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f6b81944b3c24037a910b0ad25f5b9dd~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;blockquote&gt;
  &lt;ul&gt;
   &lt;li&gt;1 事务发起方在同一个本地事务中处理业务和写消息表操作&lt;/li&gt;
   &lt;li&gt;2 事务发起方通过消息中间件，通知事务被动方处理事务消息。消息中间件可以基于 Kafka、RocketMQ 等消息队列，事务主动方主动写消息到消息队列，事务消费方消费并处理消息队列中的消息。&lt;/li&gt;
   &lt;li&gt;3 事务接收方通过消息中间件，通知事务主动方事务已处理的消息。&lt;/li&gt;
   &lt;li&gt;4 事务接收方接收中间件的消息，更新消息表的状态为已处理。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
 &lt;p&gt;一些必不可少的容错机制如下：&lt;/p&gt;
 &lt;blockquote&gt;
  &lt;ul&gt;
   &lt;li&gt;当1 步骤处理出错，由于还在事务主动方的本地事务中，直接回滚即可。&lt;/li&gt;
   &lt;li&gt;当2，3 步骤 处理出错，由于事务主动发起方本地保存了消息，只需要轮询消息重新通过消息中间件发送，通知事务被动方重新读取消息处理业务即可。&lt;/li&gt;
   &lt;li&gt;如果是业务上处理失败，事务被动接收方可以发消息给事务主动方回滚事务。&lt;/li&gt;
   &lt;li&gt;如果事务被动接收方已经消费了消息，事务主动发起方需要回滚事务的话，需要发消息通知事务主动发起方进行回滚事务。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
 &lt;p&gt;  &lt;strong&gt;本地消息表的优缺点：&lt;/strong&gt;&lt;/p&gt;
 &lt;blockquote&gt;
  &lt;p&gt;优点：&lt;/p&gt;
  &lt;ul&gt;
   &lt;li&gt;从业务设计的角度实现了消息数据的可靠性，消息数据的可靠性不依赖于消息中间件，弱化了对 MQ 的依赖。&lt;/li&gt;
   &lt;li&gt;方案比较轻量，容易实现。&lt;/li&gt;
&lt;/ul&gt;
  &lt;p&gt;缺点：&lt;/p&gt;
  &lt;ul&gt;
   &lt;li&gt;耦合了具体场景的业务，不可公用&lt;/li&gt;
   &lt;li&gt;消息数据与业务数据同库，业务数据量大的时候会有影响&lt;/li&gt;
   &lt;li&gt;业务系统在使用关系型数据库的情况下，消息服务性能会受到关系型数据库并发性能的局限&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
 &lt;p&gt;这个版本相对比较简陋，只是大体的显现出来了轮廓，下图是改进版本。&lt;/p&gt;
 &lt;h2&gt;3.3 本地消息一致性升级版本&lt;/h2&gt;
 &lt;p&gt;  &lt;img alt="&amp;#26412;&amp;#22320;&amp;#28040;&amp;#24687;&amp;#26368;&amp;#32456;&amp;#19968;&amp;#33268;&amp;#24615;&amp;#26041;&amp;#26696;1.png" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9891a5bb06db4cfeaa18feb21a57acfc~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;blockquote&gt;
  &lt;ul&gt;
   &lt;li&gt;基于本地消息的最终一致性方案的最核心做法就是在执行业务操作的时候，    &lt;strong&gt;记录一条消息数据到DB，而且消息数据的记录一定要和业务数据的记录在同一个事务内完成，这是该方案的前提核心保障&lt;/strong&gt;。&lt;/li&gt;
   &lt;li&gt;在记录完成后消息数据后，我们就可以通过一个定时任务到DB中去轮询状态为待发送的消息，然后将消息投递给MQ。&lt;/li&gt;
   &lt;li&gt;这个过程中可能存在消息投递失败的可能，此时就依靠重试机制来保证，直到成功收到MQ的ACK确认之后，再将消息状态更新或者消息清除；&lt;/li&gt;
   &lt;li&gt;而后面消息的消费失败的话，则依赖MQ本身的重试来完成，其最后做到两边系统数据的最终一致性。基于本地消息服务的方案虽然可以做到消息的最终一致性，但是它有一个比较严重的弊端，每个业务系统在使用该方案时，都需要在对应的业务库创建一张消息表来存储消息。针对这个问题，我们可以将该功能单独提取出来，做成一个消息服务来统一处理，因而就衍生出了我们下面将要讨论的方案。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
 &lt;h1&gt;四：独立消息服务的最终一致性&lt;/h1&gt;
 &lt;p&gt;  &lt;img alt="&amp;#29420;&amp;#31435;&amp;#26381;&amp;#21153;&amp;#30340;&amp;#26368;&amp;#32456;&amp;#19968;&amp;#33268;&amp;#24615;1.png" src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3f1061ac2aea4de6a0ddeb206454ce4d~tplv-k3u1fbpfcp-watermark.image?"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;blockquote&gt;
  &lt;ul&gt;
   &lt;li&gt;
    &lt;ol&gt;
     &lt;li&gt;事务主动方在执行业务前预发消息&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
   &lt;li&gt;
    &lt;ol start="2"&gt;
     &lt;li&gt;事务发起方 ，执行相应业务&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
   &lt;li&gt;
    &lt;ol start="3"&gt;
     &lt;li&gt;消息服务系统接受到消息存储，并且将消息状态置为 “待发送状态”&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
   &lt;li&gt;
    &lt;ol start="4"&gt;
     &lt;li&gt;事务主动方主动发送业务处理结果，或者消息服务系统定时去轮询事务发起方业务处理结果&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
   &lt;li&gt;
    &lt;ol start="5"&gt;
     &lt;li&gt;得到事务发起方业务处理结果&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
   &lt;li&gt;
    &lt;ol start="6"&gt;
     &lt;li&gt;发送消息到MQ&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
   &lt;li&gt;
    &lt;ol start="7"&gt;
     &lt;li&gt;MQ消息持久化防止丢失&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
   &lt;li&gt;
    &lt;ol start="8"&gt;
     &lt;li&gt;确认消息被投递到MQ，得到ACK信息&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
   &lt;li&gt;
    &lt;ol start="9"&gt;
     &lt;li&gt;事务接收方得到投递的消息&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
   &lt;li&gt;
    &lt;ol start="10"&gt;
     &lt;li&gt;事务接收放得到投递的消息执行相应业务&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
   &lt;li&gt;
    &lt;ol start="11"&gt;
     &lt;li&gt;执行完后返回ACK信息&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
 &lt;ul&gt;
  &lt;li&gt;独立消息服务最终一致性与本地消息服务最终一致性最大的差异就在于将消息的存储单独地做成了一个RPC的服务；&lt;/li&gt;
  &lt;li&gt;这个过程其实就是模拟了事务消息的消息预发送过程，如果预发送消息失败，那么生产者业务就不会去执行业务，因此对于生产者的业务而言，它是强依赖于该消息服务的。&lt;/li&gt;
  &lt;li&gt;不过要保证好独立消息服务高可用则要做成HA的集群模式，就能够保证其可靠性。在消息服务中，还有一个单独地定时任务，它会定期轮训长时间处于待发送状态的消息，通过一个check补偿机制来确认该消息对应的业务是否成功，如果对应的业务处理成功，则将消息修改为可发送，然后将其投递给MQ；如果业务处理失败，则将对应的消息更新或者删除即可。&lt;/li&gt;
  &lt;li&gt;因此在使用该方案过程中，事务发起方必须同时实现一个check服务，来供消息服务做消息的确认。对于消息的消费，该方案与上面的处理是一样，都是通过MQ自身的重发机制来保证消息被消费。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h1&gt;五：总要有总结&lt;/h1&gt;
 &lt;p&gt;使用场景：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;
   &lt;p&gt;TCC：适用于执行时间确定且较短，实时性要求高，对数据一致性要求高，比如互联网金融企业最核心的三个服务：交易、支付、账务。&lt;/p&gt;
&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;本地消息表/MQ 事务：适用于事务中参与方支持操作幂等，对一致性要求不高，业务上能容忍数据不一致到一个人工检查周期，事务涉及的参与方、参与环节较少，业务上有对账/校验系统兜底。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;本章讲述了常见分布式系统数据一致性方案，从数据库，到MQ，从TCC 到 本地消息最终一致性方案，再到 独立消息服务最终一致性，系统复杂性也随之增强，但是业务得到了解耦专注于某一块业务。但是实际应用中要根据自己系统的真实情况去选用方案，才能做到因地制宜，得到相对比较好的结果。&lt;/p&gt;
 &lt;p&gt;  &lt;em&gt;   &lt;strong&gt;本文正在参加    &lt;a href="https://juejin.cn/post/7207698564641996856/" title="https://juejin.cn/post/7207698564641996856/"&gt;「金石计划」&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62708-%E5%B9%B2%E8%B4%A7-%E5%88%86%E5%B8%83-%E7%B3%BB%E7%BB%9F</guid>
      <pubDate>Fri, 17 Mar 2023 18:22:21 CST</pubDate>
    </item>
    <item>
      <title>火山引擎DataLeap：一家企业，数据体系要怎么搭建？</title>
      <link>https://itindex.net/detail/62681-%E7%81%AB%E5%B1%B1-%E5%BC%95%E6%93%8E-dataleap</link>
      <description>&lt;blockquote&gt;
  &lt;p&gt;   &lt;strong&gt;导读：经过十多年的发展，&lt;/strong&gt;    &lt;strong&gt;数据治理&lt;/strong&gt;    &lt;strong&gt;在传统行业以及新兴互联网公司都已经产生落地实践。字节跳动也在探索一种分布式的数据治理方式。本篇内容来源于&lt;/strong&gt;    &lt;strong&gt;火山引擎&lt;/strong&gt;    &lt;strong&gt;超话数据直播活动的回顾，将从以下四个部分展开分享：&lt;/strong&gt;&lt;/p&gt;
  &lt;ul&gt;
   &lt;li&gt;字节的挑战与实践&lt;/li&gt;
   &lt;li&gt;数据治理的发展与分布式&lt;/li&gt;
   &lt;li&gt;分布式自治架构&lt;/li&gt;
   &lt;li&gt;分布式自治核心能力&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
 &lt;h1&gt;字节的挑战与实践&lt;/h1&gt;
 &lt;p&gt;首先来看一个问题：“一家公司，数据体系要怎么搭建？”&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;方案一：    &lt;strong&gt;整体规划，系统架构驱动&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;方案二：   &lt;strong&gt;问题出发，业务价值驱动&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;在字节跳动，我们选择的是方案二，即从业务遇到的问题出发，重视落地结果与业务过程，去解决实际的治理问题。&lt;/p&gt;
 &lt;p&gt;基于这个理念，在数据治理过程中，字节跳动也面临以下三个挑战与机遇：&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;业务特点：&lt;/strong&gt;   &lt;strong&gt;业务发展快、场景丰富、数据量大且形态各异。&lt;/strong&gt; 业务的线上服务及创新，都对数据有较强的依赖，核心业务数据延迟，质量问题将直接影响业务表现及发展。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;组织特点&lt;/strong&gt;   &lt;strong&gt;：扁平化的组织模式，&lt;/strong&gt;   &lt;strong&gt;分布式&lt;/strong&gt;   &lt;strong&gt;的组织管理&lt;/strong&gt;   &lt;strong&gt;。&lt;/strong&gt; 无行政手段或强组织约束，也无全局治理委员会，且数据从采集到应用全部的生产流程，没有全局规范，业务团队需要自主制定策略并落地。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;文化特点&lt;/strong&gt;   &lt;strong&gt;：&lt;/strong&gt; OKR拆解与对齐文化   &lt;strong&gt;，&lt;/strong&gt; 业务团队有充足的目标定义与拆解权限，且任何人都可能有动机、有角色、甚至有权限去进行数据治理，导致数据治理的业务流程复杂&lt;/p&gt;
 &lt;h3&gt;字节数据治理演进阶段&lt;/h3&gt;
 &lt;p&gt;字节数据治理演进阶段分为6个阶段：&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;   &lt;strong&gt;业务第一原则：&lt;/strong&gt; 坚持业务第一原则，解决业务实际遇到的治理痛点&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;优先稳定建设&lt;/strong&gt;    &lt;strong&gt;：&lt;/strong&gt; 优先解决交付稳定，保障数据链路与产出稳定，减少交付延迟&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;保障数据质量&lt;/strong&gt;    &lt;strong&gt;：&lt;/strong&gt; 核心链路质量管控，配置强质量规则，自动熔断，避免全链路数据污染；加强事前检查，从源头加强质量控制；完善事后评估，为每一张表建立健康档案，持续改进。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;关注数据安全&lt;/strong&gt;    &lt;strong&gt;：&lt;/strong&gt; 冗余权限识别，消除授权风险；数据分类分级，风险定义与多策略控制，减少安全风险&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;重视成本优化&lt;/strong&gt;    &lt;strong&gt;：&lt;/strong&gt; 基于多种规则的与完备的治理元数仓，提供低门槛的治理产品能力，快速优化存储&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;提高员工幸福感&lt;/strong&gt;    &lt;strong&gt;：&lt;/strong&gt; 在帮助业务完成数据治理的后，还需要考虑团队的负载压力，报警治理，降低员工起夜率；归因分析，快速排查修复故障。&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;在这里，再介绍字节特色的“0987”量化数据服务标准。这四个数字分别指的是：稳定性 SLA 核心指标要达到 0 个事故，需求满足率要达到 90%，数仓构建覆盖 80% 的分析需求，同时用户满意度达到 70%。按照这个高标准来要求自己，同时这也是一种自监管的机制，能够有效的防止自嗨，脱离业务需求和价值。&lt;/p&gt;
 &lt;h3&gt;  &lt;strong&gt;字节的部分场景实践&lt;/strong&gt;&lt;/h3&gt;
 &lt;p&gt;下面通过两个例子为大家介绍数据治理在字节的场景实践。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;案例一：&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;问题：字节跳动内部2019年到2020年间，双月内事故数量较多，对业务造成一定影响，且收敛困难，每天都有告警、起夜、对正常开发进度造成影响。&lt;/li&gt;
  &lt;li&gt;解决方案： 采用了分布式用户自治的SLA治理，通过数据分级保障目标管理，在各业务内部进行【拉齐链路-数据分级-广泛共识-系统管理】的行动闭环，系统化保障目标传递和落地。&lt;/li&gt;
  &lt;li&gt;效果： 截止2020年中，事故以每双月30%环比下降，在1年内达到稳定性问题彻底收敛。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;案例二：&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;问题：抖音的实时数仓治理人员的精力分散，以被动的运动式、“救火”式的工作模式为主。协同效率低，人力投入巨大，缺少可持续性。&lt;/li&gt;
  &lt;li&gt;解决方案： 覆盖质量、成本、SLA、安全等治理方向，以业务评估体系，构建治理方案进行例行诊断，对存量问题进行识别和派发，形成一套【评估-&amp;gt;识别-&amp;gt;规划-&amp;gt;执行-&amp;gt;复盘】业务内部分布式自治的治理机制。&lt;/li&gt;
  &lt;li&gt;效果： 从21年至今，治理人员的精力彻底从”运动式“治理的模式中解放出来，更多精力会集中在监督执行与规则优化中，团队起夜率降低30%。质量保障覆盖率达到100%。双月存储优化均在20+PB。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h1&gt;数据治理的发展与分布式&lt;/h1&gt;
 &lt;p&gt;众所周知，有很多机构都分享了对数据治理的定义，这里简单分享一下&lt;/p&gt;
 &lt;p&gt;国际数据管理协会（DAMA）： 数据治理是对数据资产管理行使权力和控制的活动集合&lt;/p&gt;
 &lt;p&gt;IBM：数据治理是对企业中的数据可用性、相关性、 完整性和安全性的全面管理。它帮助组织管理 他们的信息知识和作为决策依据&lt;/p&gt;
 &lt;p&gt;维基百科对数据治理的定义：数据治理是一个涉及全体组织的数据管理概念，通过数据治理，确保在数据的整个生命周期中拥有高数据质量的能力，也是对业务目标的支持。数据治理的关键的重点领域包括可用性、一致性、数据完整性和数据安全性，也包括建立流程来确保整个企业实施有效数据管理。&lt;/p&gt;
 &lt;p&gt;在传统的数据治理方法论与定义中，注意到他有以下共性特点，同时也是现在大多数公司的实践路径，即：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5af526969a134db1bd10ffc70a39b87d~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;但是在实际的执行过程中，他需要以下几个前提和随之带来的落地难点&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;需要明确组织制度&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;梳理业务数据部门，设立公司级别数据治理委员会/部门，各业务分设执行部门，公司内各业务宣导讨论，统一制定公司数据治理规章制度&lt;/p&gt;
 &lt;p&gt;难点一：组织依赖重、建设周期长。需要招聘大量专业的治理专家或引入外部咨询机构，计划制定周期长；专设部门牵头，若无自顶向下的项目背景，业务协调对齐困难。&lt;/p&gt;
 &lt;ol start="2"&gt;
  &lt;li&gt;需要明确权责管理&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;梳理公司数据资产，迁移、拆分、业务改造。确保资产归属与治理权责明确，定期梳理资产类目，维护资产元数据的有效性，确保治理边界清晰&lt;/p&gt;
 &lt;p&gt;难点二：业务影响大，目标对齐难。需完成存量的资产归属划分、改造生产开发体系，对增量定期人力打标，确保资产归属与权责边界清晰，因可能业务系统改造，会对业务发展造成影响&lt;/p&gt;
 &lt;ol start="3"&gt;
  &lt;li&gt;需要进行复盘抽查&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;管理组织定期检查各业务治理过程是否符合公司治理制度，定期检查各项治理结果是否落地，线下复盘与推动不符合预期的治理过程&lt;/p&gt;
 &lt;p&gt;难点三：沟通成本高，执行推动难。如何制定适用于不同业务特点与发展阶段的团队的治理评估体系，各团队是否认可评估标准。&lt;/p&gt;
 &lt;p&gt;为了解决以上三个问题，我们有些新的思考，即引入「分布式」的理念。&lt;/p&gt;
 &lt;p&gt;Governance一词在根源上同Government，1990年代被经济学家和政治科学家重新创造，由联合国、世界货币组织和世界银行等机构进行传播。其核心有以下两种论述：&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;第一个论述：标准与规范。&lt;/strong&gt; 指的是一定范围内的一致的管理，统一的政策，某一责任区指导以及合适的监管和可问责机制。这种行政力的集中化管理存在一些问题，比如决策成本高，人力投入高、落地阻力大，精力消耗大。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;第二个论述：过程与结果。&lt;/strong&gt; 指的是只要关注结果和产出以及业务内部实践，通过分布式协作让业务的治理结果、业务痛点和治理方式及手段在内部闭环，而不是由中台层面统一推动。&lt;/p&gt;
 &lt;p&gt;我们尝试从第二种论述，即重视过程落地和治理结果产出的出发，更快的落地产品，落地数据治理的产品解决方案&lt;/p&gt;
 &lt;h3&gt;从集中式到分布式&lt;/h3&gt;
 &lt;p&gt;基于分布式的数据自治的理念，我们来解决在落地执行上的两个最困难的点&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;一&lt;/strong&gt;   &lt;strong&gt;、&lt;/strong&gt;   &lt;strong&gt;组织制度分布式&lt;/strong&gt;   &lt;strong&gt;：&lt;/strong&gt; 尝试将组织的强管理属性转换到监督属性，治理单元与制度设计回归到业务单元。好处是，不强依赖横向中心化组织，业务治理痛点闭环在业务单元，且业务基于自身发展阶段制定治理目标，ROI论证回归业务。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;二、&lt;/strong&gt;   &lt;strong&gt;权责验收分布式&lt;/strong&gt;   &lt;strong&gt;：&lt;/strong&gt; 基于产品体系与落地解决方案，支持业务按需自驱，市场化执行，平台辅助与按需验收。好处是，无须长周期的资产类目梳理，业务系统改造，权责均由业务区分，基于业务单元与多维视角，按需验收治理结果，业务单元内对齐。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/91bba25664684b5f99026b46d992405c~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;如上图展示的饼图，对于一个公司的数据资产，传统来说，可以很清晰地按照业务边界来划分清楚。对于分布式数据治理，我们通常是由业务单元自行认领，业务单元A自行认领属于自己部分，业务单B也自行认领属于自己部分。认领就意味着，所有治理的动作包括结果，安全性、成本、质量、稳定都由认领业务单元负责。&lt;/p&gt;
 &lt;p&gt;当然，这样这样也可能存在两个问题，不过在分布式的理念中能够得到较好解决&lt;/p&gt;
 &lt;p&gt;第一是认领范围重合：这种情况往往让业务在线下对齐是否需要去做改造和划分，各自拿到自身需要的治理结果，短期无须重人力投入，不追求绝对的边界划分。长期因不同治理验收需求或团队管理需求，自行进行资产归集和整理。达到动态的平衡状态&lt;/p&gt;
 &lt;p&gt;第二是无人认领：针对长期无人认领的资产，我们可以基于每个业务的历史的规则和能力，形成一个治理的平均线，再从平台层面推动无人认领的资产治理，由于无人认领，这样的资产推动起来相对较快。&lt;/p&gt;
 &lt;h3&gt;我们理解的分布式治理&lt;/h3&gt;
 &lt;p&gt;定义：以业务单元为数据治理闭环单元，通过完善的产品工具，将管理视角转化为监督视角，解决数据治理落地痛点;各业务团队分布式自运行，整体上达到全局最优，从形态上，适配更多业务特性和发展阶段，从效果上，强推进重落实与结果&lt;/p&gt;
 &lt;p&gt;字节跳动通常以业务单元作为一个数据治理闭环，即在业务单元内部完成数据稳定性、质量、存储、计算等治理。同时每个业务单元不是孤立的，也有相互协作，比如A业务单元的数据治理经验可以沉淀为治理模板，供后续其他业务使用。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/32b7dea65683498fb6cf567eb18aef1f~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;这样的分布式治理方式，有以下一些优势：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;影响小，依赖小。&lt;/strong&gt; 治理下放到各个业务中，各级业务乃至个人都能自驱治理，业务根据自身发展阶段灵活组合治理工具，无须对组织强依赖。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;周期短，见效快。业务&lt;/strong&gt;自驱梳理核心数据及链路，跨团队对齐线上化、协议签署、过程追踪。治理周期显著缩短，很快就出成效，增强团队信心。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;效率高，省人力。&lt;/strong&gt; SLA治理提高跨团队协作效率，聚焦核心数据任务集中资源保障，集中精力，报警归因减少起夜，帮助企业节省年度人力消耗&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;算清帐，降成本。&lt;/strong&gt; 各业务口径的存储计算资源消耗、核算成本，制定降本目标并追踪落地；业务经验规则化、策略化、自动化、自驱化持续降本增效。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h1&gt;分布式自治架构&lt;/h1&gt;
 &lt;p&gt;为达成业务分布式自治，产品需要对用户行为路径完全覆盖，对业务经验完全接受。平台提供完善的开放能力，协助业务进一步提效&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c80282bce73d41ceb8f806fad016bd81~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h3&gt;产品体系&lt;/h3&gt;
 &lt;p&gt;以上关于分布式的理解，下面将介绍字节分布式自治的产品体系。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0a6d385830a04fe2b4c102c59c896da8~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;从治理门户来看，包括治理全景、工作台、规划、诊断、复盘等全流程治理环节。在治理场景中，提供数据质量安全、资源优化、报警、企业复盘管理等一系列垂直场景。在底层，包含数据全生命周期流程，从数据采集、数据传输、数据存储、数据处理、数据共享到数据销毁。&lt;/p&gt;
 &lt;h3&gt;治理双路径&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/83c64c8f295a4c309b8b9b65285667c1~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;为了把用户所有治理经验沉淀为平台能力，我们抽象了2种治理路径。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;第一种是规划式路径。这是一个比较常见的规划式路径，即从看板和报表出发，自上而下做规划。比如看板已经反映出成本增加、延时变长或者数据质量变差，团队管理者发起报告或事故，推动业务单元同事进行数据治理，最后进行复盘。&lt;/li&gt;
  &lt;li&gt;第二种是响应式。比如生产者收到一个数据质量或延时的报警，随后快速定位原因并做改进计划。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;为了更好把业务经验全部线上化，我们通常双路径并行使用。&lt;/p&gt;
 &lt;h4&gt;规划式治理路径案例&lt;/h4&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/84d937f1bb4641b29b864fb6d20e2205~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;首先看通用模块资产视图，包括资产增量情况评估等，以及业务对于资产的评价，如健康分体系。我们通常根据资产情况去制定目标。如果发现问题之后，业务驱动制定目标，可能是降低存储。同时需要去应用一些业务规则，比如团队内部认为 TTL(数据生命周期)很重要，需要帮助识别出来的同时也需要设定一个诊断周期。在团队方案确认完之后，产品会做监督，包括定义提醒，同时也推动资产owner完成总结。&lt;/p&gt;
 &lt;h4&gt;响应式治理路径案例&lt;/h4&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d7d44b392f094834bf13c466553cd197~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;例如，我们发现一些任务在深夜执行失败了，需要先做问题排查，发现问题是HDFS丢块导致。在传统情况下，解决方案是去检查API 问题，再去拉相关人员，可能2- 3 小时才能完成，最后配合监控并收归到 wiki 中。而在DataLeap数据治理产品里，可以直接实现归因打标等能力，最后快速复盘。&lt;/p&gt;
 &lt;h3&gt;  &lt;strong&gt;治理全规则&lt;/strong&gt;&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b07ffd4e802f4760ba1e447c644088d1~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;如果要覆盖业务的全部属性，治理平台需要形成有效且全面的规则模板。目前，我们的规则模板包含两个部分：&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;第一是&lt;/strong&gt;   &lt;strong&gt;规则引擎&lt;/strong&gt;   &lt;strong&gt;，具体包括业务输入、平台输入、推荐输入。&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;业务输入：主要依据业务团队的治理经验以及行业经验。&lt;/li&gt;
  &lt;li&gt;平台输入：平台会提供一些基础能力，如存储、计算、质量、报警等几个维度。截止目前已经提供了80多个规则。&lt;/li&gt;
  &lt;li&gt;推荐输入：基于业务输入和平台输入，去做分析和挖掘，发现哪些规则用得多、哪些规则阈值更合理。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;第二是治理&lt;/strong&gt;   &lt;strong&gt;数仓&lt;/strong&gt;   &lt;strong&gt;，具体包括行为数据、治理操作、效果数据。&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;行为数据：包括用户规则配置等内容是否有重复以及带元素标签的资产数据等。&lt;/li&gt;
  &lt;li&gt;治理操作：包括生命周期、任务关闭、数据删除、SLA签署等。&lt;/li&gt;
  &lt;li&gt;效果数据：包括操作收益、资产收益、指标收益等。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;  &lt;strong&gt;不同业务快速灵活接入治理规则&lt;/strong&gt;&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7d6cbc10155940af818b0299edf28db3~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;分布式自治基础是要构建治理生态、建设开放平台，让不同业务能够快速、灵活接入。&lt;/p&gt;
 &lt;p&gt;为了让业务能快速介入，我们把数据分成了四种类型：表达式、三方元数据、标准元数据、算法包。针对不同的业务，根据当前的经验和能力，我们会提供不同的接入方式，让业务去更好把规则和能力去接入到我们的平台。&lt;/p&gt;
 &lt;h3&gt;  &lt;strong&gt;基于业务单元进行智能化提效&lt;/strong&gt;&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0e047ae9a51e422ca5b6b9a56bd926f7~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;在获取不同业务的规则和能力之后，我们需要再做平台能力沉淀，把好的规则和能力复用给更多业务。&lt;/p&gt;
 &lt;p&gt;Case1：任务SLA签署推荐。基于运营时间做权重分配，保证下游任务运行完成，同时也会进行关键链路分析。这个规则目前在字节内部广泛使用。&lt;/p&gt;
 &lt;p&gt;Case2：动态阈值监控。这是基于业务在报警阈值上的实践提取的规则。&lt;/p&gt;
 &lt;p&gt;Case3：相似任务识别。通过序列化和向量化操作，去和底层 spark 引擎做配合。在业务内部应用覆盖99%，且优化任务都千级以上，由此接入平台并推荐给其他业务。&lt;/p&gt;
 &lt;h1&gt;分布式治理核心能力&lt;/h1&gt;
 &lt;h3&gt;治理全景-分布式验收&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dac00eba25554dccb3c73cc67c9c7fbf~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;在分布式验收中，会区分为全员视角、团队视角和个人视角。全员视角可以看到公司级资产，包括整体的健康分体系以及核心指标。团队视角中，主要由业务自己梳理，包括内部的评价体系。&lt;/p&gt;
 &lt;h3&gt;  &lt;strong&gt;治理工作台-集中治理待办&lt;/strong&gt;&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8cce2ceaee304de39aeca000c6fa4812~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;上图为个人工作台功能，主要为了把SLA保障、计算任务、数据存储等治理场景展示在一个页面，方便 owner 业务全局查看治理待办事项。&lt;/p&gt;
 &lt;h3&gt;  &lt;strong&gt;治理规划与诊断-权责与规划分布式&lt;/strong&gt;&lt;/h3&gt;
 &lt;p&gt;第一，支持自定义治理域，灵活自治，提供多种维度，自定义组合和圈选资产范围。&lt;/p&gt;
 &lt;p&gt;第二，支持创建治理方案，例行诊断：发起人基于业务需求，选择治理域，设计治理规则，发起存储/计算/质量等类型治理方案。例行诊断与推进实施。&lt;/p&gt;
 &lt;p&gt;第三，支持规则管理，提供80+治理基础规则，支持自定义组合和配置规则与分享。&lt;/p&gt;
 &lt;h3&gt;  &lt;strong&gt;复盘管理&lt;/strong&gt;&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e8dced4bb8ea4921a4cade5d4b91e555~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;复盘管理是一个通用模块。业务根据自身需要去识别任务是否需要复盘，或者仅仅做问题登记。除此之外，业务还可以用复盘管理能力做内部管理，比如查看、检索所有的事故复盘，查看每个事故发生的原因和改进计划。同时，也可了解归因分布情况，并帮助下一个值班同学快速反馈和定位问题。&lt;/p&gt;
 &lt;h3&gt;  &lt;strong&gt;SLA&lt;/strong&gt;   &lt;strong&gt;治理&lt;/strong&gt;&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a1d215742a87407aad5dd28924092552~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;在字节跳动内部，SLA不是平台级保障，而是源于业务团队内部。首先是业务按需申报，可能是PM、运营或数据研发等任何角色，认为自身任务重要，填写背景、原因、等级、时间等信息之后，即可发起一个SLA。发起之后，在团队内部进行审核，可能存在同一个团队多个高优任务的情况，这由团队内部自行调整优先级。同时，这个也是跨团队判断该任务重要性的标准。&lt;/p&gt;
 &lt;p&gt;之后是完成签署，签署也会在产品里面体现出来。每个节点时间都有实时监控，如果产生了延迟，会推动业务做复盘和登记。我们也提供基础的DAG，包括申报业务单的查看，同时也可以让大家去查看每个等级的破线情况，以及团队对业务的服务情况。&lt;/p&gt;
 &lt;h3&gt;  &lt;strong&gt;数据安全&lt;/strong&gt;&lt;/h3&gt;
 &lt;p&gt;在数据安全层面，主要专注于清理冗余权限，完善分类分级。不同团队对冗余权限定义不同，有的90天无访问算冗余权限，有的70天，有的7天。因此我们提供自定义能力，由业务内部发起review，完成冗余权限的识别和定义规则，识别之后复用诊断能力。&lt;/p&gt;
 &lt;h3&gt;资源优化&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a4cc881f662449689054722cf5013570~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;基于每个团队实际执行情况，提炼出一些通用的规则。例如，某些规则可能有几十个业务在使用，近 90% 认为近 30 天无查询需要被识别出来，我们就会在平台中提供这类能力，方便新业务或者小白业务去使用。&lt;/p&gt;
 &lt;h3&gt;报警归因&lt;/h3&gt;
 &lt;p&gt;在报警归因方面，我们能提供所有报警明细，方便查看是否有重复规则，是否有高频报警规则，帮助用户发现无效报警和重复规则，降低告警量和跟起夜率。除此之外，我们也提供业务内部的归因登记和分析能力。&lt;/p&gt;
 &lt;p&gt;以上是字节跳动在数据治理相关实践。目前，字节跳动也将沉淀的数据治理经验，通过火山引擎大数据研发治理套件DataLeap对外提供服务。作为一站式数据中台套件，DataLeap汇集了字节内部多年积累的数据集成、开发、运维、治理、资产、安全等全套数据中台建设的经验，助力ToB市场客户提升数据研发治理效率、降低管理成本。&lt;/p&gt;
 &lt;p&gt;点击跳转   &lt;a href="https://www.volcengine.com/product/dataleap/?utm_source=juejin_dp&amp;utm_medium=article&amp;utm_term=juejin_readmore&amp;utm_campaign=20230315&amp;utm_content=dataleap"&gt;大数据研发治理套件 DataLeap&lt;/a&gt; 了解更多&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62681-%E7%81%AB%E5%B1%B1-%E5%BC%95%E6%93%8E-dataleap</guid>
      <pubDate>Wed, 15 Mar 2023 17:35:45 CST</pubDate>
    </item>
    <item>
      <title>金融行业数据分类分级“五步走”|盾见</title>
      <link>https://itindex.net/detail/62675-%E9%87%91%E8%9E%8D-%E8%A1%8C%E4%B8%9A-%E6%95%B0%E6%8D%AE</link>
      <description>&lt;p&gt;&amp;nbsp;&lt;img src="https://image.jiqizhixin.com/uploads/editor/578d769a-aa4f-4df1-860a-8ae4504bb1ec/%E5%9B%BE%E7%89%871.png" style="width: 700%;" class="fr-fic fr-dib"&gt;&lt;/p&gt;&lt;p style="text-align: right;"&gt;&amp;nbsp;文|查浩奇&amp;nbsp;&lt;/p&gt;&lt;p&gt;《数据安全法》明确提出，国家要建立数据分类分级保护制度，根据数据在经济社会发展中的重要程度，以及一旦遭到篡改、破坏、泄露或者非法获取、非法利用，对国家安全、公共利益或者个人、组织合法权益造成的危害程度，对数据实行分类分级保护。国家数据安全工作协调机制统筹协调有关部门制定重要数据目录，加强对重要数据的保护。关系国家安全、国民经济命脉、重要民生、重大公共利益等数据属于国家核心数据，实行更加严格的管理制度。各地区、各部门应当按照数据分类分级保护制度，确定本地区、本部门以及相关行业、领域的重要数据具体目录，对列入目录的数据进行重点保护。&lt;/p&gt;&lt;p&gt;针对金融行业，中国银保监会办公厅于2019年5月22日发布的《关于开展银行业和保险业网络安全专项治理工作的通知》要求：&amp;ldquo;要制定数据安全分类分级标准，构建覆盖客户信息全生命周期的保护体系，防范数据被窃取。&amp;rdquo;&lt;/p&gt;&lt;p&gt;数据分类分级制度构建不断深化，相较之前只止步于提出数据分类分级原则性要求的做法，越来越多的法律文件开始探索数据分类分级具体标准的明确，比如证监会于2018年9月27日发布的《证券期货业数据分类分级指引》（JRT 0158-2018）、中国人民银行于2020年2月13日发布的《个人金融信息保护技术规范》（JR/T 0171&amp;mdash;2020）及2020年9月23日，中国人民银行正式发布《金融数据安全 数据安全分级指南》（JR/T 0197&amp;mdash;2020）等等，《金融数据安全 数据安全分级指南》亦为金融行业最重要的探索成果。&lt;/p&gt;&lt;p&gt;《金融数据安全 数据安全分级指南》在名称中仅体现了&amp;ldquo;分级&amp;rdquo;，但从《指南》提出的&amp;ldquo;数据安全定级工作流程&amp;rdquo;及附录A等内容可以看出，数据分类是数据分级的必要前提。&lt;/p&gt;&lt;p style="text-align: center;"&gt;&lt;strong&gt;01&lt;/strong&gt;&lt;strong&gt;行业需求：金融行业数据分类分级的必要性&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;监管明确：&lt;/strong&gt;从《金融数据安全 数据安全分级指南》附录A中可看出，金融数据内涵丰富，种类繁多。数据分类分级工作的开展过程实际上是金融业机构按照一定标准对其所拥有的数据资产进行梳理的过程&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;数据保护：&lt;/strong&gt;将各类数据按照风险进行分级，有利于金融业机构明晰数据保护重点，合理分配数据保护资源。针对不同级别的数据特征，有的放矢地采取安全保障措施，亦有利于降低数据安全遭受破坏时对国家安全、公共权益、个人隐私、企业合法权益所带来的负面影响。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;开放共享：&lt;/strong&gt;中共中央、国务院《关于构建更加完善的要素市场化配置体制机制的意见》将数据列为生产要素之一，正式纳入到市场化配置之中。数字经济新产业、新业态和新模式的培育，离不开数据的开放共享与有序使用。金融业机构若能依据统一规范的数据管理制度开展数据分类分级工作，将有利于促进数据在各机构间的开放共享，进一步挖掘金融数据价值。&lt;/p&gt;&lt;p style="text-align: center;"&gt;&lt;strong&gt;02&amp;nbsp;&lt;/strong&gt;&lt;strong&gt;&amp;ldquo;&lt;/strong&gt;&lt;strong&gt;五步走&amp;rdquo;：金融业数据分类分级的实施路径&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;金融行业存在业务数据种类繁多且复杂；不清楚自身业务环境有多少资产和数据分布情况；数据资产的防护粒度较粗，缺乏差异化保护等特征，对数据分类分级的工作带来了难度。极盾科技基于对金融行业的洞察和实践，就数据分类分级总结出&amp;ldquo;五步走&amp;rdquo;战略：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;S&lt;/strong&gt;&lt;strong&gt;tep&lt;/strong&gt;&lt;strong&gt;1&lt;/strong&gt;&lt;strong&gt;、&lt;/strong&gt;&lt;strong&gt;咨询调研分析：&lt;/strong&gt;对国家以及行业政策规范进行分析、对业务系统以及数据安全现状进行调研、对数据资产现状进行分析。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;S&lt;/strong&gt;&lt;strong&gt;tep&lt;/strong&gt;&lt;strong&gt;2&lt;/strong&gt;&lt;strong&gt;、&lt;/strong&gt;&lt;strong&gt;数据资产梳理&lt;/strong&gt;&lt;strong&gt;：&lt;/strong&gt;使用工具自动扫描发现数据资产，并对数据资产进行全面盘点、梳理打标，构建数据资产目录，形成数据资产清单，为之后企业数据资产管理和数据安全体系建设打好基础 。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;S&lt;/strong&gt;&lt;strong&gt;tep&lt;/strong&gt;&lt;strong&gt;3&lt;/strong&gt;&lt;strong&gt;、&lt;/strong&gt;&lt;strong&gt;数据分类&lt;/strong&gt;&lt;strong&gt;方案&lt;/strong&gt;&lt;strong&gt;：&lt;/strong&gt;根据行业规范和业务特性设计分类体系，对数据分类打标，梳理数据字段对应分类规则并进行调优。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;S&lt;/strong&gt;&lt;strong&gt;tep&lt;/strong&gt;&lt;strong&gt;4&lt;/strong&gt;&lt;strong&gt;、&lt;/strong&gt;&lt;strong&gt;数据分级&lt;/strong&gt;&lt;strong&gt;方案&lt;/strong&gt;&lt;strong&gt;：&lt;/strong&gt;根据行业规范和业务特性设计分级体系，梳理数据字段对应分级规则，并对敏感数据识别打标，并根据实际情况对数据等级进行变更维护 。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;S&lt;/strong&gt;&lt;strong&gt;tep&lt;/strong&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;strong&gt;、&lt;/strong&gt;&lt;strong&gt;数据分类分级全景图&lt;/strong&gt;&lt;strong&gt;：&lt;/strong&gt;根据可视化的数据分类分级清单，形成数据分类分级报表、形成分类分级全景图、分类分级信息管理机制，为数据安全保护做准备。&amp;nbsp;&lt;/p&gt;&lt;p style="text-align: center;"&gt;&lt;strong&gt;03&lt;/strong&gt;&lt;strong&gt;&amp;ldquo;&lt;/strong&gt;&lt;strong&gt;五个要点&amp;rdquo;：金融业数据分类分级落地实践&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;某某银行使用极盾&amp;middot;智辩-数据分类分级，通过四个阶段实现对数据分类分级的全面落地，具体有以下几个要点：&lt;/p&gt;&lt;p&gt;&lt;img src="https://image.jiqizhixin.com/uploads/editor/2ea28613-eefb-46aa-9a14-9813763fb3f1/%E5%9B%BE%E7%89%873.png" style="width: 700%;" class="fr-fic fr-dib"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;要点&lt;/strong&gt;&lt;strong&gt;1&lt;/strong&gt;&lt;strong&gt;：&lt;/strong&gt;&lt;strong&gt;数据安全现状梳理&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;基于行业已有规范要求，结合金融企业的现状进行符合性评估；规范包括不限于：《金融数据安全&amp;nbsp;数据安全评估规范》、《金融数据安全&amp;nbsp;数据生命周期安全规范》、《个人金融信息保护技术规范》、《个人信息安全影响评估指南》。&lt;/p&gt;&lt;p&gt;&lt;img src="https://image.jiqizhixin.com/uploads/editor/8e8ea8b5-268e-43df-af84-e9024be4a589/%E5%9B%BE%E7%89%874.png" style="width: 700%;" class="fr-fic fr-dib"&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;要点&lt;/strong&gt;&lt;strong&gt;2&lt;/strong&gt;&lt;strong&gt;：&lt;/strong&gt;&lt;strong&gt;分类分级规则设计&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;通过咨询设计落地实现5000+多条规则， 包括当事人、产品、协议、 &amp;nbsp;时间、账户、介质、渠道、资源项和通用等九大类信息字段的分类分级的识别规则。根据规则的适用范围， 形成通用规则和个性化规则。&lt;/p&gt;&lt;p&gt;分类设计如下图：&lt;/p&gt;&lt;p&gt;&lt;img src="https://image.jiqizhixin.com/uploads/editor/2943f473-2a10-4f75-b1ad-9cd7560df680/%E5%9B%BE%E7%89%875.png" style="width: 700%;" class="fr-fic fr-dib"&gt;&lt;/p&gt;&lt;p&gt;分级设计：针对金融行业特性，具体分为5级&lt;/p&gt;&lt;p&gt;&lt;img src="https://image.jiqizhixin.com/uploads/editor/a85fe2d4-1850-44ad-a134-bcaa864756e1/%E5%9B%BE%E7%89%876.png" style="width: 700%;" class="fr-fic fr-dib"&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;要点&lt;/strong&gt;&lt;strong&gt;3&lt;/strong&gt;&lt;strong&gt;：&lt;/strong&gt;&lt;strong&gt;数据分类分级工具应用&lt;/strong&gt;&lt;strong&gt;-&lt;/strong&gt;&lt;strong&gt;极盾&amp;middot;智辩&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;数据分类分级工具-极盾&amp;middot;智辩，主要功能包含：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;※&lt;/strong&gt;&lt;strong&gt;数据资产清单&lt;/strong&gt;&lt;strong&gt;：&lt;/strong&gt;对数据资产进行全面盘点，构建数据资产目录，为之后企业数据资产管理和数据安全体系建设打好基础&lt;/p&gt;&lt;p&gt;&lt;strong&gt;※&lt;/strong&gt;&lt;strong&gt;数据分类分级&lt;/strong&gt;&lt;strong&gt;：&lt;/strong&gt;根据行业规范和业务特性制定分类体系和分级体系，梳理数据字段对应分类规则和分级规则。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;※&lt;/strong&gt;&lt;strong&gt;敏感数据识别&lt;/strong&gt;&lt;strong&gt;：&lt;/strong&gt;内置敏感数据智能识别算法，高效识别敏感数据。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;※&lt;/strong&gt;&lt;strong&gt;分类分级全景图&lt;/strong&gt;&lt;strong&gt;：&lt;/strong&gt;初始化完成后，生成数据分类分级全景图。随着业务推进会不断产生新数据，定期扫描覆盖新数据，呈现最新状态视图。&lt;/p&gt;&lt;p&gt;&lt;img src="https://image.jiqizhixin.com/uploads/editor/0e5dbf02-2b09-4a8f-b2d2-92ed12bc38c2/%E5%9B%BE%E7%89%877.png" style="width: 700%;" class="fr-fic fr-dib"&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;要点&lt;/strong&gt;&lt;strong&gt;4&lt;/strong&gt;&lt;strong&gt;：&lt;/strong&gt;&lt;strong&gt;管理规范/合规监管交付物&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;形成全行级建设，梳理行业监管合规、制度规范要求，形成底线合规分类分级规范、管理办法、落地实施操作规范和数据分类分级业务需求。&lt;/p&gt;&lt;p&gt;&lt;img src="https://image.jiqizhixin.com/uploads/editor/7cba7ef3-ae17-473e-a0a2-971b332b3606/%E5%9B%BE%E7%89%878.png" style="width: 700%;" class="fr-fic fr-dib"&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;要点&lt;/strong&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;strong&gt;：&lt;/strong&gt;&lt;strong&gt;根&lt;/strong&gt;&lt;strong&gt;据安全管控评估，细化数据分级保护落地策略&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;实现全行级管理制度，遵循管理咨询的思路，进行管理制度调研，与行业内规范要求进行比较，找出当前组织架构及制度中缺失部分，进行编写完善。落地策略的建立将首先明确组织架构和岗位职责，为整体数据安全建设提供组织支撑，随后针对机构方关心的数据生命周期阶段、分类分级、数据外发共享等场景进行管理办法制定，配套流程设计、实施表单、免责申明等3、4级文件，形成系统完善的数据安全落地策略。&lt;/p&gt;&lt;p&gt;&lt;img src="https://image.jiqizhixin.com/uploads/editor/6dd1de97-4600-4e23-b796-1ef40a3211f9/%E5%9B%BE%E7%89%879.png" style="width: 700%;" class="fr-fic fr-dib"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;04&amp;nbsp;&lt;/strong&gt;&lt;strong&gt;成效凸显：&lt;/strong&gt;&lt;strong&gt;金融行业数据分类分级的价值&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;通过本次金融行业数据安全分类分级服务，在专业性、服务水平、合作效率等方面获得客户的高度认可，真正帮助客户实现了数据安全管理多重收益：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt;&lt;strong&gt;、&lt;/strong&gt;&lt;strong&gt;满足监管合规要求&lt;/strong&gt;&lt;strong&gt;：&lt;/strong&gt;帮助金融行业企业满足合规的需要，既能够应对国家层面的法律法规，亦能满足行业法规的要求。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2&lt;/strong&gt;&lt;strong&gt;、&lt;/strong&gt;&lt;strong&gt;数据资产盘点，为数据安全体系建设打好基础&lt;/strong&gt;&lt;strong&gt;：&lt;/strong&gt;能够帮助金融行业企业对数据资产进行全面的盘点，了解敏感数据分布、类型、量级，做到心中有数，以此构建企业级的数据资产目录，为之后企业数据资产管理和数据安全体系建设打好基础。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;3&lt;/strong&gt;&lt;strong&gt;、&lt;/strong&gt;&lt;strong&gt;提升安全运营效率，降低安全成本&lt;/strong&gt;&lt;strong&gt;：&lt;/strong&gt;对于低敏数据，减少数据过度保护产生的额外成本，对于高敏数据，减少数据泄漏带来的巨大风险，平衡数据保护与数据流通，实现数据价值最大化。&lt;/p&gt;&lt;p&gt;最后，给大家推荐&amp;ldquo;最全数据分类分级标准汇编&amp;rdquo;，本文将「国家层面、行业层面、地方层面」出台的【12份】数据分类分级标准指南进行总结汇编，希望对此领域感兴趣的同学能够起到一定借鉴作用。&amp;nbsp;&lt;/p&gt;&lt;p&gt;如需下载标准汇编&lt;strong&gt;【PDF完整版】&lt;/strong&gt;以及各项数据分类分级标准指南完整版关注&lt;strong&gt;&amp;ldquo;极盾科技&amp;rdquo;&lt;/strong&gt;公众号，回复&lt;strong&gt;&amp;ldquo;分类分级&amp;rdquo;&lt;/strong&gt;下载&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="https://image.jiqizhixin.com/uploads/editor/7cd98025-5366-4abf-a178-f489f5ba7f2f/%E5%9B%BE%E7%89%8710.png" style="width: 700%;" class="fr-fic fr-dib"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62675-%E9%87%91%E8%9E%8D-%E8%A1%8C%E4%B8%9A-%E6%95%B0%E6%8D%AE</guid>
      <pubDate>Mon, 13 Mar 2023 16:02:45 CST</pubDate>
    </item>
    <item>
      <title>6 大经典机器学习数据集，3w+ 用户票选得出，建议收藏</title>
      <link>https://itindex.net/detail/62669-%E7%BB%8F%E5%85%B8-%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0-%E6%95%B0%E6%8D%AE</link>
      <description>&lt;blockquote&gt;内容一览：本期汇总了超神经下载排名众多的 6 个数据集，涵盖图像识别、机器翻译、遥感影像等领域。这些数据集质量高、数据量大，经历人气认证值得收藏码住。  &lt;br /&gt;关键词：数据集   机器翻译   机器视觉&lt;/blockquote&gt; &lt;p&gt;数据集是机器学习模型训练的基础，优质的公开数据集对于模型训练效果、研究成果可靠度等具有重要意义。&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;HyperAI超神经自上线以来，为数据科学从业者提供了大量优质的公开数据集。&lt;/strong&gt; 本期内容分享，我们筛选出了 6 个热门数据集，  &lt;strong&gt;其总下载次数已达到 32,569 次。&lt;/strong&gt; 希望这些数据集能进一步为广大开发者服务~&lt;/p&gt; &lt;p&gt;注：本文梳理的数据集均来自为数据科学家服务的网站——超神经  &lt;br /&gt;  &lt;a href="https://hyper.ai/datasets" rel="nofollow noreferrer"&gt;https://hyper.ai/datasets&lt;/a&gt;&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;第 6 名：   &lt;a href="https://hyper.ai/datasets/4920" rel="nofollow noreferrer"&gt;Tanks Temple 3D 重建数据集&lt;/a&gt;&lt;/strong&gt;  &lt;br /&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474394" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474395" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;Tanks Temple 图像数据集提供高分辨率的视频，研究人员可以从视频中采集图像，  &lt;strong&gt;依据图像进行三维重建。&lt;/strong&gt; 该数据集包括训练数据和测试数据两类，其中测试数据分为中级组和高级组。&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;第 5 名：   &lt;a href="https://hyper.ai/datasets/4920" rel="nofollow noreferrer"&gt;DOTA 航拍图像数据集&lt;/a&gt;&lt;/strong&gt;   &lt;br /&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474396" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474397" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;DOTA 全称为 A Large-scale Dataset for Object DeTection in Aerial Images，是一个包含 2,806 张航拍图的图像数据集，  &lt;strong&gt;被用于在航拍图像中进行目标检测，发现和评估图像中的物体。&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;这些图像来源包含不同传感器和平台。每张图像的像素尺寸在 800  &lt;em&gt;800 到 4000&lt;/em&gt;4000 的范围内，其中包含不同尺度、方向和形状的物体。&lt;/p&gt; &lt;p&gt;往期推送请访问：  &lt;br /&gt;  &lt;a href="http://mp.weixin.qq.com/s?__biz=MzU3NTQ2NDIyOQ==&amp;mid=2247496885&amp;idx=1&amp;sn=add8058f38f5a39608d4915924c5e23b&amp;chksm=fd2002ffca578be91997c3dc38ff72aea8b818bae7be805072217220d9a71179776f71b7ec14&amp;scene=21#wechat_redirect" rel="nofollow noreferrer"&gt;DOTA 数据集：2806 张遥感图像，近 19 万个标注实例&lt;/a&gt;&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;第 4 名：   &lt;a href="https://hyper.ai/datasets/5711" rel="nofollow noreferrer"&gt;VGG-Face2 人脸识别数据集&lt;/a&gt;&lt;/strong&gt;  &lt;br /&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474398" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474399" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;VGG-Face2 是一个人脸图像数据集，包含共计 9131  个人的面部数据，图像均来自 Google 的图片搜索。  &lt;strong&gt;数据集中的人在姿势、年龄、种族和职业方面有很大差异。&lt;/strong&gt; 该数据集由牛津大学的工程科学系视觉几何组于 2015 年发布，相关论文有《Deep Face Recognition》。&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;第 3 名：   &lt;a href="https://hyper.ai/datasets/5419" rel="nofollow noreferrer"&gt;UCAS-AOD 遥感影像数据集&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474400" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474401" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;UCAS-AOD 是一个遥感影像数据集，  &lt;strong&gt;用于飞机和车辆检测。&lt;/strong&gt; 该数据集由国科大于 2014 年首次发布，并于 2015 年补充，相关论文有《Orientation Robust Object Detection in Aerial Images Using Deep Convolutional Neural Network》&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;第 2 名：   &lt;a href="https://hyper.ai/datasets/14137" rel="nofollow noreferrer"&gt;OpenMantra 漫画机器翻译数据集&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474402" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474403" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;OpenMantra 是一个针对日文漫画的机器翻译评估数据集，包含五种不同风格（fantacy、romance、battle、mystery、slice of life）的漫画。  &lt;strong&gt;数据集中共包含 1593 个句子，848 个场景画面和 214 页漫画，&lt;/strong&gt; 由东京大学 Mantra 团队发布。&lt;/p&gt; &lt;p&gt;往期推送请查看：  &lt;br /&gt;  &lt;a href="http://mp.weixin.qq.com/s?__biz=MzU3NTQ2NDIyOQ==&amp;mid=2247497461&amp;idx=1&amp;sn=3b7eede40073e65e0bd8bd73d15ede19&amp;chksm=fd2000bfca5789a92f1808b1e98464d31af07344bc98cae9f1fbad95de5e063dcd4659f77491&amp;scene=21#wechat_redirect" rel="nofollow noreferrer"&gt;漫画翻译、嵌字 AI，东京大学论文被 AAAI’21 收录&lt;/a&gt;&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;第 1 名：   &lt;a href="https://hyper.ai/datasets/4899" rel="nofollow noreferrer"&gt;ImageNet 10 图像识别数据集&lt;/a&gt;&lt;/strong&gt;  &lt;br /&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474404" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474405" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;ImageNet 是目前世界上最大的图像识别数据库，由斯坦福大学教授李飞飞等人创建。&lt;/strong&gt; 主要用于机器视觉领域的图像分类和目标检测。&lt;/p&gt; &lt;p&gt;数据集根据 WordNet 层次结构组织，其中每个节点（也称为类别）由数百甚至数千张图像组成。该数据集共包含 2.2 万个图像类别，约 1500 万张图片。&lt;/p&gt; &lt;p&gt;往期推送请访问：  &lt;br /&gt;  &lt;a href="http://mp.weixin.qq.com/s?__biz=MzU3NTQ2NDIyOQ==&amp;mid=2247486955&amp;idx=1&amp;sn=622108b403f441fe71e8e4ddbe72529b&amp;chksm=fd23fba1ca5472b7a6f6129a8f064d2839fe68fbaef100734466a19f2f34fd22ca7e2d9d0f8e&amp;scene=21#wechat_redirect" rel="nofollow noreferrer"&gt;当年这个决定，让李飞飞奠定 AI 江湖的女王地位&lt;/a&gt;&lt;/p&gt; &lt;p&gt;以上就是本期推荐的 6 个 hyper.ai 高频下载数据集，更多数据科学优质公开数据集，可访问以下链接下载：  &lt;a href="https://hyper.ai/datasets" rel="nofollow noreferrer"&gt;https://hyper.ai/datasets&lt;/a&gt;&lt;/p&gt; &lt;p&gt;—— 完 ——&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>算法 机器学习 人工智能 深度学习 数据挖掘</category>
      <guid isPermaLink="true">https://itindex.net/detail/62669-%E7%BB%8F%E5%85%B8-%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0-%E6%95%B0%E6%8D%AE</guid>
      <pubDate>Mon, 20 Feb 2023 13:56:27 CST</pubDate>
    </item>
    <item>
      <title>管理大型 Postgres 数据库的 3 个技巧</title>
      <link>https://itindex.net/detail/62662-%E7%AE%A1%E7%90%86-postgres-%E6%95%B0%E6%8D%AE%E5%BA%93</link>
      <description>&lt;p&gt;  &lt;img alt="" height="720" src="https://img.linux.net.cn/data/attachment/album/202303/06/113049bkunsxun1clzuca8.jpg" width="1280"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;blockquote&gt;
  &lt;p&gt;在处理庞大的数据库时，请尝试这些方便的解决方案，以解决常见的问题。&lt;/p&gt;
&lt;/blockquote&gt;
 &lt;p&gt;关系型数据库 PostgreSQL（也被称为 Postgres）已经越来越流行，全球各地的企业和公共部门都在使用它。随着这种广泛的采用，数据库已经变得比以前更大了。在 Crunchy Data，我们经常与 20TB 以上的数据库打交道，而且我们现有的数据库还在继续增长。我的同事 David Christensen 和我收集了一些关于管理拥有巨大表的数据库的技巧。&lt;/p&gt;
 &lt;h3&gt;大表&lt;/h3&gt;
 &lt;p&gt;生产数据库通常由许多具有不同数据、大小和模式的表组成。常见的情况是，最终有一个巨大的、无序的数据库表，远远大于你数据库中的任何其他表。这个表经常存储活动日志或有时间戳的事件，而且对你的应用或用户来说是必要的。&lt;/p&gt;
 &lt;p&gt;真正的大表会因为很多原因造成挑战，但一个常见的原因是锁。对表的定期维护往往需要锁，但对大表的锁可能会使你的应用瘫痪，或导致堵塞和许多令人头痛的问题。我有一些做基本维护的技巧，比如添加列或索引，同时避免长期运行的锁。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;添加索引的问题&lt;/strong&gt;：在创建索引的过程中锁住表。如果你有一个庞大的表，这可能需要几个小时。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;CREATE INDEX ON customers (last_name)
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;方案&lt;/strong&gt;：使用   &lt;code&gt;CREATE INDEX CONCURRENTLY&lt;/code&gt; 功能。这种方法将索引创建分成两部分，一部分是短暂的锁定，以创建索引，立即开始跟踪变化，但尽量减少应用阻塞，然后是完全建立该索引，之后查询可以开始使用它。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;CREATE INDEX CONCURRENTLY ON customers (last_name)
&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;添加列&lt;/h3&gt;
 &lt;p&gt;在数据库的使用过程中，添加列是一个常见的请求，但是对于一个巨大的表来说，这可能是很棘手的，同样是由于锁的问题。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;问题&lt;/strong&gt;：当你添加一个新的默认值为一个函数的列时，Postgres 需要重写表。对于大表，这可能需要几个小时。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;方案&lt;/strong&gt;：将操作拆分为多条基本语句，总效果一致，但控制锁的时间。&lt;/p&gt;
 &lt;p&gt;添加列：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;ALTER TABLE all_my_exes ADD COLUMN location text
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;添加默认值：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;ALTER TABLE all_my_exes ALTER COLUMN location SET DEFAULT texas()
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;使用   &lt;code&gt;UPDATE&lt;/code&gt; 来添加默认值：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;UPDATE all_my_exes SET location = DEFAULT
&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;添加约束条件&lt;/h3&gt;
 &lt;p&gt;  &lt;strong&gt;问题&lt;/strong&gt;: 你想添加一个用于数据验证的检查约束。但是如果你使用直接的方法来添加约束，它将锁定表，同时验证表中的所有现有数据。另外，如果在验证的任何时候出现错误，它将回滚。&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;ALTER TABLE favorite_bands ADD CONSTRAINT name_check CHECK (name = &amp;apos;Led Zeppelin&amp;apos;)
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;  &lt;strong&gt;方案&lt;/strong&gt;：告诉 Postgres 这个约束，但不要验证它。在第二步中进行验证。这将在第一步中进行短暂的锁定，确保所有新的/修改过的行都符合约束条件，然后在另一步骤中进行验证，以确认所有现有的数据都通过约束条件。&lt;/p&gt;
 &lt;p&gt;告诉 Postgres 这个约束，但不要强制执行它：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;ALTER TABLE favorite_bands ADD CONSTRAINT name_check CHECK (name = &amp;apos;Led Zeppelin&amp;apos;) NOT VALID
&lt;/code&gt;&lt;/pre&gt;
 &lt;p&gt;然后在创建后  &lt;strong&gt;验证&lt;/strong&gt;它：&lt;/p&gt;
 &lt;pre&gt;  &lt;code&gt;ALTER TABLE favorite_bands VALIDATE CONSTRAINT name_check
&lt;/code&gt;&lt;/pre&gt;
 &lt;h3&gt;想了解更多？&lt;/h3&gt;
 &lt;p&gt;David Christensen 和我将在 3 月 9 号到 10 到在加州帕萨迪纳参加 SCaLE 的 Postgres Days。很多来自 Postgres 社区的优秀人士也会在那里。加入我们吧！&lt;/p&gt;
 &lt;hr&gt;&lt;/hr&gt;
 &lt;p&gt;via:   &lt;a href="https://opensource.com/article/23/2/manage-large-postgres-databases"&gt;https://opensource.com/article/23/2/manage-large-postgres-databases&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;作者：  &lt;a href="https://opensource.com/users/elizabethchristensencrunchydatacom"&gt;Elizabeth Garrett Christensen&lt;/a&gt; 选题：  &lt;a href="https://github.com/lkxed/"&gt;lkxed&lt;/a&gt; 译者：  &lt;a href="https://github.com/geekpi"&gt;geekpi&lt;/a&gt; 校对：  &lt;a href="https://github.com/wxy"&gt;wxy&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;本文由   &lt;a href="https://github.com/LCTT/TranslateProject"&gt;LCTT&lt;/a&gt; 原创编译，  &lt;a href="https://linux.cn/"&gt;Linux中国&lt;/a&gt; 荣誉推出&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62662-%E7%AE%A1%E7%90%86-postgres-%E6%95%B0%E6%8D%AE%E5%BA%93</guid>
      <pubDate>Mon, 06 Mar 2023 11:30:50 CST</pubDate>
    </item>
    <item>
      <title>火山引擎 DataLeap：揭秘字节跳动数据血缘架构演进之路</title>
      <link>https://itindex.net/detail/62650-%E7%81%AB%E5%B1%B1-%E5%BC%95%E6%93%8E-dataleap</link>
      <description>&lt;blockquote&gt;
  &lt;p&gt;更多技术交流、求职机会，欢迎关注   &lt;strong&gt;字节跳动数据平台微信公众号，回复【1】进入官方交流群&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
 &lt;p&gt;DataLeap 是火山引擎数智平台 VeDI 旗下的大数据研发治理套件产品，帮助用户快速完成数据集成、开发、运维、治理、资产、安全等全套数据中台建设，降低工作成本和数据维护成本、挖掘数据价值、为企业决策提供数据支撑。&lt;/p&gt;
 &lt;p&gt;数据血缘是帮助用户找数据、理解数据以及使数据发挥价值的基础能力。基于字节跳动内部沉淀的数据治理经验，火山引擎 DataLeap 具备完备的数据血缘能力，本文将从数据血缘应用背景、发展概况、架构演讲以及未来展望四部分，为大家介绍数据血缘在字节跳动进化史。&lt;/p&gt;
 &lt;h1&gt;背景介绍&lt;/h1&gt;
 &lt;h2&gt;1. 数据血缘是数据资产平台的重要能力之一&lt;/h2&gt;
 &lt;p&gt;在火山引擎 DataLeap 中，数据资产平台主要提供元数据搜索、展示、资产管理以及知识发现能力。在数据资产平台中，数据血缘是帮助用户找数据、理解数据以及使数据发挥价值的重要基础能力。&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/30f9b975e1d64d47ba3affcabb2f4723~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h2&gt;2. 字节跳动的数据链路情况&lt;/h2&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8dfcd459d71840b9be9f2fed8cf465bb~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;h3&gt;数据来源&lt;/h3&gt;
 &lt;p&gt;在字节跳动，数据主要来源于以下两部分：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;第一，埋点数据：&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;主要来自 APP 端和 Web 端。经过日志采集后，这类数据最终进入到消息队列中。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;第二，业务数据：&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;该类数据一般以在线形式存储，如 RDS 等。&lt;/p&gt;
 &lt;p&gt;中间部分是以 Hive 为代表的离线数仓：&lt;/p&gt;
 &lt;p&gt;该类数据主要来自消息队列或者在线存储，经过数据集成服务把数据导入离线数仓。经过离线数仓的数据加工逻辑，流转到以 ClickHouse 为代表的 OLAP 引擎。&lt;/p&gt;
 &lt;p&gt;另外，在消息队列部分，还会通过 Flink 任务或者其他任务对 Topic 分流，因此上图也展现了一个回指的箭头。&lt;/p&gt;
 &lt;h3&gt;数据去向&lt;/h3&gt;
 &lt;p&gt;主要以指标系统和报表系统为代表。指标系统包含重要且常用的业务指标，如抖音的日活等。报表系统是把指标以可视化形式展现出来。&lt;/p&gt;
 &lt;h3&gt;数据服务&lt;/h3&gt;
 &lt;p&gt;主要通过 API 提供数据，具体而言，从消息队列、在线存储、下游消费以及上图右侧所示的数据流转，都涵盖在数据血缘范围内。&lt;/p&gt;
 &lt;h1&gt;血缘发展概况&lt;/h1&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/76a4db0192d14c459b60aeca5bc8b590~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;接下来介绍血缘在字节跳动的三个发展阶段。&lt;/p&gt;
 &lt;h2&gt;第一阶段：2019 年左右开始&lt;/h2&gt;
 &lt;p&gt;第一阶段主要提供数据血缘基础能力，以 Hive 和 ClickHouse 为代表，支持表级血缘、字段血缘，涉及 10+元数据。&lt;/p&gt;
 &lt;h2&gt;第二阶段：从 2020 年初开始&lt;/h2&gt;
 &lt;p&gt;第二阶段引入了任务血缘，同时支持的元数据类型进行扩充，达到 15+。&lt;/p&gt;
 &lt;h2&gt;第三阶段：从 2021 年上半年至今&lt;/h2&gt;
 &lt;p&gt;在这一阶段，我们对整个元数据系统（即前文提到的资产平台）进行了 GMA 改造，同步对血缘架构进行全面升级，由此支持了更丰富的功能，具体包括：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;首先，元数据种类扩充到近 30 种且时效性提升。&lt;/strong&gt; 之前以离线方式更新血缘数据，导致数据加工逻辑变化的第二天，血缘才会产生变化。目前，基于近实时的更新方式，数据加工逻辑在 1 分钟内即在血缘中体现。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;其次，新增血缘消费方式的变更通知&lt;/strong&gt;。由于该版本支持实时血缘，业务方产生及时了解血缘变化的需求，变动通知功能就是把血缘变化情况以消息队列的形式告知业务方。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;再次，支持评估血缘质量。&lt;/strong&gt; 新增一条链路，专门服务于血缘数据质量。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;最后，引入标准化接入方式&lt;/strong&gt;。为了减少重复工作、降低血缘接入成本，我们制定了详细的血缘接入标准，业务方数据均以标准化方式接入。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;以上就是整体的发展情况，目前处于第三个版本当中。&lt;/p&gt;
 &lt;h1&gt;数据血缘架构的演进&lt;/h1&gt;
 &lt;p&gt;接下来介绍血缘架构的演进。&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;   &lt;strong&gt;第一版血缘架构：建立血缘基本能力，初探使用场景&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
 &lt;h3&gt;血缘架构&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/21fe4ad105cf496b89a5a1be52ca4b03~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;在数据来源方面，目前血缘主要包括两个数据来源（见上图左上角）：&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;第一，数据开发平台：&lt;/strong&gt; 用户在开发平台写任务，并对数据加工，由此产生血缘数据。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;第二，追踪数据：&lt;/strong&gt; 第三方平台（即任务平台）对用户埋点等数据进行计算，也会产生血缘信息。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;在血缘加工任务方面（见上图中间部分）：&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;这部分会对任务进行血缘解析，产生血缘快照文件。由于第一版采用离线方式运行，每天该血缘任务均会生成对应的血缘快照文件。我们通过对比前后两天的血缘快照文件，来获取血缘的变更情况，然后把这些变更加载到图中。&lt;/p&gt;
 &lt;p&gt;除此之外，血缘中涉及的元数据会冗余一份，并存储到图里。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;在血缘存储方面（见上图右边部分），除了图数据库之外，血缘本身也会依赖元数据的存储，如 Mysql 以及索引类存储。&lt;/li&gt;
  &lt;li&gt;在血缘消费层面，第一版只支持通过 API 进行消费。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;  &lt;strong&gt;最后总结该版本的三个关键点：&lt;/strong&gt;&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;血缘数据每天以离线方式   &lt;strong&gt;全量更新&lt;/strong&gt;。&lt;/li&gt;
  &lt;li&gt;通过对比血缘快照来判断血缘更新操作，后面将为大家详细解答为什么要通过对比的方式。&lt;/li&gt;
  &lt;li&gt;冗余一份元数据存储到图数据库中。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;存储模型&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b352df33839b4863960a5fad2ca1259f~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;图中上半部分为  &lt;strong&gt;表级血缘&lt;/strong&gt;，只包括一种类型节点，即表节点，比如 Hive 表、 ClickHouse 表等。&lt;/p&gt;
 &lt;p&gt;图中下半部分为  &lt;strong&gt;字段血缘&lt;/strong&gt;，第一版主要是提供构建血缘的基本能力，因此用彼此分离的两张图来实现。由于血缘中元数据进行了冗余，每个图里面的每个节点里面都存储表相关的元数据，包括业务信息以及其他信息。&lt;/p&gt;
 &lt;p&gt;除此之外，我们会预先计算一些统计信息，保存到图的节点中，如当前节点下游总节点数量、下游层级数量等。&lt;/p&gt;
 &lt;p&gt;采用预先计算的目的是为了“用空间换时间”，在产品对外展示的功能上可能要露出数据信息，如果从图里实时查询可能影响性能，因此采用空间换时间的方式来支持产品的展示。&lt;/p&gt;
 &lt;ol start="2"&gt;
  &lt;li&gt;   &lt;strong&gt;第二版血缘架构：血缘价值逐步体现，使用场景拓宽&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
 &lt;h3&gt;血缘架构&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fd42cd0d1ea9470a8e624119bf741d1f~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;经过 1 年的使用，血缘在数据资产中的价值逐步体现，且不断有应用场景落地，由此我们进行了第二版本升级。升级点具体包括：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;
   &lt;p&gt;    &lt;strong&gt;第一，去除第一版本中元数据冗余。&lt;/strong&gt; 元数据冗余在图提升了性能，但是可能导致 Metadata Store 的元数据不一致，给用户带来困扰。&lt;/p&gt;
&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;    &lt;strong&gt;第二，去掉了预计算的统计信息&lt;/strong&gt;。随着血缘的数据量增多，预计算的信息透出不能给很好辅助用户完成业务判断，且导致任务负担重。比如，即使知道某一节点的下游数据量，还是要拉出所有节点才能进一步分析或决策。&lt;/p&gt;
&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;    &lt;strong&gt;第三，支持一条全新链路&lt;/strong&gt;，在新增链路上，我们把血缘快照文件导入离线数仓，主要应用于两个场景：&lt;/p&gt;
   &lt;p&gt;离线分析场景或全量分析场景。&lt;/p&gt;
   &lt;p&gt;基于离线数仓的血缘数据实现数据    &lt;strong&gt;监控&lt;/strong&gt;，尽早发现血缘异常情况。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;因此，从第二版开始，数据血缘新增了很多离线消费方式。&lt;/p&gt;
 &lt;h3&gt;存储模型&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/39649890787d4f26a38e3ab29dfc7b38~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;第二个版本引入了全新血缘存储模型（如上图所示），并将第一个版本两张图融合成一张图，解决了无法通过表遍历字段血缘的问题。&lt;/p&gt;
 &lt;p&gt;除此之外，第二个版本还  &lt;strong&gt;引入了任务类型节点&lt;/strong&gt;，服务于以下三种遍历场景：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;单纯遍历数据血&lt;/strong&gt;缘，即从数据节点到数据节点。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;数据血缘和任务血缘混合方式&lt;/strong&gt;。&lt;/li&gt;
  &lt;li&gt;单纯   &lt;strong&gt;任务之间血缘关系&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
 &lt;ol start="3"&gt;
  &lt;li&gt;   &lt;strong&gt;第三版血缘架构：血缘成为数据发挥价值的重要基础能力&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
 &lt;h3&gt;血缘架构&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/66c6464985c249b6994c41396725b5e3~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;2021 年初，火山引擎 DataLeap 数据血缘迭代到第三版，也成为公司内部数据发挥价值的重要基础能力。&lt;/p&gt;
 &lt;p&gt;服务于业务方对数据高质量要求，第三版升级点如下：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;血缘数据来源：&lt;/strong&gt; 除了支持两个平台之外，还支持包括报表、第三方用户画像等   &lt;strong&gt;其他平台&lt;/strong&gt; 。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;血缘任务：&lt;/strong&gt; 之前版本只支持每天定时运行的离线调度方式，第三版引入实时消费方式，支持实时解析血缘，并提取通用逻辑，复用离线血缘任务和实时血缘任务。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;血缘解析：&lt;/strong&gt; 不同类型任务需要使用不同解析逻辑。在之前版本中，Hive SQL 任务和 Flink SQL 任务的解析逻辑是集成到血缘任务中。从第三版开始，我们把解析服务拆解成   &lt;strong&gt;可配置的插件&lt;/strong&gt;，实现了插件化。当某一种任务类型的血缘解析逻辑需要调整的时候，只用改动其中一个解析服务，其他解析服务不受影响，同时也让血缘任务更好维护。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;元数据存储统一：&lt;/strong&gt; 只依赖图数据库和索引存储，同时支持从系统中把所有相关的数据导出离线数仓。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;实时消费：&lt;/strong&gt; 血缘发生变更的信息会被同步到消息队列。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;血缘的验证模块：&lt;/strong&gt; 使用方对血缘数据质量有高要求，因此第三版引入   &lt;strong&gt;新的血缘的验证模块&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;验证的前提是要有引擎埋点数据，该埋点数据能清楚知道某一个任务具体读取数据情况、写入数据情况&lt;/p&gt;
 &lt;p&gt;在离线数仓中，通过埋点数据与血缘数据中对比，生成血缘数据质量报表。&lt;/p&gt;
 &lt;p&gt;数据质量报表对血缘消费者开放，消费者能够清晰了解每个血缘链路准确性和覆盖情况。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;血缘标准化接入：&lt;/strong&gt; 即让用户快速接入数据，不用每一种血缘接入都重复写逻辑。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;存储模型&lt;/h3&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7f17b9255a2248ac9813b3e5c3696e84~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;第三版血缘存储模型相对于前两版的升级点如下：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;以任务为中心&lt;/strong&gt;。黄色圆圈为任务节点，数据加工逻辑产生血缘，因此我们把数据加工逻辑抽象为任务节点，血缘的建立则以任务为媒介，任务成为血缘中心。也就是说，表 1、表 2、表 3 之间的血缘，是通过任务 a 完成构建。假设没有任务 a ，则三个表之间的血缘也不存在。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;表血缘和字段血缘模型统一&lt;/strong&gt;，在字段血缘之间没有具体任务的情况下，我们会抽象出虚拟的任务来统一模型。由此，任务和任务之间的血缘采用新的边来表示依赖关系。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h3&gt;重要特性&lt;/h3&gt;
 &lt;h4&gt;增量更新&lt;/h4&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5f7c6797808940b99364f44bbbfb5133~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;在实时血缘基础上，我们还支持增量更新能力，即当某一个任务的加工逻辑发生变化时，只需要更新图中一小部分。&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;血缘创建：&lt;/strong&gt; 数据加工逻辑上线或开始生效，将被抽象为图数据库的操作，即创建一个任务节点和对应的数据节点，并创建两者之间的边。上图例子为表 1、表 2 和任务的边，以及任务和表 3 之间的边。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;血缘删除：数据的加工逻辑发生了下线、删除或不生效。&lt;/strong&gt; 先在图里面查询该任务节点，把任务节点以及关联血缘相关的边删除。血缘存储模型以任务为中心，因此表 1、表 2 和表 3 之间的血缘关系也同步消失，这部分血缘即被删除。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;血缘更新：任务本身没有发生上线或下线，但计算逻辑发生变化。&lt;/strong&gt; 例如，原本血缘关系是表 1、表 2 生成表 3，现在变成了表 2、表 4 生成表 3。我们需要做的如下：&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;解析出最新血缘状态，即表 2、表 4 到表 3 的血缘关系，与当前血缘状态做对比（主要对比该任务 a 相关的边），上图例子是入边发生变化，那么删除其中一条边，构建另外一条边，即可完成该任务节点的血缘更新。&lt;/p&gt;
 &lt;p&gt;如果面临以上血缘关系变化，但是没有该任务节点，应该执行哪些操作来更新血缘？由于只有血缘最新状态和当前状态，没有任务节点去获取最小单位的血缘关系，所以只能进行全量血缘或全图对比，才能得出边的变化情况，再更新到图数据库中。如果不进行全量血缘或全图对比，无法知晓如何删除条和创建条，导致血缘无法更新。这也是前两个版本需要进行血缘快照对比的原因。&lt;/p&gt;
 &lt;h4&gt;血缘标准化&lt;/h4&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/44b9c9dd5c974287834aca2baebd4045~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;在火山引擎 DataLeap 中，通常把血缘数据接入抽象成一个 ETL 。&lt;/p&gt;
 &lt;p&gt;首先，血缘数据来源，即第三方平台血缘相关的数据，通常是一个数据加工逻辑或者称为任务。接着，对这些任务完成 KeyBy 操作，并与数据资产平台的任务信息做对比，确定如何进行任何创建、删除和更新。&lt;/p&gt;
 &lt;p&gt;在再完成过滤操作之后， 由 Lineage Parser 对创建、更新等任务进行血缘解析，得出血缘结果之后会生成表示图相关操作的 Event，最终通过 Sink 把数据写入到数据资产平台中。&lt;/p&gt;
 &lt;p&gt;上图绿色和蓝色分别表示：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;蓝色：对不同血缘接入过程的逻辑一致，可抽象出来并复用。&lt;/li&gt;
  &lt;li&gt;绿色：不同血缘的实现情况不一样。例如，某一个平台为拉取数据，另外一个平台通过其他方式获取数据，导致三个部分不一样，因此我们抽取特殊部分，复用共同部分。除此之外，我们还提供通用 SDK，串联整个血缘接入流程，使得接入新的血缘时，只需要实现绿色组件。&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;目前，字节跳动内部业务已经可以使用 SDK 轻松接入血缘。&lt;/p&gt;
 &lt;h4&gt;数据血缘质量-覆盖率&lt;/h4&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4865fce5187945d4a4cf08e9463eafcc~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;当血缘发展到一定阶段，业务方不止关心血缘覆盖情况、支持情况，还关心血缘数据质量情况。因此，第三版本透出血缘质量相关指标——覆盖率和准确率。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;覆盖率：血缘覆盖的数据资产数占关注的资产数量占比&lt;/strong&gt;。&lt;/p&gt;
 &lt;p&gt;关注的数据资产一般指，  &lt;strong&gt;有生产任务或有生产行为的资产&lt;/strong&gt;。上图虚线圆圈，如 Table 9，用户创建该表后没有生产行为，因此也不会产生血缘，在计算中将被剔除掉。上图实线圆圈，表示有生产行为或有任务读取，则被认为是关注的资产。关注的数据资产被血缘覆盖的占比，即覆盖率。&lt;/p&gt;
 &lt;p&gt;以上图为例，在 10 张表中，由于有任务与 Table 1 ~ 8 关联，因此判定有血缘。 Table 10，它与 Task-D 之间的连线是虚线，表示本来它应该有血缘，但是实际上血缘任务没把这个血缘关系解析出来，那么我们就认为这个 Table 10 是没有被血缘覆盖的。整体上被血缘覆盖的资产就是表 1 ~ 8。除了 Table 9 之外，其他的都是关注的资产，那么血缘覆盖的资产占比就是 8/9。也就是图上蓝色的这第 8 个除以蓝色的 8 个加上 Table 10，就是 9 个，所以这个覆盖率就是 88%。&lt;/p&gt;
 &lt;h4&gt;数据血缘质量-准确率&lt;/h4&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2f1aa55bf9ec485b8249c8120e2f64a3~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;覆盖血缘不一定是正确的，所以我们还定义了准确率指标，即血缘准确的任务数/同类型的任务数。&lt;/p&gt;
 &lt;p&gt;举个例子，假设任务 c 的血缘应该是 Table 5、Table6 生成 Table 7，但实际上被遗漏，没有被解析（虚线表示），导致任务 c 的血缘不准确。也存在其他情况缺失或多余情况，导致血缘不准确。&lt;/p&gt;
 &lt;p&gt;在上图中，同类型任务包含 4 个，即 a、b、c、d。那么，准确的血缘解析只有 a、b，因此准确率占比为 2/4 = 50%。&lt;/p&gt;
 &lt;p&gt;在火山引擎 DataLeap 中，由于血缘来源是任务，因此我们以任务的视角来看待血缘准确率。&lt;/p&gt;
 &lt;h4&gt;血缘质量-字节现状&lt;/h4&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0aef1c364df0496dba6b46252519e849~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;在覆盖率部分，目前 Hive 和 ClickHouse 元数据覆盖度较高，分别达到 98%、96%。对于实时元数据，如 Kafka ，相关 Topic 覆盖 70%，其他元数据则稍低。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;在准确率部分，我们区分任务类型做准确性解析&lt;/strong&gt;。如 DTS 数据集成任务达到 99%以上，Hive SQL 任务、 Flink SQL 任务是 97%、81% 左右。&lt;/p&gt;
 &lt;h1&gt;血缘架构对比&lt;/h1&gt;
 &lt;p&gt;  &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d260c19ac3944206bd4d7621dc3da7ec~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;上图为三个版本对比情况：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;strong&gt;血缘的消费方式&lt;/strong&gt;：第一版只支持 API 的方式，用户需要在数据资产平台上查看血缘信息；第二版支持离线数仓，让用户可以全量分析血缘；第三版支持消息队列，使用户可以获取血缘增量的变化。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;增量更新：&lt;/strong&gt; 第三版开始支持增量更新。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;血缘任务：&lt;/strong&gt; 第二个版本开始支持任务血缘，第三个版本支持数据质量。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;元数据存储统一：&lt;/strong&gt; 第三版进行了元数据架构升级，使得元数据和血缘存储在同一个地方。&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;新血缘接入耗时：&lt;/strong&gt; 前两个版本大概需要花费 7-10 天左右。第三版本引入标准化，外部业务方或字节内部用标准化流程，实现 3、4 天左右完成开发、测试、上线。&lt;/li&gt;
&lt;/ul&gt;
 &lt;h1&gt;未来展望&lt;/h1&gt;
 &lt;p&gt;  &lt;strong&gt;第一，持续对架构和流程进行精简。&lt;/strong&gt; 目前，血缘任务分为离线和实时两部分，但没有完全统一。在插件化、横向扩展等方面也需要加强。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;第二，生态化支持。&lt;/strong&gt; 目前支持公司内部的元数据，未来计划拓展对开源或外部元数据的支持。在  &lt;strong&gt;血缘标准化方面&lt;/strong&gt;，提供一站式数据血缘能力，作为基础能力平台为业务方提供服务。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;第三，提升数据质量。&lt;/strong&gt; 除了血缘数量，还需要持续提升质量。同时由于数据链路复杂，导致链路问题排查异常困难，未来我们也会支持快速诊断。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;最后，支持智能化场景。&lt;/strong&gt; 结合元数仓等数据，提供包含关键链路梳理在内的智能化能力。目前，当业务方发现数据有问题之后，主要通过按照血缘数据一个一个排查方式解决，导致效率低下。未来，我们将考虑透出血缘关键链路，提升排查效率。&lt;/p&gt;
 &lt;p&gt;以上介绍的数据血缘能力和实践，目前大部分已通过火山引擎 DataLeap 对外提供服务。&lt;/p&gt;
 &lt;p&gt;点击跳转   &lt;a href="https://www.volcengine.com/product/dataleap/?utm_source=juejin_dp&amp;utm_medium=article&amp;utm_term=juejin_readmore&amp;utm_campaign=20230302&amp;utm_content=dataleap"&gt;大数据研发治理套件 DataLeap&lt;/a&gt; 了解更多&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62650-%E7%81%AB%E5%B1%B1-%E5%BC%95%E6%93%8E-dataleap</guid>
      <pubDate>Thu, 02 Mar 2023 13:43:09 CST</pubDate>
    </item>
    <item>
      <title>Flink CDC 如何简化实时数据入湖入仓</title>
      <link>https://itindex.net/detail/62643-flink-cdc-%E5%AE%9E%E6%97%B6</link>
      <description>&lt;h2&gt;  &lt;a href="http://wuchong.me/#&amp;#19968;&amp;#12289;Flink-CDC-&amp;#20171;&amp;#32461;" title="&amp;#19968;&amp;#12289;Flink CDC &amp;#20171;&amp;#32461;"&gt;&lt;/a&gt;一、Flink CDC 介绍&lt;/h2&gt; &lt;p&gt;从广义的概念上讲，能够捕获数据变更的技术, 我们都可以称为 CDC 技术。通常我们说的 CDC 技术是一种用于捕获数据库中数据变更的技术。CDC 技术应用场景也非常广泛，包括：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;strong&gt;数据分发&lt;/strong&gt;，将一个数据源分发给多个下游，常用于业务解耦、微服务。&lt;/li&gt;  &lt;li&gt;   &lt;strong&gt;数据集成&lt;/strong&gt;，将分散异构的数据源集成到数据仓库中，消除数据孤岛，便于后续的分析。&lt;/li&gt;  &lt;li&gt;   &lt;strong&gt;数据迁移&lt;/strong&gt;，常用于数据库备份、容灾等。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221934643-e6cee2ef-e4ba-4cb1-b85a-2f8a2e7940bc.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;Flink CDC 基于数据库日志的 Change Data Caputre 技术，实现了全量和增量的一体化读取能力，并借助 Flink 优秀的管道能力和丰富的上下游生态，支持捕获多种数据库的变更，并将这些变更实时同步到下游存储。&lt;/p&gt; &lt;p&gt;目前，Flink CDC 的上游已经支持了 MySQL、MariaDB、PG、Oracle、MongoDB 等丰富的数据源，对 Oceanbase、TiDB、SQLServer 等数据库的支持也已经在社区的规划中。 &lt;/p&gt; &lt;p&gt;Flink CDC 的下游则更加丰富，支持写入 Kafka、Pulsar 消息队列，也支持写入 Hudi、Iceberg 等数据湖，还支持写入各种数据仓库。&lt;/p&gt; &lt;p&gt;同时，通过 Flink SQL 原生支持的 Changelog 机制，可以让 CDC 数据的加工变得非常简单。用户可以通过 SQL 便能实现数据库全量和增量数据的清洗、打宽、聚合等操作，极大地降低了用户门槛。 此外， Flink DataStream API 支持用户编写代码实现自定义逻辑，给用户提供了深度定制业务的自由度。&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221934717-2d4de44c-7eb3-47a0-ac7e-a95c2afba0d6.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;Flink CDC 技术的核心是支持将表中的全量数据和增量数据做实时一致性的同步与加工，让用户可以方便地获每张表的实时一致性快照。比如一张表中有历史的全量业务数据，也有增量的业务数据在源源不断写入，更新。Flink CDC 会实时抓取增量的更新记录，实时提供与数据库中一致性的快照，如果是更新记录，会更新已有数据。如果是插入记录，则会追加到已有数据，整个过程中，Flink CDC 提供了一致性保障，即不重不丢。&lt;/p&gt; &lt;p&gt;那么 Flink CDC 技术能给现有的数据入仓入湖架构带来什么样的改变呢？我们可以先来看看传统数据入仓的架构。&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221934773-0366ae9a-180c-41ad-956b-add6254772f2.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;在早期的数据入仓架构中，一般会每天 SELECT 全量数据导入数仓后再做离线分析。这种架构有几个明显的缺点：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;每天查询全量的业务表会影响业务自身稳定性。&lt;/li&gt;  &lt;li&gt;离线天级别调度的方式，天级别的产出时效性差。&lt;/li&gt;  &lt;li&gt;基于查询方式，随着数据量的不断增长，对数据库的压力也会不断增加，架构性能瓶颈明显。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221934809-1c4fdbe9-14e8-495e-9629-0f6d30d9208a.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;到了数据仓库的 2.0 时代，数据入仓进化到了 Lambda 架构，增加了实时同步导入增量的链路。整体来说，Lambda 架构的扩展性更好，也不再影响业务的稳定性，但仍然存在一些问题：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;依赖离线的定时合并，只能做到小时级产出，延时还是较大；&lt;/li&gt;  &lt;li&gt;全量和增量是割裂的两条链路； &lt;/li&gt;  &lt;li&gt;整个架构链路长，需要维护的组件比较多，该架构的全量链路需要维护 DataX 或 Sqoop 组件，增量链路要维护 Canal 和 Kafka - 组件，同时还要维护全量和增量的定时合并链路。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221934838-24bc9edf-2c68-4dfe-8b40-002d101b28cf.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;对于传统数据入仓架构存在的问题，Flink CDC 的出现为数据入湖架构提供了一些新思路。借助 Flink CDC 技术的全增量一体化实时同步能力，结合数据湖提供的更新能力，整个架构变得非常简洁。我们可以直接使用 Flink CDC 读取 MySQL 的全量和增量数据，并直接写入和更新到 Hudi 中。&lt;/p&gt; &lt;p&gt;这种简洁的架构有着明显的优势。首先，不会影响业务稳定性。其次，提供分钟级产出，满足近实时业务的需求。同时，全量和增量的链路完成了统一，实现了一体化同步。最后，该架构的链路更短，需要维护的组件更少。&lt;/p&gt; &lt;h2&gt;  &lt;a href="http://wuchong.me/#&amp;#20108;&amp;#12289;Flink-CDC-&amp;#30340;&amp;#26680;&amp;#24515;&amp;#29305;&amp;#24615;" title="&amp;#20108;&amp;#12289;Flink CDC &amp;#30340;&amp;#26680;&amp;#24515;&amp;#29305;&amp;#24615;"&gt;&lt;/a&gt;二、Flink CDC 的核心特性&lt;/h2&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221934889-6df96fc4-db4e-4ef9-b5f3-0587937929ac.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;Flink CDC 的核心特性可以分成四个部分：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;一是通过增量快照读取算法，实现了无锁读取，并发读取，断点续传等功能。&lt;/li&gt;  &lt;li&gt;二是设计上对入湖友好，提升了 CDC 数据入湖的稳定性。&lt;/li&gt;  &lt;li&gt;三是支持异构数据源的融合，能方便地做 Streaming ETL的加工。&lt;/li&gt;  &lt;li&gt;四是支持分库分表合并入湖。接下来我们会分别介绍下这几个特性。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221934930-ab4365be-f221-49d6-84c5-42a543658e1f.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;在 Flink CDC 1.x 版本时，MySQL CDC 存在三大痛点，影响了生产可用性。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;一是 MySQL CDC 需要通过全局锁去保证全量和增量数据的一致性，而 MySQL 的全局锁会影响线上业务。&lt;/li&gt;  &lt;li&gt;二是只支持单并发读取，大表读取非常耗时。&lt;/li&gt;  &lt;li&gt;三是在全量同步阶段，作业失败后只能重新同步，稳定性较差。针对这些问题，Flink CDC 社区提出了 “增量快照读取算法”，同时实现了无锁读取、并行读取、断点续传等能力，一并解决了上述痛点。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221934963-fc0ee42f-8a06-425e-99f5-39b517dcb117.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;简单来说，增量快照读取算法的核心思路就是在全量读取阶段把表分成一个个 chunk 进行并发读取，在进入增量阶段后只需要一个 task 进行单并发读取 binlog 日志，在全量和增量自动切换时，通过无锁算法保障一致性。这种设计在提高读取效率的同时，进一步节约了资源。实现了全增量一体化的数据同步。这也是流批一体道路上一个非常重要的落地。 &lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221935011-e02add2d-d3b9-4493-8bed-b40a597b16ab.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;Flink CDC 是一个流式入湖友好的框架。在早期版本的 Flink CDC 设计中，没有考虑数据湖场景，全量阶段不支持 Checkpoint，全量数据会在一个 Checkpoint 中处理，这对依靠 Checkpoint 提交数据的数据湖很不友好。Flink CDC 2.0 设计之初考虑了数据湖场景，是一种流式入湖友好的设计。设计上将全量数据进行分片，Flink CDC 可以将 checkpoint 粒度从表粒度优化到 chunk 粒度，大大减少了数据湖写入时的 Buffer 使用，对数据湖写入更加友好。&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221935048-73e9bda1-03d3-4300-9137-5b74e0ce06c2.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;Flink CDC 区别于其他数据集成框架的一个核心点，就是在于 Flink 提供的流批一体计算能力。这使得 Flink CDC 成为了一个完整的 ETL 工具，不仅仅拥有出色的 E 和 L 的能力，还拥有强大的 Transformation 能力。因此我们可以轻松实现基于异构数据源的数据湖构建。&lt;/p&gt; &lt;p&gt;在上图左侧的 SQL 中，我们可以将 MySQL 中的实时产品表、实时订单表和 PostgreSQL 中的实时物流信息表进行实时关联，即 Streaming Join，关联后的结果实时更新到 Hudi 中，非常轻松地完成异构数据源的数据湖构建。&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221935142-0b288405-9b50-416b-8b83-3644d23b1ebf.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;在 OLTP 系统中，为了解决单表数据量大的问题，通常采用分库分表的方式将单个大表进行拆分以提高系统的吞吐量。但是为了方便数据分析，通常需要将分库分表拆分出的表在同步到数据仓库、数据湖时，再合并成一个大表。Flink CDC 可以轻松完成这个任务。&lt;/p&gt; &lt;p&gt;在上图左侧的 SQL 中，我们声明了一张 user_source 表去捕获所有 user 分库分表的数据，我们通过表的配置项 database-name、table-name 使用正则表达式来匹配这些表。并且，user_source 表也定义了两个 metadata 列来区分数据是来自哪个库和表。在 Hudi 表的声明中，我们将库名、表名和原表的主键声明成 Hudi 中的联合主键。在声明完两张表后，一条简单的 INSERT INTO 语句就可以将所有分库分表的数据合并写入 Hudi 的一张表中，完成基于分库分表的数据湖构建，方便后续在湖上的统一分析。&lt;/p&gt; &lt;h2&gt;  &lt;a href="http://wuchong.me/#&amp;#19977;&amp;#12289;Flink-CDC-&amp;#30340;&amp;#24320;&amp;#28304;&amp;#29983;&amp;#24577;" title="&amp;#19977;&amp;#12289;Flink CDC &amp;#30340;&amp;#24320;&amp;#28304;&amp;#29983;&amp;#24577;"&gt;&lt;/a&gt;三、Flink CDC 的开源生态&lt;/h2&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221935195-71903539-60ea-4aba-bd2f-c67f7d5f72f5.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;Flink CDC 是一个独立的开源项目，项目代码托管在   &lt;a href="https://github.com/ververica/flink-cdc-connectors" rel="noopener" target="_blank"&gt;GitHub&lt;/a&gt; 上。采取小步快跑的发布节奏，今年社区已经发布了 5 个版本。1.x 系列的三个版本推出了一些小功能；2.0 版本 MySQL CDC 支持了无锁读取、并发读取、断点续传等高级功能，commits 达到了 91 个，贡献者达到了 15 人；2.1 版本则支持了 Oracle、MongoDB 数据库，commits 达到了115个，贡献者达到了28人。社区的 commits 和 贡献者增长非常明显。&lt;/p&gt; &lt;p&gt;文档和帮助手册也是开源社区非常重要的一部分，为了更好地帮助用户，Flink CDC 社区推出了版本化的文档网站，如   &lt;a href="https://ververica.github.io/flink-cdc-connectors/release-2.1/" rel="noopener" target="_blank"&gt;2.1 版本的文档&lt;/a&gt; 。文档中还提供了很多快速入门的教程，用户只要有个 Docker 环境就能上手 Flink CDC。此外，还提供了   &lt;a href="https://github.com/ververica/flink-cdc-connectors/wiki/FAQ(ZH" rel="noopener" target="_blank"&gt;FAQ 指导手册&lt;/a&gt;)，快速解决用户遇到的常见问题。&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221935245-3e7cd218-6b7d-4dc9-a675-3af6f70dc93d.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;在过去的 2021 年，Flink CDC 社区取得了迅速的发展，GitHub 的 PR 和 issue 相当活跃，GitHub Star 更是年度同比增长 330%。&lt;/p&gt; &lt;h2&gt;  &lt;a href="http://wuchong.me/#&amp;#22235;&amp;#12289;Flink-CDC-&amp;#22312;&amp;#38463;&amp;#37324;&amp;#24052;&amp;#24052;&amp;#30340;&amp;#23454;&amp;#36341;&amp;#21644;&amp;#25913;&amp;#36827;" title="&amp;#22235;&amp;#12289;Flink CDC &amp;#22312;&amp;#38463;&amp;#37324;&amp;#24052;&amp;#24052;&amp;#30340;&amp;#23454;&amp;#36341;&amp;#21644;&amp;#25913;&amp;#36827;"&gt;&lt;/a&gt;四、Flink CDC 在阿里巴巴的实践和改进&lt;/h2&gt; &lt;p&gt;Flink CDC 入湖入仓在阿里巴巴也有大规模的实践和落地，过程中也遇到了一些痛点和挑战。我们会介绍下我们是如何改进和解决的。&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221935292-6f35e6d7-f16f-4f2d-a002-5384c5b09009.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;我们先来看下 CDC 入湖遇到的一些痛点和挑战。这是某个用户原有的 CDC 数据入湖架构，分为两个链路：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;有一个全量同步作业做一次性的全量数据拉取；&lt;/li&gt;  &lt;li&gt;还有一个增量作业通过 Canal 和处理引擎将 Binlog 数据准实时地同步到 Hudi 表中。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;这个架构虽然利用了 Hudi 的更新能力，无需周期性地调度全量合并任务，能做到分钟级延迟。但是全量和增量仍是割裂的两个作业，全量和增量的切换仍需要人工的介入，并且需要指定一个准确的增量启动位点，否则的话就会有丢失数据的风险。可以看到这种架构是流批割裂的，并不是一个统一的整体。刚刚雪尽也介绍了 Flink CDC 最大的一个优势之一就是全增量的自动切换，所以我们用 Flink CDC 替换了用户原有的入湖架构。&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221935344-0c55c457-efa2-43a9-89b9-8dfa03811f4d.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;但是用户用了 Flink CDC 后，  &lt;strong&gt;遇到的第一个痛点&lt;/strong&gt;就是需要将 MySQL 的 DDL 手工映射成 Flink 的 DDL。手工映射表结构是比较繁琐的，尤其是当表和字段数非常多的时候。而且手工映射也容易出错，比如 说 MySQL 的 BIGINT UNSINGED，它不能映射成 Flink 的 BIGINT，而是要映射成 DECIMAL(20)。 如果系统能自动帮助用户自动去映射表结构就会简单安全很多。&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221935361-936fc8f9-5668-4829-9041-d6986d05bec8.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;用户遇到的  &lt;strong&gt;另一个痛点&lt;/strong&gt;是表结构的变更导致入湖链路难以维护。例如用户有一张表，原先有 id 和 name 两列，突然增加了一列 Address。新增的这一列数据可能就无法同步到数据湖中，甚至导致入湖链路的挂掉，影响稳定性。除了加列的变更，还可能会有删列、类型变更等等。国外的 Fivetran 做过一个  &lt;a href="https://fivetran.com/blog/analyst-survey" rel="noopener" target="_blank"&gt;调研报告&lt;/a&gt; ，发现 60% 的公司，schema 每个月都会变化，30% 每周都会变化。这说明基本每个公司都会面临 schema 变更带来的数据集成上的挑战。&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221935387-1b7f0ce4-cfb7-4c33-bee4-26534c2b8d6e.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;最后一个是整库入湖的挑战&lt;/strong&gt;。因为用户主要使用 SQL，这就需要为每个表的数据同步链路定义一个 INSERT INTO 语句。有些用户的 MySQL 实例中甚至有上千张的业务表，用户就要写上千个 INSERT INTO 语句。更令人望而生却的是，每一个 INSERT INTO 任务都会创建至少一个数据库连接，读取一次 Binlog 数据。千表入湖的话就需要上千个连接，上千次的 Binlog 重复读取。这就会对 MySQL 和网络造成很大的压力。&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221935471-c4c1578f-738a-4e81-83c8-ceab33bfee82.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;刚刚我们介绍了 CDC 数据入湖的很多痛点和挑战，我们可以站在用户的角度想一想，数据库入湖这个场景用户到底想要的是什么呢？我们可以先把中间的数据集成系统看成一个黑盒，用户会期望这个黑盒提供什么样的能力来简化入湖的工作呢？&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221935553-7ba2fc2e-3ef5-4226-8dc1-8b315d353c90.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;首先，用户肯定想把数据库中全量和增量的数据都同步过去，这就需要这个系统具有全增量一体化、全增量自动切换的能力，而不是割裂的全量链路 + 增量链路。&lt;/li&gt;  &lt;li&gt;其次，用户肯定不想为每个表去手动映射 schema，这就需要系统具有元信息自动发现的能力，省去用户在 Flink 中创建 DDL 的过程，甚至帮用户自动在 Hudi 中创建目标表。&lt;/li&gt;  &lt;li&gt;另外，用户还希望源端表结构的变更也能自动同步过去，不管是加列减列和改列，还是加表减表和改表，都能够实时的自动的同步到目标端，从而不丢失任何在源端发生的新增数据，自动化地构建与源端数据库保持数据一致的 ODS 层。&lt;/li&gt;  &lt;li&gt;最后，还需要有具备生产可用的整库同步能力，不能对源端造成太大压力，影响在线业务。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;这四个核心功能基本组成了用户理想中所期待的数据集成系统，而这一切如果只需要一行 SQL，一个Job就能完成的话，那就更完美了。我们把中间的这个系统称为 “全自动化数据集成”，因为它全自动地完成了数据库的入湖，解决了目前遇到的几个核心痛点。而且目前看来，Flink 是实现这一目标非常适合的引擎。&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221935585-7bb95c9a-5a06-4017-9fce-4b9ac6131c74.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;所以我们花了很多精力，基于 Flink 去打造这个 “全自动化数据集成”。主要就是围绕刚刚说的这四点。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;首先 Flink CDC 已经具备了全增量自动切换的能力，这也是 Flink CDC 的亮点之一。&lt;/li&gt;  &lt;li&gt;在元信息的自动发现上，可以通过 Flink 的 Catalog 接口无缝对接上，我们开发了 MySQL Catalog 来自动发现 MySQL 中的表和 schema，还开发了 Hudi Catalog 自动地去 Hudi 中创建目标表的元信息。&lt;/li&gt;  &lt;li&gt;在表结构变更的自动同步方面，我们引入了一个 Schema Evolution 的内核，使得 Flink Job 无需依赖外部服务就能实时同步 schema 变更。&lt;/li&gt;  &lt;li&gt;在整库同步方面，我们引入了 CDAS 语法，一行 SQL 语句就能完成整库同步作业的定义，并且引入了 source 合并的优化，减轻对源端数据库的压力。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221935687-4685de73-c3ba-4263-a061-7425fe017144.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;为了支持整库同步，我们还引入了 CDAS 和 CTAS 的数据同步语法。它的语法非常简单，CDAS 语法就是 create database as database，主要用于整库同步，像这里展示的这行语句就完成了从 MySQL 的 tpc_ds 库，整库同步至 Hudi 的 ods 库中。与之类似的，我们还有一个 CTAS 语法，可以方便的用来支持表级别的同步，还可以通过正则表达式指定库名和表名，来完成分库分表合并同步。像这里就完成了 MySQL 的 user 分库分表合并到了 Hudi 的 users 表中。CDAS CTAS 的语法，会自动地去目标端创建目标表，然后启动一个 Flink Job 自动同步全量 + 增量的数据，并且也会实时同步表结构变更。&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221935727-9959b785-ea60-40e8-9db7-2e5bc78993b3.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;之前提到千表入湖时，建立的数据库连接过多，Binlog 重复读取会造成源库的巨大压力。为了解决这个问题，我们引入了 source 合并的优化，我们会尝试合并同一作业中的 source，如果都是读的同一数据源，则会被合并成一个 source 节点，这时数据库只需要建立一个连接，binlog 也只需读取一次，实现了整库的读取，降低了对数据库的压力。&lt;/p&gt; &lt;p&gt;为了更直观地了解我们是如何简化数据入湖入仓的工作，我们还额外提供了一个 Demo 视频，感兴趣的朋友可以在 Flink Forward Asia 2021 大会上，观看《Flink CDC 如何简化实时数据入湖入仓》的分享。&lt;/p&gt; &lt;h2&gt;  &lt;a href="http://wuchong.me/#&amp;#20116;&amp;#12289;Flink-CDC-&amp;#30340;&amp;#26410;&amp;#26469;&amp;#35268;&amp;#21010;" title="&amp;#20116;&amp;#12289;Flink CDC &amp;#30340;&amp;#26410;&amp;#26469;&amp;#35268;&amp;#21010;"&gt;&lt;/a&gt;五、Flink CDC 的未来规划&lt;/h2&gt; &lt;p&gt;  &lt;img alt="" src="https://user-images.githubusercontent.com/5378924/221935772-38974f81-1425-4489-a183-059098b6119f.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;最后关于 Flink CDC 的未来主要有三个方面的规划。&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;第一，我们会继续完善 CDAS 和 CTAS 的语法和接口，打磨 Schema Evolution 的内核，为开源做准备。&lt;/li&gt;  &lt;li&gt;第二，我们会扩展更多的 CDC 数据源，包括 TiDB、OceanBase、SQLServer 这些都已经规划中了。&lt;/li&gt;  &lt;li&gt;第三，我们会将目前的增量快照读取算法抽象成通用框架，使得有更多的数据库能通过简单几个接口就对接到这个框架上，具备全增量一体化的能力。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;也希望有更多的志同道合之士能加入到 Flink CDC 开源社区的建设和贡献中，一起打造新一代的数据集成框架！&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Flink Flink Flink CDC</category>
      <guid isPermaLink="true">https://itindex.net/detail/62643-flink-cdc-%E5%AE%9E%E6%97%B6</guid>
      <pubDate>Mon, 10 Jan 2022 01:35:43 CST</pubDate>
    </item>
    <item>
      <title>一个几十万数据的小网站便宜的方案 🧵 by @dotey(宝玉)</title>
      <link>https://itindex.net/detail/62640-%E5%8D%81%E4%B8%87-%E6%95%B0%E6%8D%AE-%E7%BD%91%E7%AB%99</link>
      <description>&lt;div&gt;  &lt;h1&gt;   &lt;div&gt;我以前帮人整过一个几十万数据的小网站，这么多数据存关系型数据库放到云上每月要几十刀不合算，所以后来采用了个便宜的方案     &lt;img alt="&amp;#55358;&amp;#56821;" src="https://abs.twimg.com/emoji/v2/svg/1f9f5.svg"&gt;&lt;/img&gt;&lt;/div&gt;&lt;/h1&gt;  &lt;div&gt;   &lt;div&gt;&lt;/div&gt;&lt;/div&gt;  &lt;div&gt;第一个版本方案

完整的数据存在本地的Sqlite，备份到网盘

用脚本将单条数据和列表数据导出到Json文件，存到AWS的S3，当做后端数据库

网站用Nextjs，基于它的ISR静态化的方案，第一次请求页面的时候静态化，后面就不需要访问数据库了

   &lt;a href="https://t.co/S9uhDQaKxW" target="_blank"&gt;nextjs.org/docs/basic-fea…&lt;/a&gt;&lt;/div&gt;  &lt;div&gt;   &lt;a href="https://t.co/S9uhDQaKxW" target="_blank"&gt;    &lt;div&gt;     &lt;div&gt;      &lt;img alt="Learn how to create or update static pages at runtime with Incremental Static Regeneration." height="882" src="https://pbs.twimg.com/card_img/1628435063934181378/tUSTAdut?format=png&amp;name=orig" width="1686"&gt;&lt;/img&gt;&lt;/div&gt;     &lt;div&gt;      &lt;div&gt;nextjs.org/docs/basic-fea…&lt;/div&gt;      &lt;div&gt;Data Fetching: Incremental Static Regeneration | Next.js&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;  &lt;div&gt;   &lt;div&gt;&lt;/div&gt;&lt;/div&gt;  &lt;div&gt;搜索用的是Meilisearch，它支持中文全文检索，性能很好，对前端也友好，可以方便的集成到Nextjs中。

部署到从oracle cloud白嫖的免费主机上，然后从网站上包了个API访问Meilisearch。

   &lt;a href="https://t.co/bcnTPv8lJ6" target="_blank"&gt;meilisearch.com&lt;/a&gt;&lt;/div&gt;  &lt;div&gt;   &lt;a href="https://t.co/bcnTPv8lJ6" target="_blank"&gt;    &lt;div&gt;     &lt;div&gt;      &lt;img alt="An open-source, blazingly fast, and hyper-relevant search engine that will improve your search experience" height="630" src="https://pbs.twimg.com/card_img/1628346977602740227/jw0gSOix?format=jpg&amp;name=orig" width="1200"&gt;&lt;/img&gt;&lt;/div&gt;     &lt;div&gt;      &lt;div&gt;meilisearch.com&lt;/div&gt;      &lt;div&gt;Meilisearch&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;  &lt;div&gt;   &lt;div&gt;&lt;/div&gt;&lt;/div&gt;  &lt;div&gt;网站直接部署到Vercel上，免费档足够用了，每月100G数据流量，还可以直接买域名或者绑定自己域名，并且有SSL证书，直接就让你的域名支持https了，不用任何额外配置。

将代码放在GitHub，并且和Vercel集成，代码一提交就自动部署了。

   &lt;a href="https://t.co/Lm23i1q5XT" target="_blank"&gt;vercel.com&lt;/a&gt;&lt;/div&gt;  &lt;div&gt;   &lt;a href="https://t.co/Lm23i1q5XT" target="_blank"&gt;    &lt;div&gt;     &lt;div&gt;      &lt;img alt="Vercel is the platform for frontend developers, providing the speed and reliability innovators need to create at the moment of inspiration." height="882" src="https://pbs.twimg.com/card_img/1628953311796764672/p_wvjCX8?format=png&amp;name=orig" width="1686"&gt;&lt;/img&gt;&lt;/div&gt;     &lt;div&gt;      &lt;div&gt;vercel.com&lt;/div&gt;      &lt;div&gt;Vercel: Develop. Preview. Ship. For the best frontend teams&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;  &lt;div&gt;   &lt;div&gt;&lt;/div&gt;&lt;/div&gt;  &lt;div&gt;后来发现Json静态文件更新维护起来还是有点麻烦，然后了解到还有Amazon DynamoDB这样经济实惠的数据库，它有25G的免费存储，每月有2亿的免费读写请求，足够用了。

唯一麻烦的是后端访问的代码要重写，不过一次升级完后面几乎不用怎么维护。

   &lt;a href="https://t.co/ZwztyNcfuL" target="_blank"&gt;aws.amazon.com/dynamodb/&lt;/a&gt;&lt;/div&gt;  &lt;div&gt;   &lt;a href="https://t.co/ZwztyNcfuL" target="_blank"&gt;    &lt;div&gt;     &lt;div&gt;      &lt;img alt="Amazon DynamoDB is a fully managed, serverless, key-value NoSQL database that runs high-performance applications at any scale, with built-in security, continuous backups, and automated multi-region..." height="109" src="https://pbs.twimg.com/card_img/1627661780985028611/5rRlrby2?format=png&amp;name=120x120" width="109"&gt;&lt;/img&gt;&lt;/div&gt;     &lt;div&gt;      &lt;div&gt;aws.amazon.com/dynamodb/&lt;/div&gt;      &lt;div&gt;Fast NoSQL Key-Value Database – Amazon DynamoDB – Amazon Web Services&lt;/div&gt;      &lt;div&gt;Amazon DynamoDB is a fully managed, serverless, key-value NoSQL database that runs high-performance applications at any scale, with built-in security, continuous backups, and automated multi-region...&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;  &lt;div&gt;   &lt;div&gt;&lt;/div&gt;&lt;/div&gt;  &lt;div&gt;完整版   &lt;img alt="&amp;#55358;&amp;#56821;" src="https://abs.twimg.com/emoji/v2/svg/1f9f5.svg"&gt;&lt;/img&gt;    &lt;a href="https://t.co/egx902OAsG" target="_blank"&gt;twitter-thread.com/t/163042603566…&lt;/a&gt;&lt;/div&gt;  &lt;div&gt;   &lt;div&gt;&lt;/div&gt;&lt;/div&gt;  &lt;div&gt;补充下，上面的整套方案下来，运维成本除了域名费用外为$0。&lt;/div&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/62640-%E5%8D%81%E4%B8%87-%E6%95%B0%E6%8D%AE-%E7%BD%91%E7%AB%99</guid>
      <pubDate>Tue, 28 Feb 2023 18:15:35 CST</pubDate>
    </item>
    <item>
      <title>分布式数据库存储透析：B-TREE 和 LSM-TREE 的性能差别</title>
      <link>https://itindex.net/detail/62628-%E5%88%86%E5%B8%83-%E6%95%B0%E6%8D%AE%E5%BA%93-%E9%80%8F%E6%9E%90</link>
      <description>&lt;div&gt;  &lt;div&gt;&lt;/div&gt;  &lt;div&gt;   &lt;p&gt;    &lt;strong&gt;作者介绍&lt;/strong&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;    &lt;strong&gt;宇文湛泉，&lt;/strong&gt;现任金融行业核心业务系统DBA，主要涉及Oracle、DB2、Cassandra、MySQL、GoldenDB、TiDB等数据库开发工作。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;h2&gt;    &lt;strong&gt;一、引子&lt;/strong&gt;&lt;/h2&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;最近一两年里，每次做分布式数据库的内容分享活动时，总是会提及现在数据库的两个重要的存储结构，B-TREE和LSM-TREE。因为，我觉得作为数据库的存储根基，无论是要选型，或者是用好一个数据库，清楚这两的差别和各自特点，都特别重要。但是几乎每一次都只能提一下，哪种数据库用了哪个存储。再多就是稍微介绍LSM-TREE的写入友好。对于有些朋友，正面临二选一项目抉择时，这点信息显然是不够的。于是他们会想要知道，更多二者差异细节，以及到底哪一种适合自己的系统。可惜我总是只能遗憾讲个大概，并解释要彻底讲清楚的话，整个分享就只能光讲这个可能时间还不太够。然而，我还是觉得每次都含含糊糊的过去，未免也有点耍流氓的感觉。总得找个机会，把这里面一些有意思的内容拿出来罗列一下。适逢国庆宅家，想想也是时候把这个坑给填一填了。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;当然，本文并不打算从0开始介绍LSM-TREE，那样篇幅也太冗长了。本文默认各位读者具有一点B-TREE和LSM-TREE的基础背景知识。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;h2&gt;    &lt;strong&gt;二、背景板-分布式关系型数据库&lt;/strong&gt;&lt;/h2&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;其实，抛开分布式数据库来纯写这两个存储引擎，似乎要更加简明一点。但是，这样的话实用性不太行。单机版LSM-TREE数据库有排名在100名左右的ROCKSDB，LEVELDB。它们被划分为KEY-VALUE类型，而且它们通常不会直接出现在我们的视野，也极少直接被使用在项目中。然而，基于LSM-TREE的分布式数据库则是非常常见的，比如这些：&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;img src="data:image/svg+xml;utf8,&lt;svg xmlns='http://www.w3.org/2000/svg' width='432' height='126'&gt;&lt;/svg&gt;" width="432"&gt;&lt;/img&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;甚至可能有些人，是有用分布式数据库的需求，才去学习和理解LSM-TREE的（比如说我就是先要使用CASSANDRA）。不过带上分布式的这个背景，未免多少会使得存储结构差异比对，变得不那么纯粹。因为分布式数据库嘛，总是带来了一些额外的开销。比如说数据库层面的SQL解析到分布式执行计划产生。再比如说分布式的场景下，分布式事务、全局时间戳获取等等。不过这个还是可以大致对比一下基于B树的分布式数据库情况来说明一下。但就具体到每一个数据库的话，因为各个数据库的具体实现方式各有不同，实际情况就得看某一个具体的数据库还做了些什么额外的动作，再把它附加上去。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;还有关系型也算是一个重要背景。因为有些特殊项目场景、特殊的数据格式，使用某种数据库或者存储结构时快得飞起，然而却缺乏了一般通用性。其实，像REDIS和CASSANDRA这样的数据库已经非常的热门，使用范围也非常的广。但是我们在项目中使用这些数据库，也还是充当某种功能性的角色比较多，我们很难把它做成系统的主数据库。尤其是那些有历史包袱迁移而来的系统。无论如何，关系型模型，基本上还是我们见到的主要情况。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;所以我准备在分布式和关系型的数据库大背景下，以最为常见的几种数据访问形态来描述一下，这样就更加具有真实的参考性价值。先摊开来数据库的主要操作都做了些什么。然后再套几个经典的案例场景进去看看。这样子的话，围绕着分布式关系型数据库来展开这两颗树的内容，也就更贴近大家现实使用这两存储结构的实际需求，起码我感觉上是如此。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;在开始眼花缭乱的各种操作叙述之前，我们可以先草率的做一点假定。比如说，我们SQL的响应时长，认为是最关键的性能指标。比如说，我们认为内存中的操作比较快，对性能的影响稍微小一些。而磁盘操作比较慢，比较可能影响交易时长。再比如，异步动作，基本不怎么影响交易性能。这些假定虽然草率，但是我认为这可以使我们对一些数据库操作的性能开销，有一些更粗暴而直观的感性认知。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;h2&gt;    &lt;strong&gt;三、LSM-TREE之优势的写&lt;/strong&gt;&lt;/h2&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;写友好，几乎是LSM-TREE的标志性特点，那么我们就从写流程开始。先来个经典的LSM-TREE的图。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;img src="data:image/svg+xml;utf8,&lt;svg xmlns='http://www.w3.org/2000/svg' width='1080' height='627'&gt;&lt;/svg&gt;" width="1080"&gt;&lt;/img&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;h3&gt;    &lt;strong&gt;STEP 1 WAL日志写入(Write Ahead Log) 磁盘操作&lt;/strong&gt;&lt;/h3&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;这个步骤基本上各个数据库都有，有各种各样的叫法。比如说Innodb的Redo log，Cassandra 的Commit logs。但是，作用都是一样的，在数据库宕机之后，这份日志可以保证数据的恢复。而这个日志，都是以顺序写入的方式不断追加。所以，感觉上，这部分开销应该是非常的接近的。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;我觉得MYSQL的BINLOG也可以放在这里提一下，从严格意义上来说，BINLOG不属于存储引擎而是属于MYSQL，它与B-TREE这个存储结构没有必然关系。功能上来看，我觉得它有点接近某些数据库的归档日志。它开销是显然有的，但是我觉得应该把这笔账算在高可用的头上去。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;h3&gt;    &lt;strong&gt;STEP 2 树数据结构维护&lt;/strong&gt;&lt;/h3&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;有观点说B-TREE至少要写两次，一次是写WAL日志，一次是写B-TREE本身，以此推出B-TREE写入比LSM-TREE更加慢。这个说法我觉得有些歧义的。因为LSM-TREE其实也是写两次，也是一次写WAL，一次写树。如果非要说，LSM-TREE能少一次，除非是某种LSM-TREE数据库在WAL写完即认为写入成功返回，不需要等MemTable维护好，而这就意味着这种数据库存在以提交的数据读不到的情况。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;我个人觉得比较精准的说法应该是，LSM-TREE中MemTable的追加写入速度，要比B树的维护快得多。首先无论是哪种树，写树本身是个内存操作，两种结构都不需要等树结构落盘数据库才算Commit成功。数据库脏页通常都是异步进程慢慢刷出的。所以单纯的写树动作并不是关键。但是，B-TREE的写树动作，并非一个纯粹内存操作。因为只要从根节点开始，一直到数据页。B-TREE这一条路上，无论是索引页还是数据页，有任何页不在缓存里，数据库都会触发磁盘IO来读取。所以在一般的写入场景下，B树的维护就慢了，它是一个先读后写的过程。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;我们可以比对一下，在Cassandra的写入步骤里面，资料上的描述，仅有ADD TO MEMTABLE这么简单来描述。首先，它体现了这条数据是顺序的追加上去的简单性。如果说还要干点啥，就只剩下一句，如果在ROW CACHES里存在，废弃存在的数据。对于LSM-TREE而言，MemTable写完，交易就应该是成功返回了。并且这些全都是内存操作。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;然后我们随便来看看B树在这个阶段的维护都做了什么：&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;1）写Undo日志，内存操作，一般只有Undo空间不够才写盘。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;2）从索引根节点开始，找到记录行应该存储的数据页，内存加磁盘操作。若为命中缓存，则可能促发多次磁盘IO。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;3）可能B-TREE索引分裂，一大波内存加磁盘操作。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;突然感觉有点什么不对劲对不对，首先追加写入MemTable显然是做不了约束性检查的，如果你的应用想写入重KEY回滚，那么在LSM-TREE的写入这里挡不住。那么你需要，那么它需要以另一种方式实现，比如说：读后写。那这时候的时间，其实有点近似与UPDATE的操作。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;这个地方显然需要两分的来看待LSM-TREE的优势。不需要约束性检查的超大规模写入场景有没有？当然有，而且还很多。比如一个专门写入流水的数据表。在互联网特别常见的记录PV数据的表，只要有人点了某个页面，就等于一条记录。不需要约束，不需要事务。这样的场景，这样的系统，用LSM-TREE自然快得飞起。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;然而，如果你的系统，几乎每个写入都要判定是不是重主键、重唯一索引的话。那么这个写入优势显然是有限的。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;h3&gt;    &lt;strong&gt;STEP 3 脏数据落盘 磁盘操作&lt;/strong&gt;&lt;/h3&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;由于这部分操作都是异步执行，只要机器资源没有问题的话，通常已经不太影响交易响应时间了。所以，这里的性能差别不是我想说的重点。我想说一些虚无缥缈的，想法。刚才说的这个脏页落盘异步，其实是很多数据库性能优化的一个空间。很多数据库的优化思路都在基于这一点去展开。比如说INNODB的DOUBLE-WRITE，Merge Insert Buffer等等。这些优化的核心思想都围绕着落盘可以异步，如何减少磁盘交互而展开。在看到这个地方的时候，不知道有没有隐隐约约的感受到，数据库的千差万别之中，总是存在着某些相似的地方。所以，接下来，我准备一边聊数据库的更新（UPDATE）操作，一边说一说这一条隐约的线索。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;h2&gt;    &lt;strong&gt;四、关于存储结构的思考&lt;/strong&gt;&lt;/h2&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;在其他枯燥的知识点对比介绍之间呢，让我们先乱入一波。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;在我没有学过LSM-TREE之前，在B树还是我脑子里，唯一占统治地位的存储结构的少年时代。我一直有一个潜在的观念，即“数据库的存储结构是为数据查询服务的”。如果非要说的不那么武断，也至少是主要为查询服务的。比如说，最常见的索引吧。我们建立一个索引，损耗插入时索引维护的成本，使用额外磁盘空间。为啥？显然是为了加快查询。再比如说“聚簇”。维持数据库中数据某种维度的顺序，为啥？显然还是为了某种查询。再往比如说列存储，为了分析型SQL在计算过程中，减少无关列的读取，还是为了查询吧。这些概念没有一个是为了数据写入服务的吧。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;正如上面所描述的，当我接触了LSM-TREE的存储结构之后，我有一个特别深刻而直观的印象，这个“数据库的存储结构是为数据写入服务的”。它和B树有根源性的不同，B树的存储结构，处处损耗写入的性能来提高查询性能。而LSM-TREE在提高写入性能，并且可能在某些时候损耗了读取的性能。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;容我大胆的在这里丢一个问题和一个猜想。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;问题：为什么数据库的发展历史中，是先有B树而后有LSM树？只是偶然的巧合吗？&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;猜想：在古老的数据库使用场景时，绝大部分数据产生的是比较慢的，这些数据变化也比较慢，但是他们反反复复的被使用和读取。于是，数据库使用了B树的存储结构。后来，随着时间的变迁。有些新兴的应用场景数据产生的速度，大幅度的加快了，数据的更新速度也加快了。甚至于出现了超大量的数据产生，但是这些数据快速的产生出来，但是被反复读取的使用的次数大幅度减少了，于是LSM树出现了。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;为什么要写这个猜测？因为，如果我的猜想是对的，那么就是时候反问一句，你的数据库系统哪一种？你系统的数据是相对稳定的还是快速膨胀的？你系统的数据是反复读取吗？那么你感觉它更适合哪种存储引擎呢？&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;先别感觉豁然开朗，故事当然没有这么简单，选择也当然没有这么容易。注意，我描述LSM-TREE用的词汇是“可能”在某些时候损耗了读取性能。这个地方有破绽的点起码有两条。第一，既然是可能，那有没有什么情况没有损耗。那就变成，用LSM-TREE我的系统可能写入变快了，读取没变慢。第二个大破绽是，这个损耗没有量化。不同的系统对于损耗的容忍程度天差地别。有的项目一个交易慢几毫秒都会被人盯着追杀，而有的场景SQL语句跑个几秒几十秒都不叫事。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;所以，要做出更准确的选择，我们还需要把自己系统的实际情况往里带入并量化差异。最佳的选择当然是实测。因为它优势的地方你的系统不一定优势，它劣势的地方你的系统也不一定就劣势，就是这么神奇。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;h2&gt;    &lt;strong&gt;五、写流程的衍生-更新动作&lt;/strong&gt;&lt;/h2&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;回到前面介绍写流程的主线上来。数据库的增删改查，并称数据库的四大操作。但是我觉得把UPDATE当作是写流程的某种衍生是合适的。我们前面讲了，在B树数据写入维护B树的过程，其实是一个先读后写的过程。如果我们把INSERT一条记录，看成是要更新这条记录所在的数据页的内容。假设空间够用，也没有分裂等等，那INSERT和UPDATE动作可不就是一个流程吗？&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;另一方面，你会发现我在描述LSM-TREE写优的反例竟然用的是约束性检查，而并没有用UPDATE操作来反例读后写。因为纯粹的LSM-TREE的UPDATE更加是一个纯纯的INSERT动作，不存在半点读后写。来看一下引用于2020年VLDB论文《LSM-based Storage Techniques:A survey》中的描述和图。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;img src="data:image/svg+xml;utf8,&lt;svg xmlns='http://www.w3.org/2000/svg' width='738' height='316'&gt;&lt;/svg&gt;" width="738"&gt;&lt;/img&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;“通常，索引结构可以选择两种策略之一种来处理更新，即就地（in-place）更新和非就地（即异位，out-of-place）更新。就地更新结构，如B+树，直接覆盖旧记录来存储新更新。例如，在图1a中，为了将key k1的值从v1更新到v4，索引条目(k1, v1)被直接修改以应用该更新。这些结构通常是读优化的，因为只存储每个记录的最新版本。然而，这种设计牺牲了写性能，因为更新会导致随机I/O。此外，索引页可以被更新和删除所分割，从而减少空间利用率。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;相反，异位（out-of-place）的更新结构，例如LSM-tree总是将更新存储到新的位置，而不是覆盖旧的条目。例如在图1b中，更新(k1, v4)被存储到一个新的位置，而不是直接更新旧的条目(k1, v1)。这种设计提高了写性能，因为它可以利用顺序I/O来处理写。它还可以通过不覆盖旧数据来简化恢复过程。然而，这种设计的主要问题是牺牲了读取性能，因为记录可能存储在多个位置中的任何一个。此外，这些结构通常需要一个独立的数据重组过程，以不断提高存储和查询效率。顺序的、异位的更新并不是新的想法；自20世纪70年代以来，它已成功地应用于数据库系统。”&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;可以看出LSM-TREE的异位（OUT-OF-PLACE）更新结构，压根就不是读后写，它就是一个INSERT动作。那这样子来看，是不是感觉把更新动作当作是一个写流程的衍生物，无论是对于B-TREE而言，还是LSM-TREE而言，基本上是没有什么违和感的。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;然而，在这一堆反反复复的文字中，你可能已经建立起一个LSM-TREE读取性能被牺牲的概念，并且可能认为读取性能不佳，可能会是阻碍你的系统选取LSM-TREE的重要障碍。因为，哪怕你就是简简单单的看最前面那个彩图，也能知道，你的一条记录可能要读好几个文件才能得到，从而质疑它的读取性能。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;如果你内心敏感，你也许能从我举得例子中察觉到另一朵重要的乌云。这个乌云是资源的冲突。LSM-TREE的写优势根源是，用追加写取代读后写。如果，你的系统有任何主要的场景，避免不掉读后写。那这个优势的根基便被动摇了。约束性检查，是最容易想到的场景之一，因为不读，就不能确定能不能写。继而，我们很容易的想到另一个重要更新场景，悲观锁和事务。为啥？长期的B-TREE经验告诉我们，SELECT FOR UPDATE，得先SELECT才能上锁FOR UPDATE。那不然我异位INSERT的时候，我去哪检查这条记录有没有锁呢？我怎么确定我INSERT的时候，别人不能INSERT呢？那这一部分内容，我们放在后面的章节里再去展开。先把基本的动作来看完。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;h2&gt;    &lt;strong&gt;六、B-TREE之优势的读&lt;/strong&gt;&lt;/h2&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;再看一下这个图&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;img src="data:image/svg+xml;utf8,&lt;svg xmlns='http://www.w3.org/2000/svg' width='1080' height='627'&gt;&lt;/svg&gt;" width="1080"&gt;&lt;/img&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;数据读取，数据库通常视为最最主要的能力。就像我前面说的，有一段时间我都一直觉得，数据如何写，如何摆放最终都是为了读起来方便。从图上看的感觉总是直观的，前面提到了，很多人眼看着LSM-TREE那张图读取动作出现了5条读取线，得出了LSM-TREE读取性能不行的结论（很显然，我初看这张图，也是这么认为的）。当然，读多次，性能是不是受损，那肯定是受损的。损得大不大？那就不好说了。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;在来来回回看这张图之后，我不再紧盯那五根线，而是开始细细的观察Level 1开始往下的这些SSTABLE文件。这些文件由异步的Compaction操作产生。这个动作有很多文档都把它翻译成数据压缩，我觉得这很容易和数据库的DATA COMPRESS概念混淆。我更喜欢把它译为数据整理。我们看看它做了什么，去重多版本数据、删除多余的老数据、数据按KEY排序。没错，它竟然是排序的。如果说SSTABLE的文件头里面，标上了起止的KEY，它像不像一个小小的B树呢？还记得我在前面说那个隐隐约约的线索吗？数据库总是把一些异步操作，作为一些优化的空间。LSM-TREE的Compaction就绝不是仅仅为了防止数据量不断增长而设计的清理机制。它的存在还有更重要的意义。LSM-TREE其实并没有自暴自弃的在优化写入的时候就放弃查询。其实它遵循了我们之前那个现索，数据库在异步的流程中，暗暗的优化数据查询时的速度。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;我们来接着填一下前面的坑。如果说，相比B树而言，LSM-TREE的读取总是很慢的。是不是数据相对稳定的系统就不能选LSM-TREE吗？如果，我们的数据一次INSERT之后，就没不动了，那会是什么情况？我们来细细的推敲一下，首先必然的，LSM-TREE写优势用不上不对，因为你就不怎么写嘛？但是读的真的就慢吗？我们来看看，首先，我们在内存里找到了这条记录，CACHE命中了，或者MEMTABLE里有最新的数据，都没有磁盘IO，那妥妥的快。假设没命中，那么只做个一次INSERT的记录，可能出现几层的几个SSTABLE里面？好像只有一个吧。当然，这里会有一个疑惑，就是我没读这个SSTABLE，我怎么知道里面有没有这条记录？在我印象中，通常SSTABLE的数据文件，通常都要配一个BLOOM过滤器，来告诉你这条KEY它有没有来解决这件事情。诶，这时候，再来整理整理感觉，是不是上面那两根内存里的线，还挺快的。下面指到磁盘上的三根线，好像也没有三根线也就只有一根，剩下这一根，感觉还和B-TREE有那么一点点的像，搞不好在这一个SSTABLE里面，拿得还比B-TREE快。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;好啦，这个例子其实有点过，我并不是要证明LSM-TREE的读取性能要比B-TREE好，这是不可能的。我只是想再提醒前面那个观点，它优势的地方你的系统不一定优势，它劣势的地方你的系统也不一定就劣势，就是这么神奇。比如我还常常被问到类似的问题，我的系统以更新为主，SSTABLE的线特别多是不是不能选LSM-TREE？那也不一定啊，如果你平时查都不查，那读取有一百根线对你的系统性能又有什么影响呢？那我的系统又改得多又查得多，又不是以写入为主呢？对的，它不适合，因为SSTABLE的读取线很多，而且它的写优势又发挥不出来。所以无论如何，你还是得把自己系统的场景往里面带一带，不要凭看图的直觉。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;LSM-TREE的读取性能或许确实的受损的。但是显而易见的是，对于很多时候，这种受损是可以通过各种各样的手段优化、缓解。使得这种受损处于可接受的范围，不然LSM-TREE是怎么越来越火的呢？对吧。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;而B树的读取方面，我觉得这里就不太需要再展开来讨论了，因为前面在说明它写的时候，其实也是要先完成读取流程的，再者B树大家也相对而言比较熟悉。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;h2&gt;    &lt;strong&gt;七、资源的冲突-数据锁&lt;/strong&gt;&lt;/h2&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;接下来，是时候来讲一讲这一朵乌云了。资源冲突问题，一直以来都在数据库的重要困难点附近出没。而且，冲突问题又和分布式的问题互相之间有一些纠缠。举个例子，在数据库单机架构往SHARE DISK的架构演变过程中，它就一度成为了很多数据库厂商搞不定的难点。比如，我在集群中的某一个数据库实例上，上锁并修改了数据。这个锁和修改信息，就需要立刻在内存中，直接通讯给其他的数据库实例。最后比较成熟的方案只有几个少数像ORACLE 的RAC，DB2的DATA SHARING这样的能够解决。这个例子特别清楚的能体现，资源冲突处理，要么要集中处理，要么需要特别靠谱的互相通信，这个通讯在分布式水平扩展的情况下会有所放大。所以，有一些SHARE NOTHING的数据库产品，会选择在数据存储节点，来集中处理数据的上锁问题。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;对于基于LSM-TREE的数据库产品而言，有的产品选择不支持锁和事务，有的选择通过其它巧妙的手段来解决。而我们还是可以显著的看到，B-TREE结构中，上锁与不上锁，也许只是内存里面一个记录标志位的修改差别，上锁与不上锁的性能差别似乎并不是很大。但是LSM-TREE结构的数据库里，似乎很有必要把上锁流程的开销拿出来额外关注一下。因为如果数据库做的是一般性先读后写，那么写优势没了。如果是别的冲突处理机制，那这部分显然属于额外开销。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;为什么不支持，竟然也可以算一个出路，我们可以往回退一步。资源冲突问题的源头是并行的处理。而在冲突的资源点上，我们需要转并行为串行，其实大致上我觉得可以分开成两个问题来看，第一个解决时序问题，就是我们认为后面的更新才是对的，第二个是解决并发过程中更新丢失和脏读问题。像CASSANDRA这样的数据，用时间戳来解决时序问题，即改更新为追加，并在数据读取合并时，以最新时间戳的数据为准。再利用时间戳来实现多版本的读取。算是解决半个资源冲突的本源问题。所以对没有第二部分问题的系统，这的确也是一个解决方案。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;另外半个问题，就比较棘手，比如说钱的转入转出模型，有的转入有的转出，若钱不够就不能够转出。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;我们来看一个我觉得比较优秀的基于LSM-TREE存储结构的 Percolator模型的实现方案。比A有10块钱，B有2块钱，A向B转7块钱。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;首先，使用三个列簇（COLUMN FAILY）来存三样东西，一个是数据本身，一个是锁信息，一个是写入的版本。要有一个时间戳和一个版本号来解决时序问题，那么在PREWRITE阶段，数据库除了写入数据之外，还要写入LOCK信息。最后再提交阶段，把LOCK信息干掉，再写一个版本信息。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;img src="data:image/svg+xml;utf8,&lt;svg xmlns='http://www.w3.org/2000/svg' width='511' height='173'&gt;&lt;/svg&gt;" width="511"&gt;&lt;/img&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;作为读后写替代，那么这种方案下的冲突解决能不能比B树的维护代价更小一点。我们先看看，在理想LSM-TREE的UPDATE只有一个追加写 MEMTABLE的操作上，又附加了什么。首先，我们看A记录，一共写了 三次，最后COMMIT结束之后，还需要把锁信息干掉。草算一算，好像时间翻了四倍。再细细的看一下，写数据和写版本看起来应该是可以追加写的。但是，这个锁信息可不就是一个妥妥的读后写吗？因为对一条记录上锁之前，起码得看看前面有没有锁吧。但是感觉上，这个锁的CF应该不大，应该基本上都是内存操作。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;我们来细细推敲一下。普通更新的话，把A从版本5的10改为版本7的3。追加写数据，追加写版本，两次内存操作。检查读一次锁，如果没锁，写一次锁，先算他是内存操作。如果在B树上，一般随机转账命中概率不大，把A读起来，那么有一波磁盘IO，再加同样的内存上锁放锁，感觉还是B树不一定快。为啥，因为同样是读后写，这个锁CF信息的读后写很可能是内存里没有磁盘操作的。而B树的读后写，那基本上磁盘IO跑不了的。在这样的情况下，其实LSM基本上不落下风的。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;但是，程序可不一定是这么写的。比如说，悲观锁。我相信很多时候，你很难把上面这个场景的SQL写成，UPDATE TABLE SET YUAN=YUAN-7 WHERE KEY=A吧。比较常见的写法不应该是，SELECT YUAN FROM TABLE WHERE KEY=A FOR UPDATE。然后IF YUAN&amp;gt;=7 YUAN_NEW=YUAN-7。再然后UPDATE TABLE SET YUAN=YUAN_NEW WHERE KEY=A。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;这中间出现了什么变化，响应时间对比其实从单一的UPDATE对比变成了两个SQL符合在一起的形态对比。首先，由于SELECT FOR UPDATE这个动作出现，磁盘读变成了一个跑不掉的步骤。B树上，记录会在SELECT FOR UPDATE的时候就被IO到内存里面来。这时候，你再看B树的UPDATE，那就纯粹是个内存操作，那应该不会比写三个CF慢的。上锁放锁的内存动作，我们姑且认为二者差不多，那这个场景就变成纯粹的比读取。而且，考虑的有冲突和并发，表示这是一个频繁变更数据的情况，那么我会猜测LSM-TREE读取的SSTABLE的线比较多，最终直接成为影响系统性能的重要因素。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;再稍微说一下分布式的叠加，如果A和B存在不同的节点里。B中的副锁还要再跨网络去访问A节点的主锁有没有释放。感觉也是有一些跟硬件相关的开销在里面。但应该不是重点，因为类比我们前面说的，RAC各实例间也有基于网络的锁信息交互开销。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;h2&gt;    &lt;strong&gt;八、高可用附加&lt;/strong&gt;&lt;/h2&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;其实这个内容，跟存储引擎的联系有限，但是前面写入的时候提到了BINLOG。MYSQL的BINLOG承担了主备机同步的桥梁作用，但它对于很多重要系统来说都是必开的。最关键的是，再RPO=0的前提下，BINLOG的远程落盘，是COMMIT成功的必要条件。它的开销对性能影响是必然的，写BINLOG也几乎写流程中的一部分。不过我觉得它还是可以剥离出来看，因为它本质并不是WAL日志。如果一定要对标的话，我觉得它类似于RAFT LOG的写入，这两个东西都是围绕着高可用和多节点数据复制展开的。对于写入的性能开销增加，似乎也是差不多的。&lt;/p&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;h2&gt;    &lt;strong&gt;九、结尾&lt;/strong&gt;&lt;/h2&gt;   &lt;p&gt;    &lt;br /&gt;&lt;/p&gt;   &lt;p&gt;终于把这个坑稍微填了一填，感觉说了好多，又感觉好多内容没有说。想必以我的认知力，也并没有能力把所有的内容说的很全。基本上把实践中，遇到过、顾虑过的一些我觉得的关键点整理了一下吧，也算可以给需要的朋友提供个参考。另外，从文中想必也能看得出来，有些内容基本我全凭猜测，未必准确，也期待有大佬看到并帮我指出其中的错漏。&lt;/p&gt;   &lt;h2&gt;    &lt;strong&gt;关于我们&lt;/strong&gt;&lt;/h2&gt;   &lt;p&gt;    &lt;strong&gt;dbaplus社群&lt;/strong&gt;是围绕Database、BigData、AIOps的企业级专业社群。资深大咖、技术干货，每天精品原创文章推送，每周线上技术分享，每月线下技术沙龙，每季度Gdevops&amp;amp;DAMS行业大会。&lt;/p&gt;   &lt;p&gt;关注公众号【dbaplus社群】，获取更多原创技术文章和精选工具下载&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>dev</category>
      <guid isPermaLink="true">https://itindex.net/detail/62628-%E5%88%86%E5%B8%83-%E6%95%B0%E6%8D%AE%E5%BA%93-%E9%80%8F%E6%9E%90</guid>
      <pubDate>Fri, 24 Feb 2023 00:00:00 CST</pubDate>
    </item>
  </channel>
</rss>

