1 分钟

迈克尔·斯通布雷克与现代数据库:他改变了什么

探索迈克尔·斯通布雷克在 Ingres、Postgres 和 Vertica 背后的关键思想——以及它们如何塑造了 SQL 数据库、分析引擎和今天的数据架构。

迈克尔·斯通布雷克与现代数据库:他改变了什么

为什么斯通布雷克的工作仍然出现在你的数据栈中

迈克尔·斯通布雷克是一位计算机科学家,他的项目不仅影响了数据库研究——还直接塑造了许多团队每天依赖的产品和设计模式。如果你使用过关系数据库、分析仓库或流处理系统,你就受益于他帮助验证、构建或推广的理念。

你从这篇文章会得到什么

这不是传记,也不是学术性的数据库理论导览。它把斯通布雷克的主要系统(如 Ingres、Postgres 和 Vertica)与现代数据栈中的选择串联起来:

  • 为什么 SQL 成为数据工作的通用语言
  • 为什么分析引擎在外观和行为上与 OLTP 数据库不同
  • 为什么“一个数据库解决一切”在实践中常常失败
  • 架构选择如何影响成本、性能与可靠性

“现代数据库”是什么意思(通俗解释)

现代数据库是任何能可靠地实现以下目标的系统:

  • 安全地存储数据(防止丢失)
  • 快速查询数据(帮助团队回答问题)
  • 可伸缩以应对数据量和用户增长(不崩溃)
  • 在并发下保持正确性(结果和现实一致)

不同数据库以不同方式在这些目标间进行权衡——尤其是在事务应用、BI 仪表盘和实时流水线之间比较时。

本文的承诺

我们聚焦于实际影响:那些出现在今天“仓库 + 湖 + 流 + 微服务”世界中的思想,以及它们如何影响你购买、构建和运营。期待清晰的解释、权衡以及现实可见的影响,而非深入证明或实现细节。

他的重要数据库里程碑简短时间线

斯通布雷克的职业生涯最好理解为一系列为特定任务构建的系统,然后最佳想法迁移到主流数据库产品中。

1970 年代:Ingres —— 让关系数据库可用

Ingres 起初是一个学术项目,证明关系数据库不仅是优雅的理论,而且可以快速且实用。它推动了近似 SQL 的查询方式和基于代价的优化思维的普及,这些后来成为商业引擎的常态。

1980–1990 年代:Postgres —— 可扩展性与“让数据库演进”

Postgres(导致 PostgreSQL 的研究系统)做出不同的赌注:数据库不应是固定功能的。你应该能够添加新数据类型、新索引方法和更丰富的行为,而无需重写整个引擎。

许多“现代”功能可追溯到这一时期:可扩展类型、用户定义函数,以及能随工作负载变化而适配的数据库。

2000 年代:列存与分析优先设计

随着分析需求增长,面向行的系统在大规模扫描和聚合上遇到瓶颈。斯通布雷克推动了列式存储和相关执行技术,目标是只读取查询需要的列并高效压缩——这些今天已成为分析数据库和云仓库的标配。

2000 年代中期:Vertica —— 成为产品的 MPP 分析

Vertica 将列存研究思想带入商业化可行的**大规模并行处理(MPP)**SQL 引擎,专为大型分析查询设计。这个模式在行业中重复上演:研究原型验证概念;产品使其在可靠性、工具与真实客户约束下成熟。

2010 年代及以后:流处理与“对的工具干对的事”

后续工作扩展到流处理和针对工作负载的专用引擎——主张一个通用数据库很少能在所有场景下胜出。

原型与产品的区别(为什么重要)

原型用于快速测试假设;产品必须优先考虑可操作性:升级、监控、安全、可预测性能与支持。斯通布雷克的影响之所以明显,是因为许多原型想法进入了商业数据库,成为默认能力而非小众选项。

Ingres:让关系数据库变得实用

Ingres(INteractive Graphics REtrieval System)是斯通布雷克早期的证据,证明关系模型可以超越理论。那时许多系统围绕定制访问方法和特定应用数据路径构建。

Ingres 要解决一个业务友好的问题:

如何让人们在不每次重写软件的情况下,对数据提出灵活的问题?

Ingres 试图修复的问题

关系数据库承诺你可以描述 你要什么(例如“加州逾期账单的客户”),而不是 如何一步步去取。但要让这个承诺成为现实,需要一个能:

  • 在表中可靠存储数据
  • 接受接近 SQL 的高级查询语言
  • 自动将查询转换为高效计划的系统

Ingres 是实现“实用”关系计算的重要一步——在当时的硬件上仍能保持响应性。

SQL 的普及与查询优化基础的诞生

Ingres 推广了数据库应该承担查询规划这项艰难工作这一想法。开发者不用为每个数据访问路径手动调优,系统可以选择读取哪张表、使用哪个索引以及如何连接表。

这有利于 SQL 思维的传播:当你可以写声明式查询时,迭代更快,更多人能直接提问——分析师、产品团队,甚至财务——不用再等定制报表。

为什么基于代价的优化重要

关键的实用洞见是基于代价的优化:根据数据统计信息,从预计“代价”(通常是 I/O、CPU 和内存的组合)最低的计划中选择。

这很重要,因为它通常意味着:

  • 更快的查询而无需更改应用
  • 减少硬件来达成相同性能目标
  • 随着数据增长性能更可预测

Ingres 并未发明现代优化的每一部分,但它帮助确立了模式:SQL + 优化器使关系系统从“好主意”变为日常工具。

Postgres:可扩展数据库的核心思想

早期关系数据库通常假定一组固定的数据类型(数字、文本、日期)和一组固定的操作(过滤、连接、聚合)。这在很多场景下有效——直到团队开始存储新类型的信息(地理、日志、时序、领域专用标识)或需要专用性能特性。

在僵化设计下,每个新需求都会演变为糟糕选择:把数据强行塞进文本、接入独立系统,或等待厂商新增支持。

用非术语化语言解释可扩展性

Postgres 提出了不同的观点:数据库应当是可扩展的——意思是你可以以受控方式添加新能力,而不会破坏你从 SQL 期待的安全性与正确性。

通俗地说,可扩展性像是给电动工具添加经过认证的附件,而不是自己重接电机。你可以教数据库“新技能”,同时保持事务、权限和查询优化作为一个连贯整体工作。

这如何影响现代扩展生态

这种思路在今天的 PostgreSQL 生态(以及许多受其启发的系统)中非常明显。团队可以采用经过验证的扩展,这些扩展能与 SQL 和运维工具链良好集成,而不用等核心功能加入。

常见高层示例包括:

  • 自定义数据类型: 将更丰富的值(例如地理点、区间或类 JSON 结构)作为一等公民存储
  • 自定义函数: 将领域逻辑直接作为查询和报表的一部分
  • 索引选项: 为不同访问模式选择不同索引,从而让相同的 SQL 查询运行得更快

关键在于:Postgres 把“改变数据库能力”当作设计目标,而非事后补救,这一思想仍在影响现代数据平台的演进。

事务与并发:在规模下得到正确结果

数据库不仅用于存储信息——更重要的是在许多操作同时发生时确保信息保持正确。这就是事务与并发控制的作用,也是 SQL 系统被信任用于实际业务的主要原因之一。

事务真正保证了什么

事务是一组必须全部成功或全部失败的变更。

如果你在账户间转账、下订单或更新库存,不可能出现“半成品”结果。事务确保不会出现既扣了客户钱但未保留库存,或减少了库存但没有记录订单这样的情况。

实务上,事务带来:

  • 可向人解释的一致性: 数据库不会“有点儿”应用变更
  • 可恢复性: 如果在更新中崩溃,系统可以回滚到安全状态

并发:数据库必须处理的现实混乱

并发意味着许多人(和应用)同时读取和更改数据:客户结账、客服编辑账户、后台任务更新状态、分析师运行报表。

如果没有严谨规则,并发会引发问题,如:

  • 更新丢失: 两个人修改同一记录时,一个覆盖另一个
  • 脏读: 某人看到后来会回滚的数据
  • 不一致的报表: 查询看到“前后”混杂的状态

用通俗话说的 MVCC

一种有影响力的方法是 MVCC(多版本并发控制)。概念上,MVCC 在短时间内保留行的多个版本,使读取者在写入发生时仍能看到稳定的快照。

最大好处是 读取不会那么频繁阻塞写入,写入也不会因长时间运行的查询而频繁等待。你仍能保证正确性,但等待更少。

这在现代 SQL 工作负载中的意义

今天的数据库常常服务于混合负载:高并发的应用写入加上频繁的仪表盘读取、客户视图和运维分析。现代 SQL 系统依赖诸如 MVCC、更智能的锁和隔离级别等技术,在速度与正确性间取得平衡——以便在不牺牲数据可信度的前提下扩展业务活动。

列式存储:分析性能的转折点

告别零散查询
构建轻量管理面板,减少团队的一次性 SQL 请求。

面向行的数据库为事务处理而建:许多小的读写操作,通常只涉及一条客户记录或一条订单记录。这种设计在需要快速获取或更新整条记录时非常合适。

行与列(一个日常类比)

把它想成电子表格。行存像是把每一行装入一个文件夹:当你需要“订单 #123 的所有信息”时,拿出一个文件夹就行。列存像是按列存放:一个抽屉放“order_total”,另一个放“order_date”,再一个放“customer_region”。

对分析来说,你很少需要整条文件夹——通常在问“上季度按地区的总收入是多少?”这类只涉及少数字段却跨越百万条记录的问题。

为什么分析负载喜欢列式

分析查询通常:

  • 扫描表的大部分数据
  • 只使用少数列
  • 大量聚合(SUM/AVG/COUNT)和过滤

在列式存储中,引擎可以只读取查询中引用的列,跳过其余列。减少从磁盘读取的数据(以及在内存中移动的数据)通常是最大的性能收益。

压缩不仅仅是为了省空间

列通常有重复值(区域、状态、类别),因此非常适合压缩——压缩加速分析,因为系统读取更少字节,并且有时能在压缩状态下直接操作数据更高效。

更大的转变

列式存储标志着从以 OLTP 为优先的数据库向分析优先引擎的转变,在那里扫描、压缩和快速聚合成为首要设计目标,而不是事后补充。

Vertica 与 MPP 分析:为大查询扩展 SQL

Vertica 是斯通布雷克如何把分析数据库思想转为可在生产中运行的产品的最清晰实例之一。它将列式存储的教训与分布式设计结合,解决特定问题:即便数据量超出单机,仍能快速回答大型分析 SQL 查询。

用通俗话解释 MPP

MPP(大规模并行处理)最简单的理解是:许多机器同时处理一个 SQL 查询。

不是一个数据库服务器读取所有数据并做所有分组与排序,而是把数据分片到节点上。每个节点并行处理自己的切片,系统再把部分结果合并为最终答案。

这就是为什么在数据分布合理且查询可并行化的情况下,本来需要单机几分钟的查询,通过集群可以降到几秒钟。

实践中的能力

类似 Vertica 的 MPP 分析系统在你需要扫描大量行并高效过滤与聚合时表现出色。典型用例包括:

  • 仪表盘读取大型事实表(产品分析、营销表现、运营指标)
  • 定时报表与交互式 SQL 探索
  • 大规模聚合(日常队列、漏斗、按多维度汇总)

相对于事务数据库的权衡

MPP 分析引擎不是事务(OLTP)系统的直接替代。它们为读取大量行计算汇总而优化,而不是处理许多小更新。

常见权衡包括:

  • 新鲜度: 数据通常以批次或微批方式到达,而不是逐行实时
  • 更新: 频繁的单行更新/删除通常更慢或更复杂
  • 延迟: 适合秒到分钟级的分析查询;不是毫秒级用户交互的理想选择

要点是专注:Vertica 等系统通过针对分析调优存储、压缩与并行执行来换取速度,同时接受事务系统避免的某些限制。

使分析更快的查询执行创新

一个数据库能“存储并查询”数据但仍然在分析上显得缓慢。区别往往不在你写的 SQL,而在引擎如何执行它:如何读取页面、在 CPU 内移动数据、使用内存以及最小化多余工作。

斯通布雷克面向分析的项目推动了这样一种思想:查询性能既是存储问题也是执行问题。这促使团队从优化单行查找转向优化对数百万(或十亿)行的长扫描、连接与聚合。

向量化执行(按批处理,而不是逐行)

许多旧引擎按“元组逐条”处理查询,导致大量函数调用与开销。向量化执行反转了这个模型:引擎在紧凑循环中处理一批(向量)值。

通俗地说,就像用购物车搬运杂货而不是每次只拿一件。批处理减少了开销,并让现代 CPU 更好地发挥:可预测循环、更少分支、更高缓存利用率。

面向内存的分析设计

快速的分析引擎强调保持 CPU 与缓存效率。执行创新通常关注:

  • 避免不必要的物化(如果可以流式推进则不生成大中间表)
  • 尽可能在压缩数据上工作(减少内存带宽、移动更少字节)
  • 把热数据保持在缓存中(布局与批处理符合 CPU 实际访问模式)

这些思想重要,因为分析查询往往受限于内存带宽与缓存未命中,而不是磁盘速度本身。

今天你在哪里看到这些

现代数据仓库与 SQL 引擎——云仓库、MPP 系统以及快速的进程内分析工具——常把向量化执行、面向压缩的运算符和缓存友好流水线作为常见做法。

即便厂商宣传“自动扩缩”或“存储与计算分离”,你日常感受到的速度仍在很大程度上取决于这些执行选择。

如果你在评估平台,请不仅问“他们存啥”,还要问“他们如何执行连接与聚合”以及其执行模型是否为分析而非事务构建。

流处理系统:从批思维到实时数据

先规划再构建
在使用 Planning Mode 生成功能代码前,先规划工作负载、端点和数据表。

流数据是持续到达的事件序列——比如刷卡记录、传感器读数、页面点击、包裹扫描或日志行:每一条都是实时发生并持续不断的。

为什么批数据库对实时工作感觉慢

传统数据库与批处理流水线适用于可以等待的场景:加载昨天数据、跑报表、发布仪表盘。但实时需求不会等下一个小时级作业。

如果只用批处理,你常会遇到:

  • 指标滞后(数字落后于实际)
  • 告警延迟(问题发生后才发现)
  • 不优雅的变通方案(轮询表、不断重跑查询)

流处理系统围绕计算能在事件到达时持续运行的思想设计。

核心思想:持续查询和窗口

持续查询像是从不“结束”的 SQL 查询。它不是一次返回结果,而是随着新事件到达不断更新结果。

由于流是无界的(不会结束),流系统使用窗口来让计算可管理。窗口可以是时间切片或事件切片,例如“最近 5 分钟”、“每分钟”或“最近 1000 条事件”。这让你能计算滚动计数、平均值或 top-N,而无需重跑全部历史。

立即受益的业务示例

实时流最有价值的场景是时间敏感的:

  • 欺诈检测:在几秒内标记异常消费
  • 运营告警:检测错误暴增并即时响应
  • 实时产品指标:立即看到注册、转化或库存变化
  • 物流可视化:从持续扫描更新预计到达时间

以工作负载驱动的架构:为任务选对引擎

斯通布雷克几十年来主张:数据库不该被做成通用的“万金油”机器。原因很简单:不同工作负载奖励不同的设计选择。若你为某项工作极度优化(比如小事务更新),通常会让另一个工作变慢(比如对数十亿行做报表扫描)。

为什么团队会有多个系统

大多数现代栈使用不止一个数据系统,因为业务需要多类答案:

  • OLTP 数据库(应用数据库): 快速插入/更新、严格正确性、大量并发用户
  • 仓库/分析库: 在大量数据上快速读取、重度聚合、长扫描
  • 缓存/键值存储: 对“热点”数据(会话、计数器、特性开关)提供极快读取
  • 流式处理 + 日志: 处理连续事件(点击、支付、IoT),低延迟流水线,实时指标

这就是“一个尺码不适合所有”在实践中的体现:按任务形态选择引擎。

简单决策指南

选用(或为另一个系统辩护)时,使用这个快速过滤器:

  • 若需要大量小的读/写并含事务(订单、用户资料):从 OLTP 数据库开始。\n- 若需要大查询和聚合(周度收入、队列分析):加入分析仓库。\n- 若需要子秒级重复查找响应:引入缓存。\n- 若需要对事件的实时反应(欺诈规则、实时仪表盘):加入流处理。

避免工具泛滥

多个引擎是健康的,但前提是每个引擎有明确的工作负载。新工具应通过降低成本、延迟或风险来“赚取”其存在价值,而不是追求新奇。

偏好有强运维负责的更少系统,并退役那些没有清晰可测目的的组件。

这些思想如何出现在现代数据架构中

拥有源代码
准备接管堆栈时,通过导出源代码保持控制权。

斯通布雷克的研究线索——关系基础、可扩展性、列式存储、MPP 执行与“为任务选对工具”——在现代数据平台的默认形态中随处可见。

常见架构模式(以及它们为何如此)

仓库反映了数十年的 SQL 优化、列式存储和并行执行工作。当你在巨大表上看到快速仪表盘时,通常是在看到列式格式加上向量化处理和 MPP 风格的扩展。

**湖仓(lakehouse)**借用了仓库的思想(模式、统计、缓存、基于代价的优化),但构建在开放文件格式与对象存储上。“存储便宜、计算弹性”是新变化;其下的查询与事务思考并非新事物。

MPP 分析系统(共享无状态集群)是研究证明:通过分区数据、把计算移动到数据并在连接与聚合中谨慎管理数据移动,你可以扩展 SQL。

SQL 今天的角色

SQL 已成为仓库、MPP 引擎乃至“湖”查询层面的通用接口。团队将其用作:

  • BI 工具与分析师的稳定契约
  • 引擎变更时的可移植层
  • 治理的表面(视图、权限、审计访问)

即便执行发生在不同引擎(批、交互式、流),SQL 常常仍是面向用户的语言。

数据建模与治理:模式仍然重要

灵活存储并不消除结构化的必要性。清晰的模式、文档化的含义和受控的演进能减少下游破坏。

良好治理更像是让数据可靠的工程实践:一致定义、归属、质量检查与访问控制,而非繁文缛节。

一个无噱头的选择清单

评估平台时,问自己:

  1. 工作负载匹配: 主要是 BI 仪表盘、交互式探索、ML 特征构建还是运营工作?
  2. 延迟需求: 秒、分钟还是小时?是否需要流式新鲜度?
  3. 数据形态: 主要是宽事件日志(适合列式)还是大量点查(往往适合其他方案)?
  4. 并发: 同时有多少用户/查询,且它们有多可预测?
  5. 一致性需求: 需要强事务还是最终一致即可?
  6. 运维现实: 谁来运行,拥有哪些技能,凌晨两点的故障模式是什么?

如果厂商不能用通俗语言把产品映射到这些基本点上,“创新”很可能只是包装。

给构建或采购数据平台的团队的关键要点

斯通布雷克的核心思想很简单:当为特定任务设计并能随着任务演进时,数据库效果最好。

1) 按工作负载匹配系统(别指望一个引擎通吃)

在比较功能之前,先写清你实际需要做的事:

  • 分析: 长扫描、大量聚合、频繁读取
  • 事务: 许多小更新、严格正确性、快速响应
  • 混合负载: 两者兼有,但通常需精心调优与明确优先级
  • 实时流: 连续摄取与增量计算

有用的规则:如果你不能用几句话描述你的工作负载(查询模式、数据规模、延迟需求、并发),你最终会按流行词购物。

2) 为变化而设计,而不仅为今天的模式

团队往往低估需求变更的频率:新数据类型、新指标、新合规要求、新消费者。

偏好那些让变更常态化而非高风险的平台与数据模型:

  • 存储查询扩展点之间有清晰分离
  • 有安全的模式演进与新逻辑的灰度发布方式
  • 随着自然增长仍能保持可衡量的性能

3) 正确性是产品特性

快速答案只有在是正确的答案时才有价值。评估选项时,问系统如何处理:

  • 并发写入(两人/进程同时更新同一记录时)
  • 隔离与一致性(你得到哪些保证,为换取这些保证牺牲了什么?)
  • 运维故障模式(重启、部分故障、回填)

4) 面向非专家的实用评估清单

做一次小规模“用你数据的验证”,而不是仅看演示:

  • 试 3–5 个代表性查询,测量时间与成本。\n- 测试峰值并发(周一早晨那波流量)。\n- 验证数据新鲜度、恢复步骤以及日常谁能运营它。

5) 把架构决策变成可交付的软件

很多数据库建议止于“选对引擎”,但团队还得围绕该引擎交付应用和内部工具:管理面板、仪表盘、摄取服务和后台工作流程。

如果你想快速原型而不重造全流水线,一类 vibe-coding 平台(例如 Koder.ai)可以帮助你从聊天驱动的工作流中快速生成网页应用(React)、后端服务(Go + PostgreSQL)甚至移动客户端(Flutter)。在你迭代模式设计、构建小型内部“数据产品”或在做长期基础设施承诺前验证工作负载行为时,这类工具常很有用。

后续阅读(用于构建直觉)

如果你想更深入,请查阅 列式存储MVCCMPP 执行流处理。更多通俗解释可在 /blog 找到。

常见问题

为什么迈克尔·斯通布雷克对现代数据团队很重要?

他是少有的案例:把研究系统变成产品基因的人。Ingres(SQL + 查询优化)、Postgres(可扩展性 + MVCC 思想)和 Vertica(列式存储 + MPP 分析)中验证的理念,今天体现在数据仓库、OLTP 数据库和流处理平台的设计与营销中。

为什么 SQL 能成为许多数据系统的通用语言?

SQL 之所以普及,是因为它让你描述“要什么”(what),由数据库决定“如何做”(how)以高效获取结果。这种分离带来了:

  • 更快的迭代(每个报表不用写定制代码)
  • 更广的可用性(分析师和非工程师也能查询)
  • 优化器可以演进而无需重写应用
什么是基于成本的查询优化,为什么我应该关心?

基于成本的优化器利用表的统计信息比较不同的查询执行计划,选择预计成本最低的(I/O、CPU、内存的组合)。从实践角度看,它能帮助你:

  • 避免手动微调连接顺序和索引
  • 随数据增长保持性能稳定
  • 通过做更少的工作来降低开销
用通俗的话说,什么是 MVCC,它解决了什么问题?

MVCC(多版本并发控制)在短时间内保留行的多个版本,使读取者可以看到一致的快照,同时写入可以进行。日常效果是:

  • 仪表盘与读取操作更少阻塞写入
  • 长时间读取不容易让高写入应用卡住
  • 仍需计划清理/维护(旧版本会积累)
“可扩展的数据库”(Postgres)如何影响我今天能构建的东西?

可扩展性意味着数据库可以在受控方式下新增能力——类型、函数、索引——而不需要分叉或重写引擎。当你需要时,它有助于:

  • 存储更丰富的数据(例如地理空间、类 JSON 结构)
  • 将领域逻辑靠近数据(UDF)
  • 优化新的访问模式(专用索引)

运营层面的建议:把扩展当作依赖来对待——版本化、测试升级,并限制谁可以安装它们。

什么时候我应使用列存而不是面向行的数据库?

当你经常读写整条记录(OLTP)时,行存很好;当你扫描大量行但只访问少数字段(分析)时,列存更出色。简单启发式:

  • 频繁单行更新 + 点查 → 行式 OLTP
  • 大量扫描 + 聚合(SUM/COUNT、group by)→ 列式仓库/引擎
MPP 是什么,何时值得承担这种复杂性?

MPP(大规模并行处理)把数据分布到节点上,让多台机器并行执行一个 SQL 查询。适合场景包括:

  • 极大的事实表
  • 在分区上进行大量连接/聚合
  • 并发 BI 查询很多

代价包括数据分布决策、连接时的 shuffle 成本,以及对高频单行更新支持较弱。

什么是向量化执行,为什么分析引擎使用它?

向量化执行按批次(向量)处理数据,而不是逐行处理,能减少开销并更好利用 CPU 缓存。你通常会感受到:

  • 扫描、过滤和聚合更快
  • 宽表分析查询性能更好
  • 在繁重 BI 负载下吞吐更稳定
什么时候我需要流式处理而不是批处理流水线?

批处理在时间上有间隔,导致“新鲜度”滞后。流处理把事件当作持续输入,增量计算结果。常见适用情形:

  • 秒级欺诈/滥用检测
  • 错误暴增的运维告警
  • 实时产品指标

为了让计算有界,流系统使用窗口(如“最近 5 分钟”)而不是“全量历史”。

如何避免“一个数据库解决一切”但又不会陷入工具爆炸?

当每个系统都有清晰的工作负载边界并带来可测收益(成本、延迟、可靠性)时,多系统是健康的。为避免工具泛滥:

  • 写下每个工具的主要工作负载(OLTP、BI、缓存、流)
  • 明确归属与值班责任
  • 退役没有明确用途的工具
  • 用代表性查询与并发做小规模验证

如果需要决策框架,可复用文章中的检查表思维和 /blog 中的相关内容。

Related posts