Postgres 正在吞噬数据库世界

Postgres 正在吞噬数据库世界

作者:Ruohang Feng(@Vonng)|微信| Medium | 2024-03-04
标签:
 
  • PostgreSQL
  • 生态系统

PostgreSQL 不仅仅是一个简单的关系型数据库,它还是一个数据管理框架,具有席卷整个数据库领域的潜力。“使用 Postgres 做一切”的趋势不再局限于少数精英团队,而是正在成为主流的最佳实践。


OLAP 的新挑战者

在 2016 年的一次数据库聚会上,我曾指出 PostgreSQL 生态系统的一个重大缺陷是缺乏足够好的列式存储引擎来处理 OLAP 工作负载。虽然 PostgreSQL 本身提供了许多分析功能,但它在对较大数据集进行全面分析时的性能与专用的实时数据仓库并不相称。

以分析性能基准ClickBench为例,我们在其中记录了 PostgreSQL、其生态系统扩展和衍生数据库的性能。未经调整的 PostgreSQL 性能较差 ( x1050 ),但经过优化后可以达到 ( x47 )。此外,还有三个与分析相关的扩展:列式存储Hydra ( x42 )、时间序列TimescaleDB ( x103 ) 和分布式Citus ( x262 )。

点击工作台.png

ClickBench c6a.4xlarge,500gb gp2 的相对时间结果

这个性能还算不错,尤其是和 MySQL、MariaDB(x3065、x19700)等纯 OLTP 数据库相比;不过,它的第三层性能还不够“好”,落后于第一层 OLAP 组件 Umbra、ClickHouse、Databend、SelectDB(x3~x4)一个数量级。这是一个很难的境地——不够好到可以用,但又好到舍不得扔。

然而, ParadeDB和DuckDB的出现改变了游戏规则!

ParadeDB的原生 PG 扩展pg_analytics实现了第二层性能(x10),将与顶级性能的差距缩小到仅 3-4 倍。考虑到额外的好处,这种程度的性能差异通常是可以接受的 - ACID、新鲜度和实时数据无需 ETL、没有额外的学习曲线、无需维护单独的服务,更不用说其 ElasticSearch 级全文搜索功能了。

DuckDB专注于纯 OLAP,将分析性能推向极致(x3.2 )——除了专注于学术的闭源数据库 Umbra 之外,DuckDB 可以说是实际 OLAP 性能最快的。它不是 PG 扩展,但 PostgreSQL 可以通过DuckDB FDW和pg_quack等项目充分利用 DuckDB 作为嵌入式文件数据库的分析性能提升。

ParadeDB和DuckDB的出现,将PostgreSQL的分析能力推向了OLAP的顶层,填补了分析性能的最后一个关键空白。


数据库领域的钟摆

在数据库诞生之初,OLTP 和 OLAP 之间的区别并不存在。OLAP 数据仓库与数据库的分离出现于 20 世纪 90 年代,原因是传统 OLTP 数据库难以支持分析场景的查询模式和性能需求。

长期以来,数据处理的最佳实践是使用 MySQL/PostgreSQL 处理 OLTP 工作负载,并通过 ETL 流程将数据同步到专门的 OLAP 系统,如 Greenplum、ClickHouse、Doris、Snowflake 等。

DDIA,Martin Kleppmann,第 3 章,OLTP 共和国和 OLAP 王国

与许多“专业数据库”一样,专用 OLAP 系统的优势通常在于性能— 比原生 PG 或 MySQL 提高 1-3 个数量级。但与完整的 DMBS 相比,其代价是冗余数据、过多的数据移动、分布式组件之间数据值不一致、专业技能的额外劳动力成本、额外的许可成本、有限的查询语言能力、可编程性和可扩展性、有限的工具集成、较差的数据完整性和可用性。

然而俗话说得好,善有善报,恶有恶报。三十多年来,硬件遵循摩尔定律不断改进,性能成倍增加,成本却大幅下降。到 2024 年,一台 x86 机器可以拥有数百个核心(512 vCPU EPYC 9754 x2)、数 TB 的 RAM,单个 NVMe SSD 可以容纳高达 64 TB 的数据,单个全闪存机架可以达到 2PB;像 S3 这样的对象存储几乎可以提供无限的存储空间。

io 带宽

硬件的进步解决了数据量和性能问题,而数据库软件的发展(PostgreSQL、ParadeDB、DuckDB)解决了访问方法的挑战。这使分析领域(即所谓的“大数据”行业)的基本假设受到了审视。

正如 DuckDB 的宣言“大数据已死”所暗示的那样,大数据时代已经结束。大多数人没有那么多数据,而且大多数数据很少被查询。随着硬件和软件的发展,大数据的前沿逐渐消退,使得 99% 的场景都不再需要“大数据”。

如果现在 99% 的用例都可以在一台机器上使用独立的 DuckDB 或 PostgreSQL(及其副本)来处理,那么使用专用分析组件还有什么意义呢?如果每部智能手机都可以自由发送和接收短信,那么传呼机还有什么意义呢?(北美医院仍在使用传呼机,这表明可能只有不到 1% 的场景可能真正需要“大数据”。)

基本假设的转变正在引导数据库世界从多样化阶段重新走向融合,从大爆炸走向大规模灭绝。在这个过程中,统一、多模型、超融合数据库的新时代将会出现,OLTP 和 OLAP 重新统一。但谁将领导这项重新整合数据库领域的艰巨任务呢?


PostgreSQL:数据库世界吞噬者

数据库领域有很多细分领域:时间序列、地理空间、文档、搜索、图形、矢量数据库、消息队列和对象数据库。PostgreSQL 在所有这些领域都占有一席之地。

一个典型的例子是 PostGIS 扩展,它设定了地理空间数据库的事实标准;TimescaleDB 扩展尴尬地定位了“通用”时间序列数据库;而矢量扩展PGVector则将专用的矢量数据库领域变成了笑柄。

这不是第一次;我们在最古老和最大的子领域再次见证了这一点:OLAP 分析。但 PostgreSQL 的野心并不仅限于 OLAP;它瞄准的是整个数据库世界!

生态系统.jpg

PostgreSQL 为何如此强大?当然,它很先进,但 Oracle 也一样;它和 MySQL 一样都是开源的。PostgreSQL 的优势在于先进性和开源性,这使其能够与 Oracle/MySQL 竞争。但它真正的独特之处在于其极高的可扩展性和蓬勃发展的扩展生态系统

调查.png

TimescaleDB 调查:您选择使用 PostgreSQL 的主要原因是什么

PostgreSQL 不只是一个关系型数据库,而是一个可以覆盖整个数据库领域的数据管理框架,除了开源和先进性之外,其核心竞争力在于可扩展性,即底层的可重用性和扩展的可组合性。


极致可扩展性的魔力

PostgreSQL 允许用户开发扩展,利用数据库的通用基础架构以最小的成本提供功能。例如,矢量数据库扩展pgvector仅包含几千行代码,与 PostgreSQL 的数百万行代码相比,其复杂性微不足道。然而,这个“微不足道”的扩展实现了完整的矢量数据类型和索引功能,性能优于许多专门的矢量数据库。

为什么?因为 pgvector 的创建者不需要担心数据库的一般额外复杂性:ACID、恢复、备份和 PITR、高可用性、访问控制、监控、部署、第三方生态系统工具、客户端驱动程序等,这些都需要数百万行代码才能解决。他们只关注问题的本质复杂性。

例如 ElasticSearch 是基于 Lucene 搜索库开发的,Rust 生态中也有改进的下一代全文搜索库Tantivy作为 Lucene 的替代品,而 ParadeDB 只需要包装并接入 PostgreSQL 的接口,就能提供媲美 ElasticSearch 的搜索服务,更重要的是,它可以站在 PostgreSQL 的肩膀上,借助整个 PG 生态的联合力量(例如与 PG Vector 的混合搜索),与另一个专用数据库“不公平”地竞争。

图片

Pigsty 有 255 个扩展可用。生态系统中还有1000 多个扩展


可扩展性带来了另一个巨大的优势:扩展的可组合性,允许不同的扩展协同工作,产生 1+1 » 2 的协同效应。例如,TimescaleDB 可以与 PostGIS 结合提供时空数据支持;用于全文搜索的 BM25 扩展可以与 PGVector 扩展结合,提供混合搜索功能。

此外,分布式扩展Citus可以透明地将独立集群转换为水平分区的分布式数据库集群。该功能可以与其他功能正交组合,使 PostGIS 成为分布式地理空间数据库,PGVector 成为分布式矢量数据库,ParadeDB 成为分布式全文搜索数据库等。


更强大的是,扩展可以独立发展,无需繁琐的主分支合并和协调。这允许扩展——PG 的可扩展性让众多团队可以并行探索数据库的可能性,所有扩展都是可选的,不会影响核心功能的可靠性。那些成熟且强大的功能有机会稳定地集成到主分支中。

PostgreSQL通过极端可扩展性的魔力实现了基础可靠性敏捷功能,使其成为数据库领域的异类,并改变了数据库领域的游戏规则。


DB 竞技场中的游戏规则改变者

PostgreSQL 的出现改变了数据库领域的范式:致力于打造“新数据库内核”的团队现在面临着严峻的考验——如何在开源、功能丰富的 Postgres 中脱颖而出。他们独特的价值主张是什么?

在革命性的硬件突破出现之前,实用的、新的、通用的数据库内核似乎不太可能出现。没有任何一个数据库能够与 PG 的整体实力相媲美,并得到其所有扩展的支持——即使是 Oracle 也不行,因为 PG 是开源和免费的。

如果某个小众数据库产品能够在特定方面(通常是性能)比 PostgreSQL 好几个数量级,那么它可能会为自己开辟一席之地。然而,PostgreSQL 生态系统通常很快就会产生开源扩展替代方案。选择开发 PG 扩展而不是全新的数据库,可以让团队在追赶中拥有压倒性的速度优势!

按照这种逻辑,PostgreSQL 生态系统将像滚雪球一样发展,不断积累优势,并最终走向垄断,几年后将与 Linux 内核在服务器操作系统中的地位相媲美。开发人员调查和数据库趋势报告证实了这一轨迹。

sf-调查

StackOverflow 2023 调查:PostgreSQL,十项全能选手

sf-趋势.jpg

StackOverflow 过去 7 年的数据库趋势

PostgreSQL 长期以来一直是 HackerNews 和 StackOverflow 中最受欢迎的数据库。许多新的开源项目默认将 PostgreSQL 作为其主要(如果不是唯一)数据库选择。许多新一代公司都全面采用 PostgreSQL。

正如《彻底简化:只使用 Postgres 》一文所说, “只使用 Postgres ”可以简化技术栈、减少组件、加速开发、降低风险、增加更多功能。Postgres可以取代许多后端技术,包括 MySQL、Kafka、RabbitMQ、ElasticSearch、Mongo 和 Redis,轻松服务数百万用户。只使用 Postgres不再局限于少数精英团队,而是成为主流的最佳实践。


还能做什么?

数据库领域的结局似乎是可以预见的。但我们能做什么,又应该做什么呢?

对于绝大多数场景来说,PostgreSQL 已经是一个近乎完美的数据库内核,因此内核“瓶颈”的说法显得荒谬。以修改内核为卖点的 PostgreSQL 和 MySQL 分支基本上是行不通的。

这与当今 Linux 操作系统内核的情况类似;尽管 Linux 发行版众多,但每个人都选择相同的内核。分叉 Linux 内核被视为会带来不必要的困难,业界对此并不欢迎。

因此,主要的冲突不再是数据库内核本身,而是两个方向——数据库扩展服务!前者涉及内部可扩展性,而后者涉及外部可组合性。与操作系统生态系统非常相似,竞争格局将集中在数据库发行版上。在数据库领域,只有以扩展和服务为中心的发行版才有机会获得最终的成功。

内核依然不温不火,MySQL 母版的分支 MariaDB 即将退市,而 AWS 则通过在免费内核之上提供服务和扩展而获利颇丰。投资已流入众多 PG 生态系统扩展和服务发行版:Citus、TimescaleDB、Hydra、PostgresML、ParadeDB、FerretDB、StackGres、Aiven、Neon、Supabase、Tembo、PostgresAI 以及我们自己的 PG 发行版 — — Pigsty。


PostgreSQL 生态系统中的一个难题是许多扩展和工具独立发展,缺乏一个统一器来协同它们。例如,Hydra 发布了自己的软件包和 Docker 镜像,PostgresML 也是如此,每个都分发带有自己的扩展的 PostgreSQL 镜像,并且只分发自己的扩展。这些镜像和软件包远非 AWS RDS 等全面的数据库服务。

即使是像 AWS 这样的服务提供商和生态系统集成商,在众多扩展面前也显得力不从心,由于各种原因(AGPLv3 许可证、多租户的安全挑战)无法包含许多扩展,从而无法充分利用 PostgreSQL 生态系统扩展的协同放大潜力。

扩展类别猪圈 RDS 和 PGDGAWS RDS PG阿里云RDS PG
添加扩展免费安装不允许不允许
地理空间PostGIS 3.4.2PostGIS 3.4.1PostGIS 3.3.4
时间序列TimescaleDB 2.14.2
分配式西图斯 12.1
人工智能/机器学习PostgresML 2.8.1
柱状Hydra 1.1.1
向量PGVector 0.6PGVector 0.6pase 0.0.1
稀疏向量PG稀疏0.5.6
全文搜索pg_bm25 的社区帖子
图形Apache AGE 1.5.0
GraphQLPG GraphQL 1.5.0
消息队列PGQ 3.5.0 简体中文
联机分析处理pg_analytics 0.5.6
鸭子数据库duckdb_fdw 1.1
CDCwal2json 2.5.3wal2json 2.5
控制膨胀pg_repack 1.5.0pg_repack 1.5.0pg_repack 1.4.8
点云PG 点云 1.2.5Ganos PointCloud 6.1

许多重要的扩展在 Cloud RDS 上不可用(PG 16,2024-02-29)

扩展是 PostgreSQL 的灵魂。没有使用扩展的自由的 Postgres 就像没有盐的烹饪,一个巨大的限制。

解决这个问题是我们的主要目标之一。


我们的决议:猪圈

尽管我之前接触过 MySQL、Oracle 和 MSSQL,但当我在 2015 年首次使用 PostgreSQL 时,我就坚信它未来将在数据库领域占据主导地位。近十年后,我从一名用户和管理员转变为一名贡献者和开发者,见证了 PG 朝着这一目标迈进。

通过与不同用户的交流,我们发现数据库领域的短板已经不在于内核了,PostgreSQL 已经足够了,关键在于如何利用好内核的能力,这也是 RDS 能够取得巨大成功的原因。

然而,我相信这种功能应该像免费软件一样可以访问,就像 PostgreSQL 内核本身一样 —— 可供每个用户使用,而不仅仅是从网络封建领主那里租用。

因此,我创建了Pigsty,一个功能齐全、本地优先的 PostgreSQL 发行版,作为开源RDS替代品,旨在利用 PostgreSQL 生态系统扩展的集体力量,并使生产级数据库服务的访问民主化。

图片

Pigsty 是PostgreSQL i n G reat STY le 的缩写,代表着PostgreSQL 的巅峰。

针对PostgreSQL数据库服务的核心问题,我们定义了6个核心主张:

可扩展的 Postgres可靠的基础设施可观察的图形可用的服务可维护的工具箱可组合的模块

这些价值主张的首字母缩写为 Pigsty:

Postgres基础设施、图形、服务工具箱的。

您的图形化 Postgres 基础设施服务工具箱。

可扩展的 PostgreSQL是此发行版的关键。在最近发布的Pigsty v2.6中,我们集成了 DuckDB FDW 和 ParadeDB 扩展,大大增强了 PostgreSQL 的分析能力,并确保每个用户都可以轻松利用这种能力。

我们的目标是整合 PostgreSQL 生态系统中的优势,打造出一股类似于数据库界Ubuntu的协同力量。我相信内核之争已经尘埃落定,真正的竞争前沿就在这里。

  • PostGIS:提供地理空间数据类型和索引,GIS 的事实标准(& pgPointCloud pgRouting)。
  • TimescaleDB:增加时间序列、连续聚合、分布式、列式存储和自动压缩功能。
  • PGVector:支持 AI 向量/嵌入和 ivfflat、hnsw 向量索引(&稀疏向量的pg_sparse )。
  • Citus:将经典的主从PG集群改造为水平分区的分布式数据库集群。
  • Hydra:增加了列式存储和分析功能,可与 ClickHouse 的分析能力相媲美。
  • ParadeDB:将全文搜索和混合检索提升到 ElasticSearch 级别(& zhparser用于中文标记化)。
  • Apache AGE:图形数据库扩展,为 PostgreSQL 添加类似 Neo4J 的 OpenCypher 查询支持。
  • PG GraphQL:为 PostgreSQL 添加原生内置 GraphQL 查询语言支持。
  • DuckDB FDW:通过 PostgreSQL(&DuckDB CLI)直接访问 DuckDB 强大的嵌入式分析数据库文件。
  • Supabase:基于 PostgreSQL 的开源 Firebase 替代品,提供完整的应用开发存储解决方案。
  • FerretDB:基于 PostgreSQL 的开源 MongoDB 替代品,兼容 MongoDB API/驱动程序。
  • PostgresML:促进经典的机器学习算法,使用 SQL 调用、部署和训练 AI 模型。

图片

开发者们,你们的选择将塑造数据库世界的未来。希望我的工作能帮助你们更好地利用世界上最先进的开源数据库内核:PostgreSQL

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/704300.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于WPF技术的换热站智能监控系统04--实现左侧历史曲线

1、区域划分 左侧分5行,第一行信息标题,第二行历史曲线 2、安装livecharts图表控件 3、引入图表控件命名空间 4、使用控件 5、运行效果 走过路过不要错过,点赞关注收藏又圈粉,共同致富,为财务自由作出贡献

IP地址乱成一团?用Shell一键搞定!

在日常的运维工作中,我们经常需要对各种数据进行处理和分析,其中包括对IP地址的管理和排序。排序后的IP地址列表可以帮助我们更好地进行日志分析、网络流量监控和故障排除。 本文将模拟一个运维场景,展示如何对IP地址进行排序,并探…

Mongodb使用$pop删除数组中的元素

学习mongodb,体会mongodb的每一个使用细节,欢迎阅读威赞的文章。这是威赞发布的第67篇mongodb技术文章,欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题,欢迎在文章下面点个赞,或者关…

编译和连接

目录1. 翻译环境和运行环境2. 翻译环境:预编译编译汇编链接1. 翻译环境和运行环境 在ANSI C 的任何一种实现中,存在两个不同环境。 (1) 翻译环境,在这种环境中源代码被转换为可执行的机器指令(二进制指令)。 (2) 执行环境,它用于实际执行的代…

PostgreSQL 多表连接不同维度聚合统计查询

摘要:在本文中,你将学习到如何使用 PostgreSQL 完全外连接,从两个或多个表中聚合维度统计数据。 文章目录 一、常用的连接类型图示二、数据库表设计示例三、连接查询示例1. inner join 内连接(不能满足维度统计需求)2. full join 完全外连接(满足维度统计需求)一、常用的…

Golang免杀-分离式加载器(传参)AES加密

目录 enc.go 生成: dec.go --执行dec.go...--上线 cs生成个c语言的shellcode. enc.go go run .\enc.go shellcode 生成: --key为公钥. --code为AES加密后的数据, ----此脚本每次运行key和code都会变化. package mainimport ("bytes""crypto/aes"&…

java1.8运行arthas-boot.jar运行报错解决

报错内容 输入java -jar arthas-boot.jar,后报错。 [INFO] JAVA_HOME: D:\developing\jdk\jre1.8 [INFO] arthas-boot version: 3.7.2 [INFO] Can not find java process. Try to run jps command lists the instrumented Java HotSpot VMs on the target system.…

Spring Boot集成antlr实现词法和语法分析

1.什么是antlr? Antlr4 是一款强大的语法生成器工具,可用于读取、处理、执行和翻译结构化的文本或二进制文件。基本上是当前 Java 语言中使用最为广泛的语法生成器工具。Twitter搜索使用ANTLR进行语法分析,每天处理超过20亿次查询&#xff1…

20240612在飞凌的OK3588-C开发板的linux系统下测试以太网

20240612在飞凌的OK3588-C开发板的linux系统下测试以太网 2024/6/12 17:56 欢迎您入坑飞凌的OK3588-C开发板,使用飞凌的预编译的固件:OK3588-linuxfs-img.tar.bz2 Z:\rockdev\update.img tar jxvf OK3588-linuxfs-img.tar.bz2 首先,刷Android…

自己用pip下载好模块啦,但是在pycharm里面不显示?

问题: 今天在cmd里面用pip命令安装第三方模块,最后用pip list 命令发现已经成功安装,但是在pycharm里面用该模块的时候,还是爆红,显示没有该库 。 解决方法: 第一种(项目刚创建)&am…

虚拟声卡实现音频回环

虚拟声卡实现音频回环 一、电脑扬声器播放声音路由到麦克风1. Voicemeeters安装设置2. 音频设备选择 二、回声模拟 一、电脑扬声器播放声音路由到麦克风 1. Voicemeeters安装设置 2. 音频设备选择 以腾讯会议为例 二、回声模拟 选中物理输入设备“Stereo Input 1”和物理输出设…

GUI listbox

GUI listbox (自用笔记) 功能details拆分 同时打开多个文件,可以是不同类型的,在listbox中显示出路径和文件名; 计算每个数据文件(.txt或.dat)掉帧出现的行数,存储到元胞数组&…

Vue10-事件修饰符

一、示例&#xff1a;<a>标签不执行默认的跳转行为 1-1、方式一 <a href"http://www.baidu.com" onclick"event.preventDefault();">点击我</a> 1-2、方式二 1-3、方式三&#xff1a;事件修饰符 二、Vue的六种事件修饰符 2-1、prevent&…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 6月13日,星期四

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年6月13日 星期四 农历五月初八 1、 财政部&#xff1a;将在19日第一次续发行2024年20年期超长期特别国债。 2、 成本低&#xff0c;商载高&#xff0c;我国自主研制HH-100商用无人运输机首飞成功。 3、 四川甘孜州石渠县1…

Mongodb在UPDATE操作中使用$pull操作

学习mongodb&#xff0c;体会mongodb的每一个使用细节&#xff0c;欢迎阅读威赞的文章。这是威赞发布的第68篇mongodb技术文章&#xff0c;欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题&#xff0c;欢迎在文章下面点个赞&#xff0c;或者关…

网站线上模板建设的优缺点

优点&#xff1a; 1.搭建的时间短&#xff0c;在线建站&#xff0c;只需要登录注册然后选择网站模板创建网站即可管理自己的网站后台&#xff0c;就几步操作就可以实现。 2.网站出错率少&#xff0c;因为有很多用户在使用&#xff0c;前期所报出来的问题就已经一一…

PHP开发的爱情盲盒交友系统网站源码

源码介绍 PHP开发的爱情盲盒交友系统网站源码 独立后台 源码截图 源码下载 PHP开发的爱情盲盒交友系统网站源码

【Tkinter界面】Canvas 图形绘制(03/5)

文章目录 一、说明二、画布和画布对象2.1 画布坐标系2.2 鼠标点中画布位置2.3 画布对象显示的顺序2.4 指定画布对象 三、你应该知道的画布对象操作3.1 什么是Tag3.2 操作Tag的函数 https://www.cnblogs.com/rainbow-tan/p/14852553.html 一、说明 Canvas&#xff08;画布&…

【高频】从准备更新一条数据到事务的提交的流程描述

一、相关问题 SQL语句是如何被MySQL解析和分析的?MySQL是如何为SQL语句生成最优的执行计划的?执行计划的各个步骤是如何一步步执行的?MySQL是如何访问存储引擎得到数据的&#xff1f;MySQL是如何将查询结果返回给客户端的?MySQL是如何处理事务的&#xff1f; 参考回答&am…

【Spine学习01】之基本操作

Spine简单讲就是做动画的&#xff0c;跟PS配合使用 左键单击选择 双颊取消选择 右键移动视图 右键单击移动变换 crtly重做 c 旋转 v 移动 x 缩放 z 倾斜 教程看的是B站的断断子老师&#xff0c;这个专栏用来放的是本人的学习笔记。
最新文章