<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>数据库 on Zampo Blog</title><link>https://blog.cpdd.fyi/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/</link><description>Recent content in 数据库 on Zampo Blog</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Fri, 17 Apr 2026 20:00:00 +0800</lastBuildDate><atom:link href="https://blog.cpdd.fyi/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/index.xml" rel="self" type="application/rss+xml"/><item><title>我用 PostgreSQL 替换了整个技术栈，省了 6 个微服务</title><link>https://blog.cpdd.fyi/posts/replaced-entire-stack-with-postgresql/</link><pubDate>Fri, 17 Apr 2026 20:00:00 +0800</pubDate><guid>https://blog.cpdd.fyi/posts/replaced-entire-stack-with-postgresql/</guid><description>&lt;p&gt;现代软件工程已经基本变成了&amp;quot;订阅管理模拟器&amp;quot;。&lt;/p&gt;
&lt;p&gt;我们被云厂商洗脑了，以为即使构建一个基础应用，也需要拼凑一个脆弱的分布式网络：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Redis 做缓存&lt;/li&gt;
&lt;li&gt;Confluent Kafka 集群做后台任务&lt;/li&gt;
&lt;li&gt;Elasticsearch 只是为了一个简单的搜索框&lt;/li&gt;
&lt;li&gt;再搞个专用向量数据库为了那个临时加上的 AI 功能&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;等你终于把应用部署给你那&amp;quot;要求极高&amp;quot;的用户群（你自己和你妈）时，你已经欠了十几家 Y Combinator 支持的 SaaS 初创公司的钱，就为了让灯亮着。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这是一个过度工程化、价格离谱的陷阱。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;但如果我告诉你，你可以把那些闪亮的云依赖全部扔进焚化炉，用一个经过 30 年验证的开源软件替换它们呢？&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;科技行业不想让你知道的秘密：一个久经考验的工具可以吞噬你的整个架构。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我刚刚用 PostgreSQL 替换了整个技术栈。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一postgresql-为什么能吞噬整个栈"&gt;一、PostgreSQL 为什么能吞噬整个栈&lt;/h2&gt;
&lt;p&gt;PostgreSQL 是一个开源对象关系数据库系统，已经活跃开发了 30 多年。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;开箱即用的能力：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;坚如磐石的 ACID 合规性——当你的廉价云服务器崩溃时，用户数据不会损坏&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可扩展性&lt;/strong&gt;——这才是它能吞噬整个栈的真正原因&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;PostgreSQL 不只是行列存储。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;它还能存储：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JSONB（半结构化数据）&lt;/li&gt;
&lt;li&gt;向量（AI 嵌入）&lt;/li&gt;
&lt;li&gt;全文搜索索引&lt;/li&gt;
&lt;li&gt;地理空间数据（PostGIS）&lt;/li&gt;
&lt;li&gt;图数据（关系遍历）&lt;/li&gt;
&lt;li&gt;时间序列数据&lt;/li&gt;
&lt;li&gt;键值对（作为 Redis 替代）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;PostgreSQL 不是数据库，是一个数据平台。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="二实战替换redis缓存--键值存储"&gt;二、实战替换：Redis（缓存 + 键值存储）&lt;/h2&gt;
&lt;h3 id="传统架构"&gt;传统架构&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;应用 → Redis（缓存） → PostgreSQL（持久化）
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;问题：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;两个服务要运维&lt;/li&gt;
&lt;li&gt;缓存和数据库数据可能不一致&lt;/li&gt;
&lt;li&gt;Redis 挂了要处理降级&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="postgresql-方案"&gt;PostgreSQL 方案&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;使用 UNLOGGED 表做高速缓存：&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>你以为自己会用 PostgreSQL，其实你只是会写 SQL</title><link>https://blog.cpdd.fyi/posts/postgresql-system-thinking/</link><pubDate>Mon, 13 Apr 2026 17:18:00 +0800</pubDate><guid>https://blog.cpdd.fyi/posts/postgresql-system-thinking/</guid><description>&lt;p&gt;很多开发者天天在用 PostgreSQL，但只要你追问三个问题，场面就会立刻安静下来：它为什么并发强？为什么崩了还能恢复？为什么 JSONB、大文本这些大字段没把系统拖死？&lt;/p&gt;
&lt;p&gt;如果这些问题你平时很少认真想过，那你多半还停留在“会用 PostgreSQL”的表层。说得再狠一点：很多人其实不是理解 PostgreSQL，只是会写 SQL。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.cpdd.fyi/images/postgresql-system-thinking/cover.svg" alt="PostgreSQL 从表层使用到系统思维的认知升级封面图"&gt;&lt;/p&gt;</description></item><item><title>PostgreSQL 入门：为什么说它能装下世间万物？</title><link>https://blog.cpdd.fyi/posts/postgresql-intro-why-it-can-store-everything/</link><pubDate>Tue, 07 Apr 2026 12:16:00 +0800</pubDate><guid>https://blog.cpdd.fyi/posts/postgresql-intro-why-it-can-store-everything/</guid><description>&lt;p&gt;这是世界上最先进的开源关系型数据库。&lt;/p&gt;
&lt;p&gt;PostgreSQL 的能力早已超越了传统关系型数据库的范围。现代开发中，为了解决各种问题，各类花哨的工具层出不穷——缓存用 Redis、全文检索用 Elasticsearch、文档存储用 MongoDB、向量数据库用专门的方案、定时任务跑在 K8s 上。&lt;/p&gt;
&lt;p&gt;但有时候，仅仅一个 PostgreSQL，就能覆盖大部分后端开发需求。&lt;/p&gt;</description></item><item><title>为什么数据库的挑战者们都没好下场</title><link>https://blog.cpdd.fyi/posts/why-rdb-challengers-always-fail/</link><pubDate>Thu, 02 Apr 2026 21:30:00 +0800</pubDate><guid>https://blog.cpdd.fyi/posts/why-rdb-challengers-always-fail/</guid><description>&lt;p&gt;1974 年，IBM 捣鼓出了世界上第一个关系数据库。&lt;/p&gt;
&lt;p&gt;50 年过去了，Oracle、MySQL、PostgreSQL 这些 RDB 依然霸榜。年轻程序员嘴上喊着 &amp;ldquo;SQL 太土&amp;rdquo;，项目里该用还是用。&lt;/p&gt;
&lt;p&gt;有意思的是，每隔几年就冒出一堆&amp;quot;未来数据库&amp;quot;来挑战 RDB 的地位：Key-Value Store、MapReduce、Hadoop、图数据库、向量数据库……&lt;/p&gt;
&lt;p&gt;我都用过。所以我知道为什么它们最后都凉了。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="redis我踩过最贵的坑"&gt;Redis：我踩过最贵的坑&lt;/h2&gt;
&lt;p&gt;Redis 是 KVS 的典型代表，用 Key 找 Value，简单粗暴。&lt;/p&gt;
&lt;p&gt;缓存用它，完美。问题是做开发的总有点执念，非要把缓存以外的事情也塞给它。&lt;/p&gt;
&lt;p&gt;我当年做物联网项目就载过这个跟头。&lt;/p&gt;
&lt;p&gt;当时选 Redis 考虑两个因素：一是物联网系统里大部分是文件，数据库只管组件状态；二是终端用 SD 卡，磁盘 IO 寿命短，想省着用。&lt;/p&gt;
&lt;p&gt;结果第三个月就开始出问题了。&lt;/p&gt;
&lt;p&gt;物联网环境里，网络和电源都不可靠，随时可能断电断网。每一个组件的状态管理变得极其复杂——在 Redis 上，你要用 Array、Set、HashMap 来描述一个简单的&amp;quot;任务运行状态&amp;quot;，换成 SQLite 的话，一个表加几条 SQL 就搞定了。&lt;/p&gt;
&lt;p&gt;最后项目里一半以上的 Bug 都跟这个定制 Redis 数据结构有关。就在写这篇文章的时候，我们还在修一个诡异的 Bug：终端下载视频时遇到网络问题，紧接着又断电，Redis 里的任务信息不完整，视频永远下不下来。&lt;/p&gt;
&lt;p&gt;你说这值不值？&lt;/p&gt;
&lt;p&gt;为了省 SD 卡那点读写寿命，被折腾了好几年。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一个 KVS 是 AT&amp;amp;T 在 1979 年发布的，叫 DBM。发明者？又是那个男人。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="hadoop我学了个寂寞"&gt;Hadoop：我学了个寂寞&lt;/h2&gt;
&lt;p&gt;MapReduce 不是数据库，是 Google 提出的一种分布式数据处理思路。&lt;/p&gt;
&lt;p&gt;Map 对应 SQL 里的 WHERE + ORDER BY，Reduce 对应 GROUP BY。说白了就是把 SQL 的逻辑拆到多台服务器上跑。&lt;/p&gt;</description></item><item><title>为什么 PostgreSQL 能超越 MySQL？这是我见过最全面的对比</title><link>https://blog.cpdd.fyi/posts/why-postgresql-beats-mysql/</link><pubDate>Thu, 02 Apr 2026 15:47:00 +0800</pubDate><guid>https://blog.cpdd.fyi/posts/why-postgresql-beats-mysql/</guid><description>&lt;p&gt;用了 MySQL 好几年，最近深入研究 PostgreSQL，才发现自己一直在将就。&lt;/p&gt;
&lt;p&gt;不是 MySQL 不好，而是 PostgreSQL 在太多地方更胜一筹。这篇文章从四个维度把它说清楚：&lt;strong&gt;索引、数据一致性、性能、扩展性&lt;/strong&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一索引postgresql-的玩法更多"&gt;一、索引：PostgreSQL 的玩法更多&lt;/h2&gt;
&lt;p&gt;两者的基础索引都是 B+ 树，但 PostgreSQL 的花样也太多了。&lt;/p&gt;
&lt;h3 id="聚簇-vs-非聚簇"&gt;聚簇 vs 非聚簇&lt;/h3&gt;
&lt;p&gt;MySQL（InnoDB）是&lt;strong&gt;聚簇索引&lt;/strong&gt;：数据按主键顺序存在叶子节点上，查主键很快，但非主键字段要先查二级索引再回表查一遍。&lt;/p&gt;
&lt;p&gt;PostgreSQL 的所有索引都是&lt;strong&gt;非聚簇索引&lt;/strong&gt;：数据单独存放在堆表里，索引只存指针。主键和普通索引没区别，插入数据直接追加到末尾，不用担心页分裂。&lt;/p&gt;
&lt;h3 id="gin-索引倒排索引"&gt;GIN 索引：倒排索引&lt;/h3&gt;
&lt;p&gt;PostgreSQL 的 GIN 索引简直是 JSON 数据的克星：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INDEX&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;idx_attr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;USING&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attributes&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="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;{&amp;#34;color&amp;#34;: &amp;#34;red&amp;#34;}&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;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;一句 &lt;code&gt;@&amp;gt;&lt;/code&gt; 操作符就能查包含特定键值对的记录。&lt;strong&gt;MySQL 根本不支持。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="gist-索引什么都能索引"&gt;GiST 索引：什么都能索引&lt;/h3&gt;
&lt;p&gt;GiST 是一个索引框架，任何数据类型实现了接口就能用。&lt;/p&gt;
&lt;p&gt;地理坐标、时间范围、IP 区间……这些用 PostgreSQL 原生的 &lt;code&gt;daterange&lt;/code&gt; 加上 GiST 索引，查询重叠和距离效率极高。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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="cl"&gt;&lt;span class="k"&gt;SELECT&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="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;reservations&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;daterange&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;[2026-01-08,2026-01-13]&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2026-01-10&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;date&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;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;MySQL 也不行。&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>