<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>PostgreSQL on 小盒子的技术分享</title><link>https://xiaobox.github.io/tags/postgresql/</link><description>Recent content in PostgreSQL on 小盒子的技术分享</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Fri, 14 Mar 2025 09:19:52 +0000</lastBuildDate><atom:link href="https://xiaobox.github.io/tags/postgresql/index.xml" rel="self" type="application/rss+xml"/><item><title>数据库选型终极指南：从数据类型到应用场景，一篇就够了</title><link>https://xiaobox.github.io/p/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/</link><pubDate>Fri, 14 Mar 2025 09:19:52 +0000</pubDate><guid>https://xiaobox.github.io/p/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/cover.jpg" alt="Featured image of post 数据库选型终极指南：从数据类型到应用场景，一篇就够了" /&gt;&lt;h2 id="引言"&gt;&lt;a href="#%e5%bc%95%e8%a8%80" class="header-anchor"&gt;&lt;/a&gt;引言
&lt;/h2&gt;&lt;p&gt;在当今的数字化时代，数据已成为企业和组织的核心资产。无论是金融交易记录、社交媒体互动、物联网传感器数据，还是企业内部的业务流程信息，都需要通过数据库进行存储、管理和分析。然而，面对市场上数十种主流的数据库技术（如 MySQL、MongoDB、Elasticsearch、HBase、Hive等），如何选择适合自身业务需求的数据库系统，成为许多技术决策者面临的难题。本文将深入探讨数据库的核心分类、技术特性、应用场景以及选择策略，帮助读者构建系统化的选型框架。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="数据库的分类"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e5%ba%93%e7%9a%84%e5%88%86%e7%b1%bb" class="header-anchor"&gt;&lt;/a&gt;数据库的分类
&lt;/h2&gt;&lt;p&gt;在进行数据库的选择前，你需要至少知道它的&lt;strong&gt;分类&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;在数据库技术的演进过程中，数据存储模型和应用需求的多样性催生了不同类型的数据库系统。这些系统根据其核心设计理念、数据组织方式以及适用场景的差异，形成了多个分类。&lt;/p&gt;
&lt;h3 id="关系型数据库rdbms结构化数据的基石"&gt;&lt;a href="#%e5%85%b3%e7%b3%bb%e5%9e%8b%e6%95%b0%e6%8d%ae%e5%ba%93rdbms%e7%bb%93%e6%9e%84%e5%8c%96%e6%95%b0%e6%8d%ae%e7%9a%84%e5%9f%ba%e7%9f%b3" class="header-anchor"&gt;&lt;/a&gt;关系型数据库（RDBMS）：结构化数据的基石
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;关系型数据库的根基是关系代数和集合论&lt;/strong&gt;，通过二维表（Table）组织数据。每个表由行（记录）和列（字段）构成，通过主键（Primary Key）唯一标识记录，外键（Foreign Key）实现表间的关联。其核心优势在于ACID事务支持，即原子性（Atomicity）、一致性（Consistency）、隔离性（Isolation）、持久性（Durability），适用于对数据一致性要求极高的场景（如金融交易）&lt;/p&gt;
&lt;p&gt;适用场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;需要强一致性的业务系统（银行核心系统、ERP）。&lt;/li&gt;
&lt;li&gt;多表关联查询频繁的OLTP（联机事务处理）场景（电商订单管理）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;局限性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;表结构预定义，修改成本高（如新增字段需 ALTER TABLE）。&lt;/li&gt;
&lt;li&gt;水平扩展困难，分库分表复杂度高（需处理分布式事务和跨分片查询）。&lt;/li&gt;
&lt;li&gt;不适合存储半结构化数据（如JSON文档、嵌套数组）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;代表数据库：&lt;code&gt;MySQL&lt;/code&gt;、&lt;code&gt;PostgreSQL&lt;/code&gt;、&lt;code&gt;Oracle&lt;/code&gt;、&lt;code&gt;SQL Server&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="nosql-数据库灵活性与扩展性的革命"&gt;&lt;a href="#nosql-%e6%95%b0%e6%8d%ae%e5%ba%93%e7%81%b5%e6%b4%bb%e6%80%a7%e4%b8%8e%e6%89%a9%e5%b1%95%e6%80%a7%e7%9a%84%e9%9d%a9%e5%91%bd" class="header-anchor"&gt;&lt;/a&gt;NoSQL 数据库：灵活性与扩展性的革命
&lt;/h3&gt;&lt;p&gt;NoSQL（Not Only SQL）的诞生是为了解决关系型数据库在扩展性、灵活性和高性能场景下的不足。根据数据模型的差异，NoSQL 可进一步细分为四类：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 文档型数据库（Document Database）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;数据模型：以文档为基本单元，通常采用JSON或BSON格式存储，支持嵌套结构和动态字段&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;user_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;张三&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;orders&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;order_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;amount&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;150.0&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;order_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2002&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;amount&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;300.0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;查询能力：支持基于文档属性的查询，部分数据库（如MongoDB）提供类SQL的聚合管道（Aggregation Pipeline）和索引优化。&lt;/p&gt;
&lt;p&gt;适用场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;内容管理系统（CMS）中文章的多版本存储。&lt;/li&gt;
&lt;li&gt;用户配置文件的动态字段管理（如社交平台用户的个性化标签）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;局限性：跨文档事务支持较弱（MongoDB 4.0后支持多文档事务，但性能损耗较大）。&lt;/p&gt;
&lt;p&gt;代表数据库：&lt;code&gt;MongoDB&lt;/code&gt;、&lt;code&gt;Couchbase&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 键值型数据库（Key-Value Store）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;数据模型：最简单的 NoSQL 模型，数据以键值对（Key-Value）形式存储，Value可以是任意二进制数据。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;Key: &amp;#34;user:101:profile&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;Value: &amp;#34;{&amp;#39;name&amp;#39;: &amp;#39;李四&amp;#39;, &amp;#39;last_login&amp;#39;: &amp;#39;2023-10-01&amp;#39;}&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;高性能特性：通过哈希表实现O(1)时间复杂度的读写操作，适合缓存和高并发场景。&lt;/p&gt;
&lt;p&gt;适用场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;会话存储（Session Storage）：快速存取用户登录状态。&lt;/li&gt;
&lt;li&gt;分布式缓存（如Redis缓存热门商品信息）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;局限性：缺乏复杂查询能力（仅能通过Key检索），需业务层处理数据关联逻辑。&lt;/p&gt;
&lt;p&gt;代表数据库：&lt;code&gt;Redis&lt;/code&gt;、&lt;code&gt;Memcached&lt;/code&gt;、&lt;code&gt;Amazon DynamoDB&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. 列族数据库（Wide-Column Store）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;数据模型：数据按列族（Column Family）组织，每行可动态添加列，适合稀疏矩阵存储。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;Row Key: &amp;#34;device_001&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;Columns: 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; &amp;#34;metrics:temperature&amp;#34; -&amp;gt; 25.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &amp;#34;metrics:humidity&amp;#34; -&amp;gt; 60%
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; &amp;#34;location:city&amp;#34; -&amp;gt; &amp;#34;北京&amp;#34; 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;存储优势：基于LSM树（Log-Structured Merge Tree）的存储引擎，优化高吞吐写入（如日志、传感器数据）。&lt;/p&gt;
&lt;p&gt;适用场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;时间序列数据（物联网设备监控）。&lt;/li&gt;
&lt;li&gt;海量数据的随机读写（如HBase存储网页爬虫数据）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;局限性：复杂查询需依赖Row Key设计，二级索引支持有限。&lt;/p&gt;
&lt;p&gt;代表数据库：&lt;code&gt;Apache HBase&lt;/code&gt;、&lt;code&gt;Cassandra&lt;/code&gt;、&lt;code&gt;Google Bigtable&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. 图数据库（Graph Database）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;数据模型：以图论为基础，通过节点（Node）、边（Edge）、属性（Property）表示实体及其关系。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;Node: User(id=101, name=&amp;#34;王五&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;Edge: User101 -[FRIEND]-&amp;gt; User102 (since=2020)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;/ul&gt;
&lt;p&gt;局限性：非关系场景下性能无明显优势，学习曲线陡峭。&lt;/p&gt;
&lt;p&gt;代表数据库：&lt;code&gt;Neo4j&lt;/code&gt;、&lt;code&gt;Amazon Neptune&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="大数据生态数据库分布式与批量处理的支柱"&gt;&lt;a href="#%e5%a4%a7%e6%95%b0%e6%8d%ae%e7%94%9f%e6%80%81%e6%95%b0%e6%8d%ae%e5%ba%93%e5%88%86%e5%b8%83%e5%bc%8f%e4%b8%8e%e6%89%b9%e9%87%8f%e5%a4%84%e7%90%86%e7%9a%84%e6%94%af%e6%9f%b1" class="header-anchor"&gt;&lt;/a&gt;大数据生态数据库：分布式与批量处理的支柱
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;1. 分布式列式存储（HBase）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;技术架构：基于HDFS的分布式存储，通过Region分片实现水平扩展，ZooKeeper协调元数据。&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;适用场景：实时查询TB级数据（如电信通话记录检索）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 数据仓库（Hive）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;技术原理：将结构化数据映射为HDFS文件，通过 HiveQL（类SQL）转换为MapReduce或Tez任务。&lt;/p&gt;
&lt;p&gt;核心能力：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;离线批量处理（小时级延迟）。&lt;/li&gt;
&lt;li&gt;复杂ETL流程（数据清洗、转换）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;适用场景：历史数据报表生成（如零售业月度销售分析）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. 实时数仓（ClickHouse、Doris）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;技术突破：向量化执行引擎、列式存储、预聚合，实现亚秒级响应。&lt;/p&gt;
&lt;p&gt;适用场景：交互式OLAP分析（如广告投放效果实时看板）。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/001-609ddd79.png"&gt;&lt;/p&gt;
&lt;h3 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h3&gt;&lt;p&gt;我们做一个整体的对比&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/002-4df3e69a.png"&gt;&lt;/p&gt;
&lt;p&gt;随着技术发展，数据库的界限逐渐模糊。例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;多模型数据库：如PostgreSQL通过扩展支持JSONB（文档模型）和Citus（分布式能力）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;HTAP&lt;/code&gt;(Hybrid Transactional/Analytical Processing)数据库：TiDB、Oracle Exadata支持OLTP与OLAP混合负载。&lt;/li&gt;
&lt;li&gt;AI驱动数据库：利用机器学习优化查询计划（如Google AlloyDB）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;随着 AI 技术的兴起，&lt;code&gt;向量数据库&lt;/code&gt;也是非常热门的一类数据库。数据库的分类也并非绝对的技术壁垒，而是反映了不同场景下的核心矛盾权衡：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;结构化 vs 灵活性&lt;/strong&gt;：关系型牺牲灵活性换取严格约束，文档型反之。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;一致性 vs 扩展性&lt;/strong&gt;：CP系统（如ZooKeeper）优先保障一致性，AP系统（如Cassandra）优先保障可用性。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实时性 vs 吞吐量&lt;/strong&gt;：HBase优化单点查询延迟，Hive优化批量吞吐量。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;理解这些分类背后的哲学，才能避免“技术选型中的锤子效应”（手里只有一把锤子，看所有问题都是钉子），从而在复杂业务场景中构建合理的数据存储架构。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="数据类型"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e7%b1%bb%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;数据类型
&lt;/h2&gt;&lt;p&gt;在进行数据库的选择前，你要处理的数据类型是你必须要明确的。&lt;/p&gt;
&lt;p&gt;结构化、半结构化和非结构化数据在存储、查询和处理方式上存在本质差异，直接影响了技术选型的路径。&lt;/p&gt;
&lt;p&gt;在数据管理的实践中，数据类型是决定数据库选型的关键因素之一。结构化、半结构化和非结构化数据在存储、查询和处理方式上存在本质差异，直接影响了技术选型的路径。以下从数据特征、处理需求到典型数据库选择展开系统性分析。&lt;/p&gt;
&lt;h3 id="结构化数据秩序与约束的领域"&gt;&lt;a href="#%e7%bb%93%e6%9e%84%e5%8c%96%e6%95%b0%e6%8d%ae%e7%a7%a9%e5%ba%8f%e4%b8%8e%e7%ba%a6%e6%9d%9f%e7%9a%84%e9%a2%86%e5%9f%9f" class="header-anchor"&gt;&lt;/a&gt;结构化数据：秩序与约束的领域
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;1. 核心特征&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;严格模式（Schema）：数据字段预先定义，类型明确（如整数、日期、枚举值）。&lt;/li&gt;
&lt;li&gt;二维表结构：数据以行和列的形式组织，遵循第一范式（1NF）到第三范式（3NF）的规范。&lt;/li&gt;
&lt;li&gt;强关联性：通过外键建立表间关系，支持JOIN操作实现跨表查询。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;示例：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;银行账户表：&lt;code&gt;账户ID (主键) | 户主姓名 | 余额 | 开户日期&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;电商订单表：&lt;code&gt;订单ID | 用户ID (外键) | 商品ID (外键) | 订单金额 | 支付状态&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;2. 数据库选择&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;首选：关系型数据库（RDBMS）。它的选型逻辑：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;事务完整性：需要ACID保障的场景（如转账操作）。&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;ul&gt;
&lt;li&gt;MySQL/PostgreSQL：适用于中小规模OLTP系统。&lt;/li&gt;
&lt;li&gt;Oracle：企业级高并发、高可靠性需求（如金融核心系统）。&lt;/li&gt;
&lt;li&gt;TiDB：分布式架构下仍需强一致性的场景（如跨境支付平台）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3. 反模式案例&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;错误尝试：将用户行为日志（半结构化JSON）存入MySQL。这样做的问题是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;需要为动态字段创建稀疏列，导致存储空间浪费。&lt;/li&gt;
&lt;li&gt;频繁ALTER TABLE修改表结构，引发锁表风险。&lt;/li&gt;
&lt;li&gt;查询嵌套字段需解析JSON字符串，性能低下。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="半结构化数据灵活性与动态性的平衡"&gt;&lt;a href="#%e5%8d%8a%e7%bb%93%e6%9e%84%e5%8c%96%e6%95%b0%e6%8d%ae%e7%81%b5%e6%b4%bb%e6%80%a7%e4%b8%8e%e5%8a%a8%e6%80%81%e6%80%a7%e7%9a%84%e5%b9%b3%e8%a1%a1" class="header-anchor"&gt;&lt;/a&gt;半结构化数据：灵活性与动态性的平衡
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;1. 核心特征&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;松散模式：字段可动态增减，数据类型允许一定灵活性。&lt;/li&gt;
&lt;li&gt;层次化结构：数据以树形或网状形式组织（如JSON、XML）。&lt;/li&gt;
&lt;li&gt;自描述性：数据本身携带元信息（如字段名称、嵌套关系）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;示例：用户配置文件&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;user_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;preferences&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;theme&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;dark&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;notifications&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;email&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;sms&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;last_activity&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;login&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2023-10-05T08:30:00Z&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;purchase&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;&amp;#34;item_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;SKU123&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;设备传感器元数据：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;device&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;D001&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;location&lt;/span&gt; &lt;span class="na"&gt;lat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;39.9042&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;lon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;116.4074&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;sensors&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;sensor&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;temperature&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;unit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;°C&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;sensor&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;humidity&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;unit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;%&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;sensors&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;device&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;/li&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;p&gt;MongoDB：&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;适用场景：CMS内容管理、物联网设备元数据存储。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;优势：BSON二进制存储、聚合管道、地理位置索引。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;限制：事务跨文档操作成本高（需4.0+版本）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cassandra：&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;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;li&gt;
&lt;p&gt;限制：写入吞吐受分片数限制，不支持事务。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3. 混合架构实践&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;典型组合：MySQL + MongoDB + Elasticsearch。 数据流示例：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用户注册信息（结构化）存入MySQL。&lt;/li&gt;
&lt;li&gt;用户行为轨迹（半结构化JSON）写入MongoDB。&lt;/li&gt;
&lt;li&gt;关键字段（如用户ID、行为类型）同步到Elasticsearch供快速检索。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="非结构化数据海量与多元化的挑战"&gt;&lt;a href="#%e9%9d%9e%e7%bb%93%e6%9e%84%e5%8c%96%e6%95%b0%e6%8d%ae%e6%b5%b7%e9%87%8f%e4%b8%8e%e5%a4%9a%e5%85%83%e5%8c%96%e7%9a%84%e6%8c%91%e6%88%98" class="header-anchor"&gt;&lt;/a&gt;非结构化数据：海量与多元化的挑战
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;1. 核心特征&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;/p&gt;
&lt;ul&gt;
&lt;li&gt;媒体文件：监控摄像头的1080P视频流（MP4格式）。&lt;/li&gt;
&lt;li&gt;办公文档：PDF合同、Word报告。&lt;/li&gt;
&lt;/ul&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;存储效率：需支持大文件分块存储（如HDFS的128MB块）。&lt;/li&gt;
&lt;li&gt;元数据管理：通过附加结构化信息实现快速检索。&lt;/li&gt;
&lt;li&gt;访问接口：提供HTTP API或对象存储接口（如S3兼容）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;代表方案：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;对象存储：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Amazon S3/阿里云OSS：存储图片、视频等静态资源。&lt;/li&gt;
&lt;li&gt;MinIO：自建私有化对象存储方案。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="3"&gt;
&lt;li&gt;分布式文件系统：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;HDFS：用于Hadoop生态的原始文件存储。&lt;/li&gt;
&lt;li&gt;Ceph：统一存储池支持块、文件、对象接口。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="5"&gt;
&lt;li&gt;专用数据库扩展：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;MongoDB GridFS：将大文件分块存储为文档。&lt;/li&gt;
&lt;li&gt;PostgreSQL大对象（LOB）：通过TOAST机制存储二进制数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3. 元数据关联策略&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;典型架构是：对象存储 + 关系型数据库。分两步：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;数据流：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;上传视频文件到S3，获得存储路径&lt;code&gt;s3://bucket/video_001.mp4&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;在MySQL中创建记录：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;media_files&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s3_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uploader_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s3://bucket/video_001.mp4&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;501&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;1920x1080&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;
&lt;li&gt;查询过程：&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- 查找用户501上传的高清视频
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s3_path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;media_files&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uploader_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;501&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;resolution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;1920x1080&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="总结-1"&gt;&lt;a href="#%e6%80%bb%e7%bb%93-1" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h3&gt;&lt;p&gt;总结一下不同数据类型的特点&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/003-ff369010.png"&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;p&gt;说了这么多，虽然对于数据是什么类型有了比较清楚的定义和区分，但是数据到底是结构化的还是非结构化的，其实&lt;strong&gt;主要是看 “数据的组织方式”和“处理方式”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这里举个例子，比如 &lt;code&gt;用户评论&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;如果我们只是想简单的读写用户评论，可以把它用关系型数据库存储，当作一个表中的一个字段:&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;在评论内容（CommentContent）这个字段中，我们可以存储用户的评论文本。对于包含的表情、图片等多媒体元素，也有一些常见的处理方法。例如，把表情转换为编码存储，而图片可以存储在文件服务器上，并在数据库中保存链接地址。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;如果把用户评论当成非结构化数据，那么它的&lt;strong&gt;处理方式&lt;/strong&gt;就会更加复杂。&lt;/p&gt;
&lt;p&gt;用户评论的内容通常是文本信息，但其实不容易进行有效的结构化处理。评论的长度、格式、语言等都可能差异很大，甚至某些评论可能包含表情符号或者图片等多媒体元素。这些元素都无法通过预定义的数据模型进行有效地分类和组织，因此我们将其当做非结构化数据来处理。&amp;ndash;这里主要是指数据的&lt;strong&gt;组织方式&lt;/strong&gt;。&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;p&gt;具体实现架构如下：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/004-560fe49f.png"&gt;&lt;/p&gt;
&lt;p&gt;用户评论的存储与分析系统需结合多种技术实现高效处理。在存储层设计中，推荐采用混合存储架构以满足非结构化数据的持久化需求。核心存储使用MongoDB文档数据库保存完整的评论内容（如文本、表情编码、图片链接等），其灵活的JSON结构支持动态字段扩展，例如可包含用户设备信息、地理位置等元数据。同时，MongoDB的水平扩展能力和聚合查询功能可有效支持大规模数据管理。对于评论中的图片、视频等二进制文件，则通过对象存储（如Amazon S3或阿里云OSS）存储，结合预签名URL实现安全访问，避免数据库性能损耗。辅助索引层采用Elasticsearch同步关键字段，通过倒排索引和中文分词技术（如IK分词）实现秒级全文检索，并支持模糊搜索与高亮显示。&lt;/p&gt;
&lt;p&gt;在场景化应用中，情感分析可通过多种技术实现：对于中文评论，SnowNLP或Hugging Face的BERT模型能精准识别情感倾向，例如通过预训练模型对“电池续航太差”等文本输出负面标签及置信度评分。评论分类则结合监督学习（如SVM、BERT）与无监督方法（如K-Means聚类），通过FastAPI构建实时分类服务或使用Spark进行批量处理。全文搜索功能由Elasticsearch支撑，通过MongoDB Connector实现实时数据同步，支持用户快速定位包含特定关键词的评论内容。主题模型则利用LDA、BERTopic等算法从海量评论中提取高频主题（如“屏幕质量”“物流服务”），并通过WordCloud等工具可视化呈现，帮助业务方洞察用户关注焦点。整个架构通过混合存储与多技术协同，在保证性能的同时实现成本优化。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="应用场景"&gt;&lt;a href="#%e5%ba%94%e7%94%a8%e5%9c%ba%e6%99%af" class="header-anchor"&gt;&lt;/a&gt;应用场景
&lt;/h2&gt;&lt;p&gt;数据库选型的核心是：理解业务数据的生命周期，把握各类数据库的能力边界，在架构灵活性与技术可控性之间寻找最佳平衡点。任何脱离具体业务场景的数据库对比都是无效的，优秀的架构设计应当像精密钟表般，让每个齿轮（数据库）在最适合的位置发挥最大效能。&lt;/p&gt;
&lt;p&gt;结合典型应用场景，什么场景应该用什么数据库呢？其实在一个业务场景下需要多种类数据库结合使用，总结如下：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/005-00b9fa8f.png"&gt;&lt;/p&gt;
&lt;p&gt;我们以单个数据库为维度再分别讨论一下：&lt;/p&gt;
&lt;h3 id="关系型mysql"&gt;&lt;a href="#%e5%85%b3%e7%b3%bb%e5%9e%8bmysql" class="header-anchor"&gt;&lt;/a&gt;关系型:MySQL
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/006-22a3aff1.png"&gt;&lt;/p&gt;
&lt;p&gt;MySQL：高并发事务系统（如电商订单处理）&lt;/p&gt;
&lt;p&gt;核心场景：电商平台的订单系统，需要保证每笔交易的原子性（如扣减库存、生成订单、支付记录必须同时成功或回滚）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择MySQL&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ACID事务支持：通过InnoDB引擎实现强一致性，确保订单状态的准确性。&lt;/li&gt;
&lt;li&gt;复杂查询能力：支持多表JOIN（如查询用户历史订单及商品详情）。&lt;/li&gt;
&lt;li&gt;成熟生态：主从复制、分库分表工具（如ShardingSphere）支持高可用和扩展。&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;MongoDB&lt;/strong&gt;：不支持跨文档事务（早期版本），不适合强一致性场景。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Redis&lt;/strong&gt;：内存数据库，无法持久化复杂事务逻辑。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：每秒处理10万笔订单的电商平台，通过MySQL分库分表（按用户ID哈希）实现横向扩展。&lt;/p&gt;
&lt;h3 id="搜索引擎es"&gt;&lt;a href="#%e6%90%9c%e7%b4%a2%e5%bc%95%e6%93%8ees" class="header-anchor"&gt;&lt;/a&gt;搜索引擎：ES
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/007-559c2219.png"&gt;&lt;/p&gt;
&lt;p&gt;Elasticsearch：实时商品搜索与日志分析&lt;/p&gt;
&lt;p&gt;核心场景：电商平台商品搜索，用户输入关键词（如“防水运动鞋”）后毫秒级返回结果。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择Elasticsearch&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;近实时（NRT）&lt;/strong&gt;：新上架商品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;strong&gt;MySQL&lt;/strong&gt;：全文索引性能差，无法支持高并发搜索。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;：文本搜索功能简单，缺乏分词器和相关性排序。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：某跨境电商平台，每日处理1亿次搜索请求，通过ES集群（分片+副本）实现99.9%的查询响应时间&amp;lt;50ms。&lt;/p&gt;
&lt;h3 id="文档型mongodb"&gt;&lt;a href="#%e6%96%87%e6%a1%a3%e5%9e%8bmongodb" class="header-anchor"&gt;&lt;/a&gt;文档型：MongoDB
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/008-6afc9d95.png"&gt;&lt;/p&gt;
&lt;p&gt;MongoDB：内容管理系统（CMS）与动态配置存储**&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心场景&lt;/strong&gt;：新闻发布平台的文章存储，每篇文章包含标题、正文、多级评论、动态标签。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择MongoDB&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;灵活文档模型&lt;/strong&gt;：存储嵌套结构的JSON数据（如评论树形结构）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;水平扩展&lt;/strong&gt;：通过Sharding自动分配数据到多个分片。&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;ul&gt;
&lt;li&gt;&lt;strong&gt;MySQL&lt;/strong&gt;：需要拆分为多张表（文章表、评论表），JOIN查询效率低。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HBase&lt;/strong&gt;：适合结构化扫描，不适合嵌套数据查询。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：某媒体平台存储1000万篇文章，每篇文章包含动态标签（如“科技, 2023趋势”），通过MongoDB的文档结构直接存储。&lt;/p&gt;
&lt;h3 id="键值存储redis"&gt;&lt;a href="#%e9%94%ae%e5%80%bc%e5%ad%98%e5%82%a8redis" class="header-anchor"&gt;&lt;/a&gt;键值存储：Redis
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/009-116b15b9.png"&gt;&lt;/p&gt;
&lt;p&gt;Redis：高频访问缓存与会话管理&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心场景&lt;/strong&gt;：社交平台的热门帖子缓存，用户访问时优先从缓存读取，减少数据库压力。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择Redis&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;内存存储&lt;/strong&gt;：读写延迟&amp;lt;1ms，支持每秒百万级操作。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据结构丰富&lt;/strong&gt;：使用Sorted Set存储热门帖子排行榜，Hash存储用户会话信息。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;持久化可选&lt;/strong&gt;：RDB快照或AOF日志保障数据安全。&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;MySQL&lt;/strong&gt;：磁盘存储，无法满足毫秒级响应。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;：内存占用高，不适合纯缓存场景。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：某论坛每日活跃用户500万，通过Redis缓存前1000热门帖子，命中率90%，数据库负载下降70%。&lt;/p&gt;
&lt;h3 id="宽列存储hbasecassandra"&gt;&lt;a href="#%e5%ae%bd%e5%88%97%e5%ad%98%e5%82%a8hbasecassandra" class="header-anchor"&gt;&lt;/a&gt;宽列存储：HBase、Cassandra
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/010-9e144a87.png"&gt;&lt;/p&gt;
&lt;p&gt;HBase：海量时序数据存储（如物联网设备监控）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心场景&lt;/strong&gt;：电力公司存储智能电表每秒采集的电流、电压数据。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择HBase&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;：按设备ID+时间戳快速查询某时刻数据。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HDFS集成&lt;/strong&gt;：数据自动下沉至HDFS实现低成本归档。&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;Cassandra&lt;/strong&gt;：适合跨数据中心写入，但单点查询性能不如HBase。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MySQL&lt;/strong&gt;：无法支持每秒百万级数据写入。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：某物联网平台每日新增1TB传感器数据，通过HBase的RowKey设计（设备ID+时间戳）实现毫秒级查询。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/011-87d2288b.png"&gt;&lt;/p&gt;
&lt;p&gt;Cassandra：多数据中心日志同步（如全球化应用）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心场景&lt;/strong&gt;：跨国社交应用的聊天日志存储，要求数据在欧美亚三地就近写入且最终一致。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择Cassandra&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;：LSM树引擎支持每秒百万级写入。&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;ul&gt;
&lt;li&gt;&lt;strong&gt;HBase&lt;/strong&gt;：依赖HDFS和ZooKeeper，扩展性受限。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MySQL&lt;/strong&gt;：主从复制跨地域延迟高。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：某IM应用每日处理50亿条消息，通过Cassandra实现三地数据中心写入延迟&amp;lt;10ms。&lt;/p&gt;
&lt;h3 id="数据仓库hive"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e4%bb%93%e5%ba%93hive" class="header-anchor"&gt;&lt;/a&gt;数据仓库：Hive
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/012-a845c0c5.png"&gt;&lt;/p&gt;
&lt;p&gt;Hive：离线数据仓库与ETL批处理&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心场景&lt;/strong&gt;：零售企业每月销售数据的批量清洗与报表生成。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择Hive&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SQL兼容&lt;/strong&gt;：通过HiveQL实现类SQL查询，降低学习成本。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;海量数据批处理&lt;/strong&gt;：基于MapReduce或Tez引擎处理TB级数据。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;低成本存储&lt;/strong&gt;：数据存储在HDFS，支持压缩格式（ORC、Parquet）。&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;ClickHouse&lt;/strong&gt;：适合实时分析，但存储成本高。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MySQL&lt;/strong&gt;：无法处理PB级数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：某电商每月分析10TB历史订单数据，通过Hive生成“年度区域销售趋势”报表，耗时2小时。&lt;/p&gt;
&lt;h3 id="列式存储clickhouse"&gt;&lt;a href="#%e5%88%97%e5%bc%8f%e5%ad%98%e5%82%a8clickhouse" class="header-anchor"&gt;&lt;/a&gt;列式存储：ClickHouse
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/013-c7953de3.png"&gt;&lt;/p&gt;
&lt;p&gt;ClickHouse：实时OLAP与用户行为分析&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心场景&lt;/strong&gt;：广告平台的实时点击流分析，每日处理千亿级事件，生成实时报表。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择ClickHouse&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;列式存储&lt;/strong&gt;：压缩率高，适合聚合计算（如SUM、COUNT）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;向量化执行&lt;/strong&gt;：利用CPU SIMD指令加速查询。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实时写入&lt;/strong&gt;：支持Kafka直接导入数据，延迟低至秒级。&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;Hive&lt;/strong&gt;：批处理模式，查询延迟分钟级。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MySQL&lt;/strong&gt;：无法支撑海量数据聚合。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：某广告平台分析每日200亿次点击事件，通过ClickHouse集群实现“过去1小时各渠道转化率”秒级响应。&lt;/p&gt;
&lt;h3 id="图数据库neo4j"&gt;&lt;a href="#%e5%9b%be%e6%95%b0%e6%8d%ae%e5%ba%93neo4j" class="header-anchor"&gt;&lt;/a&gt;图数据库：Neo4j
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/014-d3af3ea6.png"&gt;&lt;/p&gt;
&lt;p&gt;Neo4j：社交网络关系挖掘（如好友推荐）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心场景&lt;/strong&gt;：社交平台的“六度关系”分析，计算用户A到用户B的最短路径。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么选择Neo4j&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;Cypher查询语言&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;ul&gt;
&lt;li&gt;&lt;strong&gt;MySQL&lt;/strong&gt;：需递归JOIN，性能随跳数指数级下降。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;：无法直接表达关系网络。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：某社交平台分析10亿用户关系，Neo4j可在毫秒级返回“用户A的三度人脉中可能认识的人”。&lt;/p&gt;
&lt;h3 id="总结-2"&gt;&lt;a href="#%e6%80%bb%e7%bb%93-2" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;事务强一致&lt;/strong&gt; → MySQL&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实时搜索&lt;/strong&gt; → Elasticsearch&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;动态文档&lt;/strong&gt; → MongoDB&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;高频缓存&lt;/strong&gt; → Redis&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实时OLAP&lt;/strong&gt; → ClickHouse&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;时序海量存储&lt;/strong&gt; → HBase&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;全球化写入&lt;/strong&gt; → Cassandra&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;关系网络&lt;/strong&gt; → Neo4j&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;离线批处理&lt;/strong&gt; → Hive&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/015-95068fb0.png"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="最后总结"&gt;&lt;a href="#%e6%9c%80%e5%90%8e%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;最后总结
&lt;/h2&gt;&lt;p&gt;**数据模型的本质差异是选型的第一道分水岭。**关系型数据库（如MySQL、PostgreSQL）建立在严格的二维表结构之上，通过外键约束和范式理论保障数据完整性。这种结构特别适合需要复杂关联查询的财务系统、ERP等业务场景。例如银行转账操作需要严格遵循ACID事务原则，MySQL的InnoDB引擎通过行级锁和MVCC机制实现事务隔离，配合主从复制架构可以满足多数金融级需求。但在物联网设备日志存储场景下，每天千万级的写入请求会导致关系型数据库的索引维护成本急剧上升，此时文档型数据库MongoDB的BSON自由格式和分片集群优势便显现出来。MongoDB的写操作默认不等待磁盘确认，通过内存映射文件实现高速写入，特别适合内容管理系统或实时分析场景中半结构化数据的快速摄入。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;分布式架构的CAP权衡直接影响系统可用性。&lt;/strong&gt; Elasticsearch作为分布式搜索引擎，其倒排索引结构对文本检索的优化已达到毫秒级响应，在电商商品搜索、日志分析等场景具有不可替代性。但ES的强一致性模型可能导致集群脑裂风险，需要结合zen discovery机制进行节点状态管理。相比之下，HBase作为Hadoop生态的列式存储，通过RegionServer的水平扩展和LSM树的写入优化，能够承载PB级数据量的实时读写。某智慧城市项目曾使用HBase存储数十亿条交通卡口数据，利用其行键有序分布特性实现车辆轨迹的快速回溯，这是传统关系型数据库难以企及的吞吐能力。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;计算与存储的分离趋势重构了数据分析范式。&lt;/strong&gt; Hive建立在HDFS之上的元数据管理机制，通过类SQL语法实现大数据集的离线分析，其分区表和桶表的设计显著提升了TB级数据查询效率。某电商平台的历史订单分析采用Hive进行月度销售统计，配合Tez执行引擎将任务耗时从小时级压缩到分钟级。但Hive的高延迟特性使其不适合实时查询场景，这正是ClickHouse等OLAP数据库的突破方向。需要特别注意的是，数据湖架构的兴起使得Delta Lake、Hudi等解决方案开始融合事务管理和批流一体处理，这对传统数仓选型提出了新的挑战。&lt;/p&gt;
&lt;p&gt;**事务完整性与系统弹性的平衡艺术。**当业务需要跨数据库操作时，如电商订单系统同时涉及MySQL库存扣减和MongoDB订单日志记录，分布式事务管理就成为关键挑战。Saga模式通过补偿机制实现最终一致性，而Seata框架的AT模式能在业务侵入性较低的情况下保障事务边界。但在高并发场景下，这类方案的性能损耗可能达到20%-30%，这就需要架构师在一致性级别和系统吞吐之间做出权衡。例如社交平台的点赞功能更适合使用Redis的原子计数器，完全放弃强一致性以换取百万级QPS的处理能力。&lt;/p&gt;
&lt;p&gt;**硬件成本与运维复杂度的隐藏成本。**云原生时代，AWS Aurora通过计算存储分离架构实现了MySQL兼容数据库的自动扩缩容，其存储层可自动扩展到128TB，这种托管服务显著降低了运维负担。但对于需要定制化优化的场景，如金融行业的风控模型计算，仍需要基于物理机部署的Oracle RAC集群来保障IOPS性能。开源方案的隐性成本同样不容忽视，Elasticsearch集群的JVM堆内存配置直接影响索引性能，不当的分片设置可能导致磁盘空间浪费，这需要运维团队积累足够的调优经验。&lt;/p&gt;
&lt;p&gt;在具体选型实践中，建议采用四维评估法：首先明确数据结构化程度（结构化、半结构化、非结构化），其次分析读写比例和并发量级，再次确定一致性要求（强一致、最终一致），最后考量扩展性和生态集成需求。例如智能穿戴设备数据采集场景，设备标识符作为MongoDB文档的天然主键，时间序列数据采用嵌套文档存储，既避免了关系型数据库的表关联开销，又利用TTL索引实现自动过期清理。而在用户画像分析场景，HBase 的宽表结构可以存储数千个用户标签，配合Phoenix的SQL层实现灵活查询，这种架构组合充分发挥了列式存储的高压缩比优势。&lt;/p&gt;
&lt;p&gt;最后我们用一个简单的流程图来说明一下这个选型过程：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-14-shu-ju-ku-xuan-xing-zhong-ji-zhi-nan-cong-shu-ju-lei-xing-da/016-d55b1bf4.png"&gt;&lt;/p&gt;</description></item><item><title>Milvus实战：如何用一个数据库提升你的AI项目性能</title><link>https://xiaobox.github.io/p/2024-10-11-milvus-shi-zhan-ru-he-yong-yi-ge-shu-ju-ku-ti-sheng-ni-de-ai/</link><pubDate>Fri, 11 Oct 2024 08:22:08 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-10-11-milvus-shi-zhan-ru-he-yong-yi-ge-shu-ju-ku-ti-sheng-ni-de-ai/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-10-11-milvus-shi-zhan-ru-he-yong-yi-ge-shu-ju-ku-ti-sheng-ni-de-ai/cover.jpg" alt="Featured image of post Milvus实战：如何用一个数据库提升你的AI项目性能" /&gt;&lt;h2 id="回顾"&gt;&lt;a href="#%e5%9b%9e%e9%a1%be" class="header-anchor"&gt;&lt;/a&gt;回顾
&lt;/h2&gt;&lt;p&gt;在上一文中我们使用 LlamaIndex 整合 智谱 AI 的 GLM-4 和 Embedding-3 模型一起构建 RAG 应用。&lt;/p&gt;
&lt;p&gt;在上篇文章的最后，我们发现因为 Embedding-3 模型是同步调用的，所以从测试效果看比较慢。每一次运行都产生了大量的 http 同步请求。文末我说解决的办法可以在本地部署一个开源的 embedding 模型，这样就不会产生远程的 http 调用了，而且也比较省钱。&lt;/p&gt;
&lt;p&gt;这是个办法，但实际上还有其他的好办法。&lt;/p&gt;
&lt;p&gt;我们可以将 &lt;strong&gt;文档通过 embedding 模型产生的向量存储起来，这样相同的文档，只有在第一次 embedding 时会慢一些，再次检索时，可以快速地将已经保存好的向量查询出来使用。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="本地文件存储"&gt;&lt;a href="#%e6%9c%ac%e5%9c%b0%e6%96%87%e4%bb%b6%e5%ad%98%e5%82%a8" class="header-anchor"&gt;&lt;/a&gt;本地文件存储
&lt;/h2&gt;&lt;p&gt;利用 LlamaIndex 的 API ，我们可以非常方便地把向量存储到本地文件，以下是一个例子，我把向量存储到项目的 &lt;code&gt;index&lt;/code&gt;目录下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_or_create_index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 检查是否存在有效的持久化索引&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;index&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;index&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nb"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;.json&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;index&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;正在加载现有索引。..&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;storage_context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StorageContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_defaults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;persist_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;index&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;load_index_from_storage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;storage_context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;未找到有效的现有索引，正在创建新索引。..&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 使用预定义的 DATA_DIR 常量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 创建新索引，显示 embedding 进度&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;show_progress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 持久化索引&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;storage_context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;persist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;persist_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;index&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;索引已创建并保存到本地。&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;看起来代码多，实际上重要的就是这两行：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;storage_context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StorageContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_defaults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;persist_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;index&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;load_index_from_storage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;storage_context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;也很容易理解，见文知意。&lt;/p&gt;
&lt;p&gt;索引创建后，&lt;code&gt;index&lt;/code&gt; 会自动创建一些文件来保存向量信息：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-10-11-milvus-shi-zhan-ru-he-yong-yi-ge-shu-ju-ku-ti-sheng-ni-de-ai/001-33676f25.png"&gt;&lt;/p&gt;
&lt;h2 id="向量数据库"&gt;&lt;a href="#%e5%90%91%e9%87%8f%e6%95%b0%e6%8d%ae%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;向量数据库
&lt;/h2&gt;&lt;p&gt;一般情况下，比如小型项目，将向量数据保存在系统文件中就已经够用了。但是，在中大型项目中，由于数据规模较大，使用人数较多，为了方便管理和扩展，我们会使用专业的向量数据库来存储和管理向量数据。&lt;/p&gt;
&lt;p&gt;你可以借助下图了解下向量数据库在 AIGC 应用架构中的位置和作用&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-10-11-milvus-shi-zhan-ru-he-yong-yi-ge-shu-ju-ku-ti-sheng-ni-de-ai/002-4d7dc065.png"&gt;&lt;/p&gt;
&lt;h3 id="向量数据库选型"&gt;&lt;a href="#%e5%90%91%e9%87%8f%e6%95%b0%e6%8d%ae%e5%ba%93%e9%80%89%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;向量数据库选型
&lt;/h3&gt;
 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;RAG 系统的成功在很大程度上取决于其高效地获取和处理海量信息的能力。向量数据库又在其中发挥了不可替代的作用，并构成了 RAG 系统的核心&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;不看不知道，作为一个数据库软件 ，目前向量数据库领域是真卷啊，打眼一看至少有几十个。知名的也得有 10 几个。&lt;/p&gt;
&lt;p&gt;说实话，最开始还真有些茫然，有点儿挑花眼了，我们这里列举几个知名的向量数据库：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Milvus&lt;/strong&gt; 是一个 2019 年开源的纯向量数据库，号称全球最先进的开源向量数据库。它是 &lt;code&gt;LF AI &amp;amp; Data Foundation&lt;/code&gt;（简称 &lt;strong&gt;LFAI，它相当于 CNCF 在云原生界的地位&lt;/strong&gt;）赞助的毕业项目&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Chroma&lt;/strong&gt; 是一个相对较新的向量数据库，目前它的设计确实是以单节点模式为主，主要用于中小型应用或开发测试环境。然而，对于需要更高可用性和横向扩展能力的生产环境，Chroma 当前的版本可能还不完全满足需求。Chroma 内置了 &lt;code&gt;SQLite&lt;/code&gt; 作为其底层存储引擎&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Weaviate&lt;/strong&gt; ：是一个云原生的、开源的向量数据库。专为大规模的向量数据存储和检索设计。它结合了向量搜索和图数据库的优势，适用于机器学习、推荐系统、图像识别和自然语言处理等场景。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Faiss&lt;/strong&gt; ：由 Facebook AI Research 开发的 Faiss 是一个开源库，用于快速、密集向量相似性搜索和分组&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Qdrant&lt;/strong&gt; 是一个开源的向量数据库，专为高效的大规模向量数据存储和检索设计。它适用于机器学习、推荐系统、图像识别和自然语言处理等场景，提供了高性能和易用性的结合。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PGVector&lt;/strong&gt; 是一个基于 PostgreSQL 的扩展插件，旨在提供强大的向量存储和查询功能，PGVector 可以无缝集成到现有的 PostgreSQL 数据库中，用户无需迁移现有的数据库即可开始使用向量搜索功能。因为是 PostgreSQL 插件，借助 PostgreSQL 的长期开发和优化，PGVector 继承了其可靠性和稳健性，同时在向量化处理方面进行了增强。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;整体上看在向量数据库领域有这么几类玩家：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;专做向量数据库的，大部分是开源的，如 Chroma、Weaviate 等&lt;/li&gt;
&lt;li&gt;做关系型数据库的扩展或插件，如 PGVector&lt;/li&gt;
&lt;li&gt;做 NoSQL 数据库的功能扩展或兼容，如 &lt;code&gt;Elasticsearch&lt;/code&gt;、 &lt;code&gt;Redis&lt;/code&gt;、 &lt;code&gt;ClickHouse&lt;/code&gt; 等&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;太多了，真是太多了，最开始我做选型的时候真是有点儿挑花眼了。最后，一点点缩小范围，最终进入决赛圈的是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Qdrant&lt;/li&gt;
&lt;li&gt;Weaviate&lt;/li&gt;
&lt;li&gt;Milvus&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;你可以通过 &lt;a class="link" href="https://zilliz.com.cn/comparison" target="_blank" rel="noopener"
 &gt;https://zilliz.com.cn/comparison&lt;/a&gt; 来了解各向量数据库之间的对比情况&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-10-11-milvus-shi-zhan-ru-he-yong-yi-ge-shu-ju-ku-ti-sheng-ni-de-ai/003-5681900f.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-10-11-milvus-shi-zhan-ru-he-yong-yi-ge-shu-ju-ku-ti-sheng-ni-de-ai/004-331f1c43.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;最终我选择了 Milvus&lt;/strong&gt; 原因是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;它确实很知名，看了那么多评测，各方面性能都很能打&lt;/li&gt;
&lt;li&gt;我个人觉得比较重要的是它还有数据库管理客户端 &lt;code&gt;attu&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;向量数据库不像我之前使用过的关系型数据库，一般是没有像 &lt;code&gt;Navicat&lt;/code&gt; 、&lt;code&gt;DataGrip&lt;/code&gt; 这样的数据库管理客户端的。一般只有 CRUD 接口或 CLI 客户端。这对于初学者了解和学习向量数据库不太友好，所以我还是特别希望有这样一个有 GUI 图形界面、看得见摸得着的客户端的，而 Milvus 正好是有的。就是 &lt;code&gt;attu&lt;/code&gt; （可以通过 &lt;a class="link" href="https://github.com/zilliztech/attu" target="_blank" rel="noopener"
 &gt;https://github.com/zilliztech/attu&lt;/a&gt; 下载）&lt;/p&gt;
&lt;p&gt;如果你也和我一样在 Qdrant、Weaviate、Milvus 之间纠结的话，可以参考网上一位大哥对它们的评价：&lt;strong&gt;“总结起来就是，Qdrant 开销特别小，Weaviate 支持向量搜索、对象存储和倒排索引的组合，Milvus 性能最强、花活最多。”&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="chroma"&gt;&lt;a href="#chroma" class="header-anchor"&gt;&lt;/a&gt;Chroma
&lt;/h2&gt;&lt;p&gt;LlamaIndex 官方的例子使用的是 Chroma 作为向量数据库进行向量存储。&lt;/p&gt;
&lt;p&gt;默认情况下，Chroma 会将向量数据存储在本地文件系统中。我们就以 Chroma 为例写个例子。&lt;/p&gt;
&lt;p&gt;Chroma 不需要安装外部软件，安装导入相关的库就可了&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;import chromadb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;from llama_index.vector_stores.chroma import ChromaVectorStore
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在导入了 Chroma 相关的库后，我们将 &lt;code&gt;load_or_create_index()&lt;/code&gt; 方法调整一下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_or_create_index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 初始化客户端，设置数据保存路径&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chromadb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PersistentClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./chroma_db&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 创建或获取集合&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;chroma_collection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_or_create_collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;quickstart&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 将 chroma 指定为上下文的 vector_store&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vector_store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ChromaVectorStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chroma_collection&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;chroma_collection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;storage_context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StorageContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_defaults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vector_store&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;vector_store&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 检查集合是否为空&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;chroma_collection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 如果集合为空，加载文档并创建新的索引&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;storage_context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;storage_context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;已创建新的索引&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 如果集合不为空，直接从 vector_store 加载索引&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_vector_store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vector_store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;storage_context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;storage_context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;已加载现有索引&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可以看到也很简单。程序运行后，&lt;code&gt;chroma_db&lt;/code&gt; 文件夹下会自动创建以下文件：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-10-11-milvus-shi-zhan-ru-he-yong-yi-ge-shu-ju-ku-ti-sheng-ni-de-ai/005-79a82529.png"&gt;&lt;/p&gt;
&lt;p&gt;前文中我们提到过 chroma 内置了 &lt;code&gt;SQLite&lt;/code&gt; ，这里就体现出来了。&lt;/p&gt;
&lt;h2 id="milvus"&gt;&lt;a href="#milvus" class="header-anchor"&gt;&lt;/a&gt;Milvus
&lt;/h2&gt;&lt;p&gt;在使用 Milvus 前我们需要先安装它。它有多种安装方式，我本地通过 Docker-Compose 安装&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;3.5&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;etcd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;milvus-etcd&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;quay.io/coreos/etcd:v3.5.14&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;ETCD_AUTO_COMPACTION_MODE=revision&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;ETCD_AUTO_COMPACTION_RETENTION=1000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;ETCD_QUOTA_BACKEND_BYTES=4294967296&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;ETCD_SNAPSHOT_COUNT=50000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;CMD&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;etcdctl&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;endpoint&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;health&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;30s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;20s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;minio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;milvus-minio&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;23&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;minio/minio:RELEASE.2023-03-20T20-16-18Z&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;24&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;25&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MINIO_ACCESS_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;minioadmin&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;26&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MINIO_SECRET_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;minioadmin&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;27&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;28&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;9001:9001&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;29&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;9000:9000&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;30&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;31&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;32&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;minio server /minio_data --console-address &amp;#34;:9001&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;33&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;34&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;CMD&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;curl&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-f&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://localhost:9000/minio/health/live&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;35&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;30s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;36&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;20s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;37&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;38&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;39&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;40&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;milvus-standalone&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;41&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;milvusdb/milvus:v2.3.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;42&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;milvus&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;run&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;standalone&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;43&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;security_opt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;44&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;seccomp:unconfined&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;45&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;46&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MINIO_REGION&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;us-east-1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;47&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ETCD_ENDPOINTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;etcd:2379&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;48&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MINIO_ADDRESS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;minio:9000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;49&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;50&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;51&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;healthcheck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;52&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;CMD&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;curl&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-f&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://localhost:9091/healthz&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;53&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;30s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;54&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;start_period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;90s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;55&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;20s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;56&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;57&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;58&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;19530:19530&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;59&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;9091:9091&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;60&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;61&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;etcd&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;62&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;minio&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;63&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;64&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;65&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;66&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;milvus&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;安装好以后，可以看到它内部有三个容器：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-10-11-milvus-shi-zhan-ru-he-yong-yi-ge-shu-ju-ku-ti-sheng-ni-de-ai/006-b694b4d5.png"&gt;&lt;/p&gt;
&lt;p&gt;接着我们安装 attu，它的安装比较简单，下载相关平台的安装文件安装即可&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-10-11-milvus-shi-zhan-ru-he-yong-yi-ge-shu-ju-ku-ti-sheng-ni-de-ai/007-4bc242b7.png"&gt;&lt;/p&gt;
&lt;p&gt;attu 安装完成后打开进行 Milvus 的连接：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-10-11-milvus-shi-zhan-ru-he-yong-yi-ge-shu-ju-ku-ti-sheng-ni-de-ai/008-1963366f.png"&gt;&lt;/p&gt;
&lt;p&gt;默认地址是 &lt;code&gt;127.0.0.1:19530&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;接着，我们来到程序这里，进行连接和使用，同样，要先导入库&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;from llama_index.vector_stores.milvus import MilvusVectorStore
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后我们调整一下之前的方法，改写一个新的方法来连接 Miluvs:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_or_create_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_create&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; 获取或创建索引
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; overwrite 设置为 False 意味着如果同名的集合已存在，将不会覆盖它。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; dim 是向量维度，必须与 embedding 模型的维度一致。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;vector_store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MilvusVectorStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://localhost:19530&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;overwrite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;collection_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;llamaindex_collection&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_create&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;storage_context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StorageContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_defaults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vector_store&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;vector_store&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleDirectoryReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;storage_context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;storage_context&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;已成功创建并存储新的索引。&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_vector_store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vector_store&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;23&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;24&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我相信如果你阅读了前文，知道这段代码的重要点在哪里。&lt;/p&gt;
&lt;p&gt;当 RAG 应用程序正常运行后，向量数据就被存储到了 Milvus 数据库中：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-10-11-milvus-shi-zhan-ru-he-yong-yi-ge-shu-ju-ku-ti-sheng-ni-de-ai/009-ef9054d1.png"&gt;&lt;/p&gt;
&lt;p&gt;有了 GUI 界面，就比较直观地能感受到向量数据是个什么样子了。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-10-11-milvus-shi-zhan-ru-he-yong-yi-ge-shu-ju-ku-ti-sheng-ni-de-ai/010-fbd533b2.png"&gt;&lt;/p&gt;
&lt;p&gt;有关在 attu 中进行向量数据的查询等操作可以参数相关文档，本文就不多说了。&lt;/p&gt;
&lt;p&gt;使用向量数据库存储以后，我们再次运行查询，速度就很快了，因为第一次运行的时候就已经把文档 embedding 后的向量存储起来了，只需要从 Milvus 中加载查询就可以了，不用再走 http 远程调用。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-10-11-milvus-shi-zhan-ru-he-yong-yi-ge-shu-ju-ku-ti-sheng-ni-de-ai/011-14a85a67.png"&gt;&lt;/p&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;在本文中，我们深入探讨了如何通过 LlamaIndex 整合智谱 AI 的 GLM-4 和 Embedding-3 模型来构建 RAG 应用，并针对 Embedding-3 模型同步调用导致的性能瓶颈问题，提出了有效的解决方案。我们发现，将文档的向量存储起来，可以显著提高检索速度，避免了重复的 HTTP 同步请求，从而节省了成本和时间。&lt;/p&gt;
&lt;p&gt;通过本地文件存储和向量数据库的选型，我们对比了多种向量数据库的特点和性能，最终选择了 Milvus 作为我们的向量数据库。Milvus 以其卓越的性能和易用性脱颖而出，特别是其数据库管理客户端 attu，为初学者提供了友好的图形界面，使得向量数据库的管理和操作变得更加直观和便捷。&lt;/p&gt;
&lt;p&gt;在实际应用中，我们通过 Docker-Compose 安装了 Milvus，并利用 attu 进行了连接和操作。通过将向量数据存储到 Milvus 数据库中，我们显著提高了查询速度，因为文档的向量在第一次运行时就已经被存储起来，后续的查询可以直接从 Milvus 中加载，无需再次进行远程 HTTP 调用。&lt;/p&gt;
&lt;p&gt;此外，我们还探讨了使用 Chroma 作为向量数据库的方案，它内置了 SQLite，简化了安装和使用过程。通过 LlamaIndex 的 API，我们可以轻松地将向量存储到本地文件或 Chroma 数据库中，进一步增强了 RAG 应用的性能和可扩展性。&lt;/p&gt;
&lt;p&gt;总的来说，通过本文的探讨和实践，我们不仅解决了 RAG 应用中的性能问题，还为中大型项目提供了一种高效、可扩展的向量数据存储和管理方案。随着 AI 技术的不断发展，向量数据库在 AIGC 应用架构中的作用将越来越重要，而 Milvus 等向量数据库的选择和应用，将为构建更加智能和高效的 AI 应用提供强有力的支持。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;本文所涉及的完整代码在该项目中：https://github.com/xiaobox/llamaindex_test 大家可按需自取&lt;/em&gt;&lt;/p&gt;</description></item><item><title>RAG 实践- Ollama+MaxKB 部署本地知识库</title><link>https://xiaobox.github.io/p/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/</link><pubDate>Sat, 22 Jun 2024 09:55:14 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/cover.jpg" alt="Featured image of post RAG 实践- Ollama+MaxKB 部署本地知识库" /&gt;&lt;h2 id="前言"&gt;&lt;a href="#%e5%89%8d%e8%a8%80" class="header-anchor"&gt;&lt;/a&gt;前言
&lt;/h2&gt;&lt;p&gt;本文我们介绍另外一种部署本地知识库的方案：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Ollama + MaxKB&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;相对来说，容易安装且功能较完善，30 分钟内即可上线基于本地大模型的知识库问答系统，并嵌入到第三方业务系统中。&lt;/p&gt;
&lt;p&gt;缺点是如果你的电脑配置不高，问题回答响应时间较长。&lt;/p&gt;
&lt;p&gt;下图为 MaxKB 的产品架构：&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/001-08767b01.png"&gt;&lt;/p&gt;
&lt;p&gt;实现原理上，仍然是应用了 RAG 流程：&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/002-4f55ccfd.png"&gt;&lt;/p&gt;
&lt;h2 id="安装-maxkb"&gt;&lt;a href="#%e5%ae%89%e8%a3%85-maxkb" class="header-anchor"&gt;&lt;/a&gt;安装 MaxKB
&lt;/h2&gt;&lt;p&gt;首先我们通过 Docker 安装 MaxKB&lt;/p&gt;
&lt;p&gt;&lt;code&gt;docker run -d --name=maxkb -p 8080:8080 -v ~/.maxkb:/var/lib/postgresql/data cr2.fit2cloud.com/1panel/maxkb &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;注意这里镜像源是 china mainland，走代理的镜像会下载失败。&lt;/p&gt;
&lt;p&gt;安装成功后访问：http://localhost:8080/ 登录，初始账号为：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;用户名: admin 密码: MaxKB@123.. &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;进入系统后是这样的：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/003-01b4122a.png"&gt;&lt;/p&gt;
&lt;h2 id="配置模型"&gt;&lt;a href="#%e9%85%8d%e7%bd%ae%e6%a8%a1%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;配置模型
&lt;/h2&gt;&lt;p&gt;接下来我们进行最重要的模型配置&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/004-5751bc9e.png"&gt;&lt;/p&gt;
&lt;p&gt;可以看到有许多模型的供应商，这里你可以通过 API key 在线去连接大模型&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/005-722d2069.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;API key 不同的模型厂商有不同的申请地址，这种方式不是本文采用的方式，本文我们将把通过 Ollama 本地部署的 Qwen2 大模型配置到 MaxKB&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;所以，第一步我们添加模型选择 Ollama&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/006-00646cce.png"&gt;&lt;/p&gt;
&lt;p&gt;第二步配置模型，在模型添加界面有几个点要注意（下图是修改界面，和添加界面差不多）&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/007-d7ed64f9.png"&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;模型名称和基础模型一定要和你在 &lt;code&gt;ollama list&lt;/code&gt; 中显示的一样，不然可能会导致没有必要的重复下载和连接失败&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/008-ca9df5eb.png"&gt;&lt;/li&gt;
&lt;li&gt;API 域名，因为 MaxKB 是 Docker 部署的，Ollama 是本机部署的，不在一个网络环境，所以要填 ：http://host.docker.internal:11434&lt;/li&gt;
&lt;li&gt;API Key 随便写什么都行&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="创建知识库"&gt;&lt;a href="#%e5%88%9b%e5%bb%ba%e7%9f%a5%e8%af%86%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;创建知识库
&lt;/h2&gt;&lt;p&gt;模型添加完成，就可以创建知识库了。&lt;/p&gt;
&lt;p&gt;这个比较简单，通过界面功能自己就能搞定，我就不多说了&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/009-c0e740af.png"&gt;&lt;/p&gt;
&lt;p&gt;这里比较好的是，MaxKB 支持选择文件夹，这一点 AnythingLLM 就不行，不过一次上传文件数量有限：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/010-1298aa3c.png"&gt;&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;支持格式：TXT、Markdown、PDF、DOCX、HTML 每次最多上传50个文件，每个文件不超过 100MB 若使用【高级分段】建议上传前规范文件的分段标识&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="创建应用"&gt;&lt;a href="#%e5%88%9b%e5%bb%ba%e5%ba%94%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;创建应用
&lt;/h2&gt;&lt;p&gt;知识库创建完，就可以创建应用进行问答了&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/011-c2fb9b46.png"&gt;&lt;/p&gt;
&lt;p&gt;这里注意除了要为应用添加知识库外，还要进行一下参数设置&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/012-3d44b352.png"&gt;&lt;/p&gt;
&lt;p&gt;我选择的是第二项，因为我的知识库数据量较小&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/013-61cbad40.png"&gt;&lt;/p&gt;
&lt;p&gt;设置完成后点击演示&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/014-76e6c2a8.png"&gt;&lt;/p&gt;
&lt;h2 id="问答效果展示"&gt;&lt;a href="#%e9%97%ae%e7%ad%94%e6%95%88%e6%9e%9c%e5%b1%95%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;问答效果展示
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/015-caa129ab.png"&gt;&lt;/p&gt;
&lt;p&gt;这里不太好的是没有同时展示引文，更不用说引文的预览了，实际上这个功能基本上是企业应用上的 &lt;strong&gt;刚需&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="嵌入第三方应用"&gt;&lt;a href="#%e5%b5%8c%e5%85%a5%e7%ac%ac%e4%b8%89%e6%96%b9%e5%ba%94%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;嵌入第三方应用
&lt;/h2&gt;&lt;p&gt;嵌入三方应用的需求也是比较常见的，比如你可以通过 iframe 或者 js 代码的形式嵌入到你现有的系统中，我们经常看到一些网站右下角的浮窗就是这种形式，在 MaxKB 中支持嵌入三方应用，需要在应用的 “概览” 中点击 “嵌入第三方”&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/016-8c062a85.png"&gt;&lt;/p&gt;
&lt;p&gt;剩下的你只需要把代码集成到你的其他应用中就可以了&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/017-f904d255.png"&gt;&lt;/p&gt;
&lt;h2 id="思考"&gt;&lt;a href="#%e6%80%9d%e8%80%83" class="header-anchor"&gt;&lt;/a&gt;思考
&lt;/h2&gt;&lt;p&gt;学习新知识，最好的方式就是直接去应用它，你可能从来都不知道什么是 RAG，但对相关知识有个大概了解后，通过实践，亲自搭建几个可以 run 起来的应用，那些架构里的结构、名词，逐渐全部都能对应得上了。&lt;/p&gt;
&lt;p&gt;我笔记本的配置有限，如果所有的东西都部署在配置有性能强较的显卡的服务器上，那么就可以满足企业级应用的需求了，企业可以直接完成私有化部署并开始应用。&lt;/p&gt;
&lt;h2 id="参考"&gt;&lt;a href="#%e5%8f%82%e8%80%83" class="header-anchor"&gt;&lt;/a&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/1Panel-dev/MaxKB/wiki" target="_blank" rel="noopener"
 &gt;https://github.com/1Panel-dev/MaxKB/wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>如何让 Nacos 支持达梦数据库作为外置数据源</title><link>https://xiaobox.github.io/p/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/</link><pubDate>Thu, 23 Nov 2023 05:08:51 +0000</pubDate><guid>https://xiaobox.github.io/p/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/cover.jpg" alt="Featured image of post 如何让 Nacos 支持达梦数据库作为外置数据源" /&gt;&lt;p&gt;Nacos 支持两种数据持久化方式，一种是利用内置的数据，一种是利用外置的数据源。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;内置数据库支持:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Nacos 默认内置了一些数据存储解决方案，如内嵌的 &lt;code&gt;Derby&lt;/code&gt; 数据库。&lt;/li&gt;
&lt;li&gt;这种内置方式主要用于轻量级或测试环境。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="3"&gt;
&lt;li&gt;外置数据库支持:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;对于生产环境，Nacos 支持外置数据库以提供更高的可靠性和伸缩性。&lt;/li&gt;
&lt;li&gt;常见的外置数据库包括 MySQL 等，这些数据库通过标准的 JDBC 接口与 Nacos 集成。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;然而 达梦数据库 Nacos 原生是不支持的，或者说不能通过简单配置使 Nacos + 达梦数据库这样的组合生效。&lt;/p&gt;
&lt;h3 id="达梦数据库-是什么"&gt;&lt;a href="#%e8%be%be%e6%a2%a6%e6%95%b0%e6%8d%ae%e5%ba%93-%e6%98%af%e4%bb%80%e4%b9%88" class="header-anchor"&gt;&lt;/a&gt;达梦数据库 是什么
&lt;/h3&gt;&lt;p&gt;达梦数据库（DMDB），是一款由中国国内团队自主研发的关系型数据库管理系统（RDBMS）。它旨在提供高性能、高可靠性和高安全性的数据库解决方案，特别是对于在政府、金融、电信等行业的应用。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/001-e47e4976.png"&gt;&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;li&gt;兼容性和易用性：为了更好地适应现有的企业环境，达梦数据库支持广泛的操作系统和平台，并且与主流的编程语言和开发工具具有良好的兼容性。此外，它还提供了易于使用的管理工具和丰富的文档支持。&lt;/li&gt;
&lt;li&gt;应用场景：达梦数据库广泛应用于政府、金融、电信、能源、教育等多个行业，特别是在那些对数据安全性和可靠性有高要求的领域。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="为什么使用达梦数据库"&gt;&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e4%bd%bf%e7%94%a8%e8%be%be%e6%a2%a6%e6%95%b0%e6%8d%ae%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;为什么使用达梦数据库
&lt;/h3&gt;&lt;p&gt;在数据库的选型方面，通常我们会使用业内广泛使用的产品，如开源的 MySQL, 甚至收费的如 Oracle、SQL Server，直到 “信创” 的到来，打破了这些传统产品在数据库市场的垄断地位。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;“信创”这个词最早来源于“信创工委会”。该组织的全称是：信息技术应用创新工作委员会，是在 2016 年，由 24 家专业从事软硬件关键技术研究及应用的国内单位，共同发起成立的一个非营利性社会组织。&lt;/p&gt;
&lt;p&gt;”&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;后来，除了数据安全、网络安全，信创是把之前的一些软硬件等行业放到了一起，重新起了一个名字叫：信息技术应用创新产业，简称“信创”。&lt;/p&gt;
&lt;p&gt;也因此，一般来说，信创包括基础硬件、基础软件、应用软件、信息安全四大板块。其中，基础硬件主要包括：芯片、服务器/PC、存储等；基础软件包括：数据库、操作系统、中间件等；应用软件包括：办公软件、ERP 和其它软件等；信息安全包括硬件安全、软件安全、安全服务等各类产品。&lt;/p&gt;
&lt;p&gt;针对安全可控，我们国家提出的是“2+8”体系。“2”指党、政；“8”指关于国计民生的八大行业：金融、电力、电信、石油、交通、教育、医疗、航空航天。&lt;/p&gt;
&lt;p&gt;发展信创，先在党政等封闭市场进行应用信创产品，打磨产品和生态；接着在产品好用和生态相对成熟之后，进入金融、电力、电信、石油、交通、教育、医疗、航空航天重点行业市场；最后才是将信创产品全面应用到消费市场。&lt;/p&gt;
&lt;p&gt;而数据库就是我们常说的 “信创” 四件套（芯片、操作系统 、数据库、中间件）之一。达梦数据库就是这样一个符合 “国产化” 要求的自主研发的数据库。所以，由于国家信息安全的要求，我们的客户需要符合这些要求，也必然要进行软件的替换。&lt;/p&gt;
&lt;h2 id="实现方案"&gt;&lt;a href="#%e5%ae%9e%e7%8e%b0%e6%96%b9%e6%a1%88" class="header-anchor"&gt;&lt;/a&gt;实现方案
&lt;/h2&gt;&lt;p&gt;首先看一下 Nacos 原生支持的外置数据库有哪些，是否支持达梦？&lt;/p&gt;
&lt;p&gt;根据以下 Nacos 官方文档，无论是单机还是集群模式，貌似只支持 &lt;code&gt;MySQL&lt;/code&gt; 作为外置数据源&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://nacos.io/zh-cn/docs/v2/guide/admin/deployment.html" target="_blank" rel="noopener"
 &gt;https://nacos.io/zh-cn/docs/v2/guide/admin/deployment.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://nacos.io/zh-cn/docs/v2/guide/admin/cluster-mode-quick-start.html" target="_blank" rel="noopener"
 &gt;https://nacos.io/zh-cn/docs/v2/guide/admin/cluster-mode-quick-start.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/002-d112b950.png"&gt;&lt;/p&gt;
&lt;p&gt;只支持 MySQL 吗？不是说还支持其他像 Oracle 之类的数据库吗？&lt;/p&gt;
&lt;p&gt;在调研的过程中，发现 github 上 Nacos 的源码有这样一个功能分支 &lt;code&gt;feature_multiple_datasource_support&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/003-32e47164.png"&gt;&lt;/p&gt;
&lt;p&gt;很明显，它就是用来支持多数据源的，通过源码我们可以看到它支持的多种数据源都有哪些：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/004-2ff5f297.png"&gt;&lt;/p&gt;
&lt;p&gt;这个分支能够支持的外部数据源分别是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;oracle&lt;/li&gt;
&lt;li&gt;mysql&lt;/li&gt;
&lt;li&gt;postgresql&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我分析了 Nacos 1.0 及 2.0 主要版本，发现 多数据源的这个功能并没有被合并到主要的开发及 &lt;code&gt;release&lt;/code&gt; 分支上。也就是说 &lt;code&gt;Nacos&lt;/code&gt; 现有的主要版本的 &lt;code&gt;release&lt;/code&gt; 并没有多数据源的这个功能，外置数据源只兼容 MySQL。&lt;/p&gt;
&lt;p&gt;根据前面的分析我们知道即使是 &lt;code&gt;feature_multiple_datasource_support&lt;/code&gt; 分支也只支持三个数据源，如果想用非 MySQL 的数据源，比如用 Oracle 就需要自己修改和编译源代码。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;mvn -Prelease-nacos -Dmaven.test.skip=true -Dcheckstyle.skip=true clean install -U
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;具体修改的部分也主要是配置文件 &lt;code&gt;application.properties&lt;/code&gt; 没有其他地方了。&lt;/p&gt;
&lt;p&gt;Nacos 是支持 Oracle 和 PostgreSQL 的，只不过需要手动修改配置和编译。虽然这种方法可行，但由于功能分支长时间未更新，最新版本的代码未合并过来，可能会造成一些安全和功能上的问题。更重要的是，通过上述的分析我们知道，Nacos 在原生的模式下，确实是不支持达梦数据库的。&lt;/p&gt;
&lt;h3 id="方案一-修改源代码方式"&gt;&lt;a href="#%e6%96%b9%e6%a1%88%e4%b8%80-%e4%bf%ae%e6%94%b9%e6%ba%90%e4%bb%a3%e7%a0%81%e6%96%b9%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;方案一 修改源代码方式
&lt;/h3&gt;&lt;p&gt;根据前文我们知道，Nacos 原生是不支持达梦数据库的，所以就要想办法让它 “支持”，直觉上因为是开源软件，我们还是会从源码入手。&lt;/p&gt;
&lt;p&gt;既然可以修改源代码，我们就不需要从 &lt;code&gt;feature_multiple_datasource_support&lt;/code&gt; 分支开始了，可以在流行的 1.x 、2.x 或最新版本代码的基本上修改。&lt;/p&gt;
&lt;p&gt;主要涉及到以下内容的修改：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;com/alibaba/nacos/persistence/datasource/ExternalDataSourceProperties.java&lt;/li&gt;
&lt;li&gt;console/src/main/resources/application.properties&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;代码具体的修改方式和内容可以是多样的，下面举几个例子，供参考：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://developer.aliyun.com/article/976299" target="_blank" rel="noopener"
 &gt;https://developer.aliyun.com/article/976299&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.cnblogs.com/hi-gdl/p/nacos-02.html" target="_blank" rel="noopener"
 &gt;https://www.cnblogs.com/hi-gdl/p/nacos-02.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://cloud.tencent.com/developer/article/1912024" target="_blank" rel="noopener"
 &gt;https://cloud.tencent.com/developer/article/1912024&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://codeantenna.com/a/SJdgkqAbZt" target="_blank" rel="noopener"
 &gt;https://codeantenna.com/a/SJdgkqAbZt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;核心思路是：由于达梦数据库良好的支持了 JDBC 驱动，所以我们只需要把 jdbcDriver 进行更换就可以了。然后同样手动进行编译，使用自己编译好的构建物进行部署。&lt;/p&gt;
&lt;p&gt;这里涉及到的 Nacos 数据库初始化脚本可以参考：https://gitee.com/tangjingshan/nacos/blob/tjs-study-fetch-master/distribution/conf/dm-schema.sql&lt;/p&gt;
&lt;p&gt;总结：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;源代码修改方案并不复杂，相对比较简单，但需要做好相关功能的完整测试。&lt;/li&gt;
&lt;li&gt;使用这种方式不但可以支持达梦数据库也可以在同样原理下支持其他国产数据库，如 &lt;code&gt;人大金仓&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;这种方式的问题是由于自行修改了源代码，在进行版本升级时会比较麻烦，每一次升级都要手动合并最新的代码再进行编译，未来甚至有可能出现 Nacos 官方源码进行大规模重构，自行编译的代码无法合并的情况。虽然也有解决办法，但是个麻烦点。&lt;/li&gt;
&lt;li&gt;数据迁移，这个后面我具体再详细说明&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="方案二-多数据源插件"&gt;&lt;a href="#%e6%96%b9%e6%a1%88%e4%ba%8c-%e5%a4%9a%e6%95%b0%e6%8d%ae%e6%ba%90%e6%8f%92%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;方案二 多数据源插件
&lt;/h3&gt;&lt;p&gt;Nacos 从 2.2.0 版本开始，可通过 SPI 机制注入多数据源实现 插件，它的原理是：&lt;/p&gt;
&lt;p&gt;在原来的 Config 模块中，所有的 SQL 操作的执行是通过直接使用 JdbcTemplate 执行固定 SQL 语句的形式，使得 SQL 语句与业务逻辑高度耦合，并且只支持 Derby 与 MySQL 两种数据源，原有 Config 模块架构如下。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/005-83c9e702.png"&gt;&lt;/p&gt;
&lt;p&gt;现在的多数据源插件通过 SPI 机制，将 SQL 操作按照数据表进行抽象出多个 Mapper 接口，Mapper 接口的实现类需要按照不同的数据源编写对应的 SQL 方言实现；现在插件默认提供 Derby 以及 MySQL 的 Mapper 实现，可直接使用；而其他的数据源则需要用户使用数据源插件进行加载，其改造后架构图如下。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/006-5b6348c2.png"&gt;&lt;/p&gt;
&lt;p&gt;我们这里详细描述一下原理&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/007-66cf215c.png"&gt;&lt;/p&gt;
&lt;p&gt;上图是 Nacos 的源码包中 plugin 模块，可以看到在 datasource 包下有不同的数据库实现类。这里其实就是抽象了 Nacos 操作的各个表的 Mapper 接口实现，你可以看到具体的 SQL 语句都在里面。&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/008-696a8914.png"&gt;&lt;/p&gt;
&lt;p&gt;既然有 MySQL、derby 的实现，也可以有我们自己的实现，具体来说就是达梦数据库的实现，我们只需要把这几个类重写就可以了，当然具体重写的内容中的 SQL 要根据达梦数据库的方言情况，修改或者不修改。&lt;/p&gt;
&lt;p&gt;那么是否可以直接在源码的基础上添加 DM 的实现类进行开发呢？&lt;/p&gt;
&lt;p&gt;理论上当然可以，但既然叫插件就有插件的形式。在 Nacos 源码的基础上开发耦合太重了，这不是插件化的表现形式。&lt;/p&gt;
&lt;p&gt;我们要把与多数据源相关的自定义代码专门写一个包，然后在 Nacos 的代码中依赖，这样就解耦了，也与上文 Nacos 插件架构图中的描述相符。&lt;/p&gt;
&lt;p&gt;插件化是如何实现的呢，或者说动态替换实现类是如何实现的？&lt;/p&gt;
&lt;p&gt;这就要利用到 Java 的 SPI 知识了，由于是基础理论这里就不展开讲了。Nacos 在源码中已然利用 SPI 进行数据源 Mapper 的加载了，可以参考下图：&lt;/p&gt;
&lt;p&gt;源码位置：com.alibaba.nacos.plugin.datasource.MapperManager#loadInitial&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/009-cfaeb6e1.png"&gt;&lt;/p&gt;
&lt;p&gt;我们可以看到，源码是利用 ServiceLoader 加载插件包，而这些实现类也写在 &lt;code&gt;plugin/datasource/src/main/resources/META-INF/services/com.alibaba.nacos.plugin.datasource.mapper.Mapper&lt;/code&gt; 这个文件里&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/010-d4851c25.png"&gt;&lt;/p&gt;
&lt;p&gt;那么如果我们也利用 SPI 配置好 DM 的实现类，然后根据数据源参数找到相应的实现类是不是就可以了？&lt;/p&gt;
&lt;p&gt;是的，所以源码中也正是这么做的&lt;/p&gt;
&lt;p&gt;源码位置：com.alibaba.nacos.plugin.datasource.MapperManager#findMapper&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/011-0eb5b472.png"&gt;&lt;/p&gt;
&lt;p&gt;这里我们讲一下具体的实现方法：&lt;/p&gt;
&lt;p&gt;1 初始化达梦数据库，具体脚本可以参考 ：https://github.com/nacos-group/nacos-plugin/blob/develop/nacos-datasource-plugin-ext/nacos-dm-datasource-plugin-ext/src/main/resources/schema/nacos-dm.sql&lt;/p&gt;
&lt;p&gt;2 编写插件包，利用 SPI 的原理，自定义实现各个表的 Mapper 实现类，这里其实 Nacos 的社区 nacos-group 中已经有现成的实现了，可以参考他们的项目和代码，实际上的代码都比较简单，甚至不需要做什么改动，因为基本的 SQL 达梦都是兼容的。&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/012-b5df1816.png"&gt;&lt;/p&gt;
&lt;p&gt;3 插件引入，有两种方式&lt;/p&gt;
&lt;p&gt;第一种：&lt;/p&gt;
&lt;p&gt;直接用 nacos-group 的现成的实现包，然后用 maven 进行依赖就可以了，例如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;dependency&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;groupId&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;com.alibaba.nacos&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;groupId&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;artifactId&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;nacos-dm-datasource-plugin-ext&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;artifactId&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;1.0.0-SNAPSHOT&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;dependency&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;第二种：&lt;/p&gt;
&lt;p&gt;将插件源码打包为 jar 包，将该文件的路径配置到 &lt;code&gt;startup.sh&lt;/code&gt; 文件中，使用 Nacos 的 &lt;code&gt;loader.path&lt;/code&gt;机制指定该插件的路径，可修改 &lt;code&gt;startup.sh&lt;/code&gt; 中的 &lt;code&gt;loader.path&lt;/code&gt; 参数的位置进行指定。&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/013-92ff4969.png"&gt;&lt;/p&gt;
&lt;p&gt;启动脚本会指定插件包位置为：&lt;code&gt;-Dloader.path=${BASE_DIR}/plugins&lt;/code&gt; loader.path 机制为打包插件 spring-boot-maven-plugin 提供的，该机制下实际启动类会变成&lt;code&gt;org.springframework.boot.loader.PropertiesLauncher#main&lt;/code&gt;，且类会由&lt;code&gt;org.springframework.boot.loader.LaunchedURLClassLoader&lt;/code&gt;这个类加载器加载&lt;/p&gt;
&lt;p&gt;4 修改数据库配置文件，在 application.properties 文件中声明 dameng 的配置信息：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;spring.datasource.platform=dm
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt; db.url.0=jdbc:dm://127.0.0.1:5236/DMSERVER?schema=NACOS&amp;amp;compatibleMode=mysql&amp;amp;ignoreCase=true&amp;amp;ENCODING=utf-8
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; db.user.0=SYSDBA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; db.password.0=SYSDBA
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; db.pool.config.driverClassName=dm.jdbc.driver.DmDriver 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;5 如果用 maven 依赖的方式引入了插件包，就需要源码重新编译，如果使用 loader.path 指定路径的方式就可以重启进行测试了&lt;/p&gt;
&lt;h3 id="数据迁移"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e8%bf%81%e7%a7%bb" class="header-anchor"&gt;&lt;/a&gt;数据迁移
&lt;/h3&gt;&lt;p&gt;无论使用哪种解决方案很大可能性都需要进行数据迁移，即将旧的非 达梦数据库的数据迁移到达梦数据库。&lt;/p&gt;
&lt;p&gt;我们要把 &lt;code&gt;Nacos&lt;/code&gt; 的数据或者 &lt;code&gt;SQL&lt;/code&gt; 语句迁移到达梦数据库。借助 &lt;code&gt;DM 数据迁移工具&lt;/code&gt; ，完成 &lt;code&gt;Nacos&lt;/code&gt; 配置数据表迁移到达梦数据库。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2023-11-23-ru-he-rang-nacos-zhi-chi-da-meng-shu-ju-ku-zuo-wei-wai-zhi-s/014-4780c6a9.png"&gt;&lt;/p&gt;</description></item></channel></rss>