MySQL 与 PostgreSQL 相比哪个更好?

2017 年 11 月 30 日 数据库技术大会 标点符

点击蓝色字关注 "数据库技术大会" 一起玩耍哦~


作者:标点符

www.biaodianfu.com/mysql-vs-postgresql.html


网上已经有很多拿 PostgreSQL 与 MySQL 比较的文章了,这篇文章只是对一些重要的信息进行下梳理。

在开始分析前,先来看下这两张图:



MySQL


MySQL 声称自己是最流行的开源数据库。LAMP 中的 M 指的就是 MySQL。构建在 LAMP 上的应用都会使用 MySQL,如 WordPress、Drupal 等大多数 php 开源程序。MySQL 最初是由 MySQL AB 开发的,然后在 2008 年以 10 亿美金的价格卖给了 Sun 公司,Sun 公司又在 2010 年被 Oracle 收购。Oracle 支持 MySQL 的多个版本:Standard、Enterprise、Classic、Cluster、Embedded 与 Community。其中有一些是免费下载的,另外一些则是收费的。其核心代码基于 GPL 许可,由于 MySQL 被控制在 Oracle,社区担心会对 MySQL 的开源会有影响,所以开发了一些分支,比如: MariaDB 和 Percona。


PostgreSQL


PostgreSQL 标榜自己是世界上最先进的开源数据库。PostgreSQL 的一些粉丝说它能与 Oracle 相媲美,而且没有那么昂贵的价格和傲慢的客服。最初是 1985 年在加利福尼亚大学伯克利分校开发的,作为 Ingres 数据库的后继。PostgreSQL 是完全由社区驱动的开源项目。它提供了单个完整功能的版本,而不像 MySQL 那样提供了多个不同的社区版、商业版与企业版。PostgreSQL 基于自由的 BSD/MIT 许可,组织可以使用、复制、修改和重新分发代码,只需要提供一个版权声明即可。


MySQL 与 PostgreSQL 的对比


MySQL 的背后是一个成熟的商业公司,而 PostgreSQL 的背后是一个庞大的志愿开发组。这使得 MySQL 的开发过程更为慎重,而 PostgreSQL 的反应更为迅速。这样的两种背景直接导致了各自固有的优点和缺点。


PostgreSQL 相对于 MySQL 的优势


1)不仅仅是关系型数据库


除了存储正常的数据类型外,还支持存储:


array,不管是一位数组还是多为数组均支持

json(hStore)和 jsonb,相比使用 text 存储接送要高效很多


json 和 jsonb 之间的区别


jsonb 和 json 在更高的层面上看起来几乎是一样的,但在存储实现上是不同的。


json 存储完的文本,json 列会每次都解析存储的值,它不支持索引,但你可以为查询创建表达式索引。


jsonb 存储的二进制格式,避免了重新解析数据结构。它支持索引,这意味着你可以不使用指定的索引就能查询任何路径。


当我们比较写入数据速度时,由于数据存储的方式的原因,jsonb 会比 json 稍微的慢一点。json 列会每次都解析存储的值,这意味着键的顺序要和输入的时候一样。但 jsonb 不同,以二进制格式存储且不保证键的顺序。因此,如果你有软件需要依赖键的顺序,jsonb 可能不是你的应用的最佳选择。使用 jsonb 的优势还在于你可以轻易的整合关系型数据和非关系型数据, PostgreSQL 对于 mongodb 这类的基于文档的数据库是个不小的威胁,毕竟如果一个表中只有一列数据的类型是半结构化的,没有必要为了迁就它而整个表的设计采用 schemaless 的结构。


2)支持地理信息处理扩展


PostGIS 为 PostgreSQL 提供了存储空间地理数据的支持,使 PostgreSQL 成为了一个空间数据库,能够进行空间数据管理、数量测量与几何拓扑分析。在功能上,和 MYSQL 对比,PostGIS 具有下列优势:



O2O 业务场景中的 LBS 业务使用 PostgreSQL + PostGIS 有无法比拟的优势。


3)可以快速构建 REST API


PostgREST 可以方便的为任何 PostgreSQL 数据库提供完全的 RESTful API 服务。


4)支持树状结构


支持 R-trees 这样可扩展的索引类型,可以更方便地处理一些特殊数据。MySQL 处理树状的设计会很复杂, 而且需要写很多代码, 而 PostgreSQL 可以高效处理树结构。


5)有极其强悍的 SQL 编程能力


支持递归,有非常丰富的统计函数和统计语法支持。


MySQL:支持 CREATE PROCEDURE 和 CREATE FUNCTION 语句。存储过程可以用 SQL 和 C++ 编写。用户定义函数可以用 SQL、C 和 C++ 编写。


PostgreSQL:没有单独的存储过程,都是通过函数实现的。用户定义函数可以用 PL/pgSQL(专用的过程语言)、PL/Tcl、PL/Perl、PL/Python 、SQL 和 C 编写。


6)外部数据源支持


可以把 70 种外部数据源 (包括 Mysql, Oracle, CSV, hadoop …) 当成自己数据库中的表来查询。Postgres 有一个针对这一难题的解决方案:一个名为 “外部数据封装器(Foreign Data Wrapper,FDW)” 的特性。该特性最初由 PostgreSQL 社区领袖 Dave Page 四年前根据 SQL 标准 SQL/MED(SQL Management of External Data)开发。FDW 提供了一个 SQL 接口,用于访问远程数据存储中的远程大数据对象,使 DBA 可以整合来自不相关数据源的数据,将它们存入 Postgres 数据库中的一个公共模型。这样,DBA 就可以访问和操作其它系统管理的数据,就像在本地 Postgres 表中一样。例如,使用 FDW for MongoDB,数据库管理员可以查询来自文档数据库的数据,并使用 SQL 将它与来自本地 Postgres 表的数据相关联。借助这种方法,用户可以将数据作为行、列或 JSON 文档进行查看、排序和分组。他们甚至可以直接从 Postgres 向源文档数据库写入(插入、更细或删除)数据,就像一个一体的无缝部署。也可以对 Hadoop 集群或 MySQL 部署做同样的事。FDW 使 Postgres 可以充当企业的中央联合数据库或 “Hub”。


7)没有字符串长度限制


一般关系型数据库的字符串有限定长度 8k 左右,无限长 TEXT 类型的功能受限,只能作为外部大数据访问。而 PostgreSQL 的 TEXT 类型可以直接访问,SQL 语法内置正则表达式,可以索引,还可以全文检索,或使用 xml xpath。MySQL 的各种 text 字段有不同的限制,要手动区分 small text, middle text, large text… PostgreSQL 没有这个限制,text 能支持各种大小。


8)支持图结构数据存储


没有具体使用过,具体可以自己搜索下。参考链接:https://mp.weixin.qq.com/s/cjor82wgDu5gzDvTYpLDWw


9)支持窗口函数


窗口函数提供跨行相关的当前查询行集执行计算的能力。仅当调用跟着 OVER 子句的聚集函数,作为窗口函数;否则它们作为常规的聚合函数。窗口也是一种分组,但和 group by 的分组不同。窗口,可以提供分组之外,还可以执行对每个窗口进行计算。可以相像成是 group by 后,然后对每个分组进行计算,而不像 Group by ,只是单纯地分组。MySQL 不支持 OVER 子句, 而 PostgreSQL 支持。OVER 子句能简单的解决 “每组取 top 5” 的这类问题。MySQL 支持的 SQL 语法 (ANSI SQL 标准) 的很小一部分。不支持递归查询、通用表表达式(Oracle 的 with 语句)或者窗口函数(分析函数)。


10)对索引的支持更强


PostgreSQL 的可以使用函数和条件索引,这使得 PostgreSQL 数据库的调优非常灵活,mysql 就没有这个功能,条件索引在 web 应用中很重要。对于索引类型:


MySQL:取决于存储引擎。MyISAM:BTREE,InnoDB:BTREE。


PostgreSQL:支持 B - 树、哈希、R - 树和 Gist 索引。


InnoDB 的表和索引都是按相同的方式存储。也就是说表都是索引组织表。这一般要求主键不能太长而且插入时的主键最好是按顺序递增,否则对性能有很大影响。PostgreSQL 不存在这个问题。


索引类型方面,MySQL 取决于存储引擎。MyISAM:BTREE,InnoDB:BTREE。PostgreSQL 支持 B - 树、哈希、R - 树和 Gist 索引。


11)集群支持更好


Mysql Cluster 可能与你的想象有较大差异。开源的 cluster 软件较少。复制 (Replication) 功能是异步的并且有很大的局限性。例如,它是单线程的 (single-threaded),因此一个处理能力更强的 Slave 的恢复速度也很难跟上处理能力相对较慢的 Master。


PostgreSQL 有丰富的开源 cluster 软件支持。plproxy 可以支持语句级的镜像或分片,slony 可以进行字段级的同步设置,standby 可以构建 WAL 文件级或流式的读写分离集群,同步频率和集群策略调整方便,操作非常简单。


另外,PostgreSQL 的主备复制属于物理复制,相对于 MySQL 基于 binlog 的逻辑复制,数据的一致性更加可靠,复制性能更高,对主机性能的影响也更小。对于 WEB 应用来说,复制的特性很重要,mysql 到现在也是异步复制,pgsql 可以做到同步,异步,半同步复制。还有 mysql 的同步是基于 binlog 复制,类似 oracle golden gate, 是基于 stream 的复制,做到同步很困难,这种方式更加适合异地复制,pgsql 的复制基于 wal,可以做到同步复制。同时,pgsql 还提供 stream 复制。


12)事务隔离做的更好


MySQL 的事务隔离级别 repeatable read 并不能阻止常见的并发更新, 得加锁才可以, 但悲观锁会影响性能, 手动实现乐观锁又复杂. 而 PostgreSQL 的列里有隐藏的乐观锁 version 字段, 默认的 repeatable read 级别就能保证并发更新的正确性, 并且又有乐观锁的性能。


13)对于字符支持更好一些


MySQL 里需要 utf8mb4 才能显示 emoji 的坑, PostgreSQL 没这个坑。


14)对表连接支持较完整


对表连接支持较完整,MySQL 只有一种表连接类型: 嵌套循环连接 (nested-loop), 不支持排序 - 合并连接 (sort-merge join) 与散列连接 (hash join)。PostgreSQL 都支持。


15)存储方式支持更大的数据量


PostgreSQL 主表采用堆表存放,MySQL 采用索引组织表,能够支持比 MySQL 更大的数据量。


16)时间精度更高


MySQL 对于时间、日期、间隔等时间类型没有秒以下级别的存储类型,而 PostgreSQL 可以精确到秒以下。


17)优化器的功能较完整


MySQL 对复杂查询的处理较弱,查询优化器不够成熟,explain 看执行计划的结果简单。性能优化工具与度量信息不足。


PostgreSQL 很强大的查询优化器,支持很复杂的查询处理。explain 返回丰富的信息。提供了一些性能视图,可以方便的看到发生在一个表和索引上的 select、delete、update、insert 统计信息,也可以看到 cache 命中率。网上有一个开源的 pgstatspack 工具。


18) 序列支持更好


MySQL 不支持多个表从同一个序列中取 id, 而 PostgreSQL 可以。


19)对子查询支持更好


对子查询的支持。虽然在很多情况下在 SQL 语句中使用子查询效率低下,而且绝大多数情况下可以使用带条件的多表连接来替代子查询,但是子查询的存在在很多时候仍然不可避免。而且使用子查询的 SQL 语句与使用带条件的多表连接相比具有更高的程序可读性。几乎任何数据库的子查询 (subquery) 性能都比 MySQL 好。


20)增加列更加简单


MySQL 表增加列,基本上是重建表和索引,会花很长时间。PostgreSQL 表增加列,只是在数据字典中增加表定义,不会重建表.


MySQL 相对于 PostgreSQL 的优势


1)MySQL 比 PostgreSQL 更流行


流行对于一个商业软件来说,也是一个很重要的指标,流行意味着更多的用户,意味着经受了更多的考验,意味着更好的商业支持、意味着更多、更完善的文档资料。易用,很容易安装。第三方工具,包括可视化工具,让用户能够很容易入门。


2)回滚实现更优


innodb 的基于回滚段实现的 MVCC 机制,相对 PG 新老数据一起存放的基于 XID 的 MVCC 机制,是占优的。新老数据一起存放,需要定时触发 VACUUM,会带来多余的 IO 和数据库对象加锁开销,引起数据库整体的并发能力下降。而且 VACUUM 清理不及时,还可能会引发数据膨胀。


3)在 Windows 上运行更可靠


与 PostgreSQL 相比,MySQL 更适宜在 Windows 环境下运行。MySQL 作为一个本地的 Windows 应用程序运行 (在 NT/Win2000/WinXP 下,是一个服务),而 PostgreSQL 是运行在 Cygwin 模拟环境下。PostgreSQL 在 Windows 下运行没有 MySQL 稳定,应该是可以想象的。


4)线程模式相比进程模式的优势


MySQL 使用了线程,而 PostgreSQL 使用的是进程。在不同线程之间的环境转换和访问公用的存储区域显然要比在不同的进程之间要快得多。


进程模式对多 CPU 利用率比较高。进程模式共享数据需要用到共享内存,而线程模式数据本身就是在进程空间内都是共享的,不同线程访问只需要控制好线程之间的同步。


线程模式对资源消耗比较少。所以 MySQL 能支持远比 PostgreSQL 多的更多的连接。但 PostgreSQL 中有优秀的连接池软件软件,如 pgbouncer 和 pgpool,所以通过连接池也可以支持很多的连接。


5)权限设置上更加完善


MySQL 在权限系统上比 PostgreSQL 某些方面更为完善。PostgreSQL 只支持对于每一个用户在一个数据库上或一个数据表上的 INSERT、SELECT 和 UPDATE/DELETE 的授权,而 MySQL 允许你定义一整套的不同的数据级、表级和列级的权限。对于列级的权限, PostgreSQL 可以通过建立视图,并确定视图的权限来弥补。MySQL 还允许你指定基于主机的权限,这对于目前的 PostgreSQL 是无法实现的,但是在很多时候,这是有用的。


6)存储引擎插件化机制


MySQL 的存储引擎插件化机制,使得它的应用场景更加广泛,比如除了 innodb 适合事务处理场景外,myisam 适合静态数据的查询场景。


7)适应 24/7 运行


MySQL 可以适应 24/7 运行。在绝大多数情况下,你不需要为 MySQL 运行任何清除程序。PostgreSQL 目前仍不完全适应 24/7 运行,这是因为你必须每隔一段时间运行一次 VACUUM。


8)更加试用于简单的场景


PostgreSQL 只支持堆表,不支持索引组织表,Innodb 只支持索引组织表。


索引组织表的优势:表内的数据就是按索引的方式组织,数据是有序的,如果数据都是按主键来访问,那么访问数据比较快。而堆表,按主键访问数据时,是需要先按主键索引找到数据的物理位置。


索引组织表的劣势:索引组织表中上再加其它的索引时,其它的索引记录的数据位置不再是物理位置,而是主键值,所以对于索引组织表来说,主键的值不能太大,否则占用的空间比较大。


对于索引组织表来说,如果每次在中间插入数据,可能会导致索引分裂,索引分裂会大大降低插入的性能。所以对于使用 innodb 来说,我们一般最好让主键是一个无意义的序列,这样插入每次都发生在最后,以避免这个问题。


由于索引组织表是按一个索引树,一般它访问数据块必须按数据块之间的关系进行访问,而不是按物理块的访问数据的,所以当做全表扫描时要比堆表慢很多,这可能在 OLTP 中不明显,但在数据仓库的应用中可能是一个问题。


总结


MySQL 从一开始就没有打算做所有事情,因而它在功能方面有一定的局限性,并不能满足一些先进应用程序的要求。MySQL 对某些功能(例如引用、事务、审计等)的实现方式使得它与其他的关系型数据库相比缺少了一些可靠性。对于简单繁重的读取操作,使用 PostgreSQL 可能有点小题大做,同时性能也比 MySQL 这样的同类产品要差。除非你需要绝对的数据完整性,ACID 遵从性或者设计复杂,否则 PostgreSQL 对于简单的场景而言有点多余。


如何你确定只在 MySQL 和 PostgreSQL 中进行选择,以下规则总是有效的:

如果你的操作系统是 Windows,你应该使用 MySQL。


当绝对需要可靠性和数据完整性的时候,PostgreSQL 是更好的选择。


如果需要数据库执行定制程序,那么可扩展的 PostgreSQL 是更好的选择。


你的应用处理的是地理数据,由于 R-TREES 的存在,你应该使用 PostgreSQL。


如果你对数据库并不了十分了解,甚至不知道事务、存储过程等究竟是什么,你应该使用 MySQL。


以上内容只是个人观点

如果你有不同的看法可以在评论区一起交流哦~


登录查看更多
0

相关内容

PostgreSQL 是自由的对象-关系数据库服务器(数据库管理系统),在灵活的 BSD 风格许可证下发行。
【2020新书】使用高级C# 提升你的编程技能,412页pdf
专知会员服务
56+阅读 · 2020年6月26日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
115+阅读 · 2020年5月10日
【2020新书】C++20 特性 第二版,A Problem-Solution Approach
专知会员服务
57+阅读 · 2020年4月26日
【资源】100+本免费数据科学书
专知会员服务
105+阅读 · 2020年3月17日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
94+阅读 · 2019年12月4日
在K8S上运行Kafka合适吗?会遇到哪些陷阱?
DBAplus社群
9+阅读 · 2019年9月4日
携程用ClickHouse轻松玩转每天十亿级数据更新
DBAplus社群
11+阅读 · 2019年8月6日
工行基于MySQL构建分布式架构的转型之路
炼数成金订阅号
15+阅读 · 2019年5月16日
亿级订单数据的访问与存储,怎么实现与优化?
码农翻身
16+阅读 · 2019年4月17日
去哪儿网开源DNS管理系统OpenDnsdb
运维帮
21+阅读 · 2019年1月22日
6大最常用的Java机器学习库一览
AI前线
4+阅读 · 2018年10月9日
Python 杠上 Java、C/C++,赢面有几成?
CSDN
6+阅读 · 2018年4月12日
33款可用来抓数据的开源爬虫软件工具 (推荐收藏)
数据科学浅谈
6+阅读 · 2017年7月29日
Spark的误解-不仅Spark是内存计算,Hadoop也是内存计算
Area Attention
Arxiv
5+阅读 · 2019年5月23日
Efficient and Effective $L_0$ Feature Selection
Arxiv
5+阅读 · 2018年8月7日
Arxiv
6+阅读 · 2018年5月22日
VIP会员
相关资讯
在K8S上运行Kafka合适吗?会遇到哪些陷阱?
DBAplus社群
9+阅读 · 2019年9月4日
携程用ClickHouse轻松玩转每天十亿级数据更新
DBAplus社群
11+阅读 · 2019年8月6日
工行基于MySQL构建分布式架构的转型之路
炼数成金订阅号
15+阅读 · 2019年5月16日
亿级订单数据的访问与存储,怎么实现与优化?
码农翻身
16+阅读 · 2019年4月17日
去哪儿网开源DNS管理系统OpenDnsdb
运维帮
21+阅读 · 2019年1月22日
6大最常用的Java机器学习库一览
AI前线
4+阅读 · 2018年10月9日
Python 杠上 Java、C/C++,赢面有几成?
CSDN
6+阅读 · 2018年4月12日
33款可用来抓数据的开源爬虫软件工具 (推荐收藏)
数据科学浅谈
6+阅读 · 2017年7月29日
Spark的误解-不仅Spark是内存计算,Hadoop也是内存计算
Top
微信扫码咨询专知VIP会员