Postgres和MySQL引擎的区别

59 阅读5分钟

几十年来,数据库在存储和检索信息方面一直很受欢迎,它们为处理各种形状和大小的数据提供了方法,而且不需要专门进行任何形式的检索或功能。在过去的十年中,出现了一种分析型数据库,它利用了这样一个事实,即一些数据,主要是报告和分析中的数据,只需写一次就可以读很多次。更新并不频繁,所以单个行的查找也不频繁。这些引擎与我们在Postgres或MySQL中的引擎有什么不同?有几个概念需要展开。

行和列

为了支持异质的工作负载和严格的保证(ACIDMVCC和其他),数据库通常将某一行的所有数据存储在一个块中。一个名字和年龄的表格,以一种严重简化的方式,被存储为joe,20;jane,24;doug,30;lynn,21 ,这可以正常工作,但 "问题 "是,当我们想查询联系人列表中所有人的平均年龄时,我们需要同时读取所有的名字。这在这个表中不是一个问题,但是想象一下有100个列的宽表(在生产环境中并不罕见)。你突然读到了比你需要的多得多的数据。

一种缓解方法是使用索引。它们的效果很好,但在分析中却带来了一些问题。1)重复存储,2)所有的表操作都更加昂贵,因为你需要保持索引的同步,3)理想情况下,你会为每一列都有一个索引,因为你往往不知道你会查询哪些列,从而扩大了问题一和问题二。

这就是列存储的作用。它们不是按行存储数据,而是把列的信息放在一起,所以我们上面的例子会产生joe,jane,doug,lynn;20,24,30,21 ,所以查询平均年龄或我们是否知道任何Dougs的问题会比在行存储中快很多。相比之下,在列存储中查找道格的所有信息会相当慢,因为你需要在n ,查找n 列。你知道,权衡利弊。

引擎和存储

虽然我们认为数据库是同质的、一站式的商店,但它们或多或少都有一些模块化的部分。这里的关键部分是存储系统。例如,MySQL在历史上的存储引擎是可以互换的,这就是为什么多年来它有很多实现方式。

Postgres用户解决这个问题的方式也不尽相同。要么建立新的扩展。想想CitusTimescaleDB这些允许在某种程度上对功能进行本地改进,但它们不与Postgres一起运送,它们不是一等公民,它们通常不被托管解决方案支持(如Amazon RDS),它们需要与上游Postgres保持同步以保持兼容。另一个选择是硬分叉,其中比较明显的是亚马逊Redshift,亚马逊的数据仓库解决方案,它从Postgres 8的分叉开始,一直过着自己的生活。Postgres的新功能没有被纳入,更重要的是,这种列式存储的整个设计牺牲了一些围绕完整性和表设计的功能(例如,你不能即时改变列类型,这和它的声音一样令人沮丧)。

Postgres在历史上采取了这种与MySQL不同的路径,它一直将Postgres存储系统作为维护数据的唯一方式,也就是说,直到去年春天(2019年),当可插拔存储得到承诺

现在这一变化引发了人们对新的存储引擎的兴趣,例如zheap。但我想简单谈一下的是zedstore

Zedstore最终作为一个列存储的一流实现,具有Postgres目前提供的所有保证和API,无论是MVCC、ACID、事务性DDL等。如果你喜欢在本地运行或测试数据库,我鼓励你试试这个。我从来没有自己建立过Postgres,但事实证明这很简单。

首先克隆上面链接的 repo,使用README中指出的推荐选项进行配置,然后按照上游安装文档进行安装。如果你已经在运行Postgres,确保编辑这个zedstore分支所使用的端口(我使用5433)。然后创建一个数据库,初始化它,在新的端口上针对这个新的数据库运行你的新构建。

我在当时运行的一个真实的工作负载中测试了zedstore,它是一个相当完整的表扫描重型查询集,是一个列存储的理想工作负载。在大多数聚合和过滤查询中,我得到了3-10倍的速度提升。在某些情况下,我得到了缓慢的速度,这在运行昂贵的计算时尤其明显,如count(distinct)

总结

在Postgres中内置列存储的主要优点是可以很容易地运行混合工作负载,其中你有基于行的OLTP类表用于日常操作,然后有一些列存储表/视图用于分析和报告。这种方法为你省去了在数据库之间同步数据的麻烦,这已经是我们不得不忍受的一种痛苦了。这是微软的SQL Server在相当长一段时间内提供的东西,我很高兴开源数据库正在迎头赶上。

我认为消除ETL过程的潜力是所有这些的主要好处,但还有一些其他的考虑,我还没有谈及特别是由于磁盘压缩而节省的空间,以及其他一些东西。