Postgres性能的费米估计

2020-08-17 08:58:20

如果你想了解更多关于Microsoft Azure上的CATUS,请阅读这篇关于Azure Database for PostgreSQL上的Hyperscale(CATUS)的文章。

跳过导航许多人期待CITUTS提供一种解决方案,将他们的Postgres数据库横向扩展,无论是本地的、开源的还是云中的,都可以将其作为完全托管的数据库作为服务。然而,甚至在研究西图斯之前,一个常见的问题就是:“我能在波斯格雷斯身上获得什么样的表现?”答案是:这要视情况而定。单节点Postgres的性能归根结底取决于您的工作负载,包括插入和查询方面的工作负载,以及该单节点的大小。不幸的是,“视情况而定”往往会让人有点不满。

幸运的是,对于单节点Postgres可以提供什么样的性能,有一些费米估计,或者用外行术语大致估计。这些粗略估计都适用于单节点Postgres,但从那里您可以开始估计在使用CATUS向外扩展时还能走多远。让我们演练一个简化的指南,了解Postgres中查询的读取性能和摄取性能方面的预期。

首先要注意的是,当从内存而不是从磁盘提供数据时,查询速度将提高几个数量级。幸运的是,Postgres将非常高效地将频繁访问的数据保存在内存中。更好的是,您可以轻松地跟踪从缓存(而不是从磁盘)提供查询的频率。

选。

SUM(HEAP_BLKS_READ)AS HEAP_READ,

SUM(HEAP_BLKS_HIT)AS HEAP_HIT,

SUM(HEAP_BLKS_HIT)/(SUM(HEAP_BLKS_HIT)+SUM(HEAP_BLKS_READ))的比率

从…。

PG_STATIO_USER_TABLES;

通常,您的目标应该是缓存命中率达到99%或更高,除非您正在处理数据仓库/BI类型的工作负载,然后情况发生了一些变化。相反,一旦您必须转到磁盘,情况就会变得慢得多,尽管这都会因磁盘性能的不同而有所不同。举一个I/O带宽为100MB/s的示例(不是很惊人,但足够合理),假设行大小为100字节,您将能够每秒扫描大约1,000,000行。

仅仅因为您有很高的缓存命中率,并不意味着您不会编写不好的查询,这些查询确实会不断命中内存,但性能很差。但是高速缓存命中率是一个很好的起点,糟糕的高速缓存命中率几乎可以立即为您指明正确的方向。

因此,在上面的示例硬件上,您可以说在1秒内扫描一百万条记录。Postgres的美妙之处在于,当您查询数据时,它并不总是扫描数据库中的所有数据,它更多地取决于您正在执行的操作类型。

在Postgres中,您能够通过的行数取决于您正在执行的操作。如果您有一个目标索引,并且正在检索单个记录或几组记录,那么期望它在毫秒内返回是合理的。当聚合数据时,或者如果您要从一些较大的数据集中进行筛选并返回几条记录,事情就会变得有点复杂。

如果您只是简单地过滤数据,并且数据可以放在内存中,Postgres每秒能够解析大约500-1000万行(假设某个合理的行大小为100字节)。如果您在聚合,那么您的速度大约是每秒100-200万行。所有这一切并不是说您不能在比方说10秒内聚合1亿行,但是为了做到这一点,您需要一定程度的并行性,因为这些数字是以每个内核为基础的。

正确的索引和调优都可以帮助您在读取端做些什么,但上面的内容应该会给您提供一个预期的起点。现在让我们转到数据摄取。

有几个因素会影响Postgres中的写入性能。决定您可以达到的吞吐量的一个重要因素是您是在查看单行插入还是使用Copy进行批量加载。

对于单行插入,如果您的应用程序使用单线程,瓶颈主要是网络延迟。对于您发送到数据库的每一次写入,写入都必须从您的应用程序转到数据库,并且数据库的写入确认必须返回到您的应用程序。因此,如果您的应用程序和数据库位于不同的区域,例如延迟为5ms,那么您预计每秒将看到大约100个插入(1000毫秒/(5ms+5ms))。在AWS上的同一区域,假设延迟为1ms,这个数字可能会上升到每秒约500次插入。

提示:对于大多数应用程序,通常建议使用能够同时服务多个请求的生产Web服务器。

一旦您有多个线程/进程为请求提供服务,那么您可以预期写入吞吐量会随着您所在的硬件的扩展而增加。在较小的AWS实例(例如r4.xLarge/r4.2xLarge)上,这个数字可能以个位数千为单位,而对于较大的实例,这个数字可能会增加到几十几千。确切的数字取决于每行的大小、数据类型以及是否有索引。

拥有更多索引可以让您拥有更好的读取性能,但会给写入端带来负担。例如,如果在没有索引的情况下,单个INSERT语句在数据库端的执行时间为0.1ms,则添加索引可能会使该时间增加一个数量级。此外,随着表和索引大小的增加,对写入性能的影响也会增加。因此,请注意故意创建索引,以保持最佳写入性能。

数据库中有索引,但不确定它们是否正在使用?此查询将报告前几位未使用的索引:

选。

Schemaname||';.';||重命名为表,

Indexrelname作为索引,

PG_SIZE_Pretty(PG_Relationship_Size(i.。INDEX_RELID))作为INDEX_SIZE,

IDX_SCAN作为INDEX_SCANES。

从PG_STAT_USER_INDEX UI。

在UI上加入PG_INDEX I。Indexrelid=i。索引对象。

WHERE NOT INDIQUIZE AND IDX_SCAN<;50和PG_Relationship_Size(REID)>;5*8192。

按PG关系大小排序(i.。IndexRelid)/NULLIF(IDX_SCAN,0)DESC NULL First,

PG关系大小(i.。Indexrelid)DESC;

在更新和删除方面,如果您有正确的索引,您可以预期更新和删除吞吐量与插入吞吐量大致相同(尽管略低)。定向更新和删除的一个重要因素是在具有UPDATE条件的列上具有索引。如果没有这样的索引,那么每次更新都必须扫描整个表,这会大大降低速度:(。

许多应用程序通常需要超过每秒10,000次写入。我们发现这在实时分析领域尤其常见。这里的实时可能落后几秒或几分钟,但本质上是人类的实时。但是,数据摄取可能有更高的要求。在使用Postgres时,如果您确实需要每秒超过10,000秒的插入写入,我们会求助于Postgres复制实用程序进行批量加载。

Copy能够处理每秒100,000秒的写入。即使没有持续的高写入吞吐量,拷贝也可以方便地快速摄取非常大的数据集。要每秒接收100,000个写入,您不必创建这种大小的批,而实际上可以通过微批处理(比方说每几千个组)加载小得多的批。

提示:索引对接收性能有相当高的影响。在使用COPY加载大量数据时,通常首先加载数据,然后从接收性能的角度创建索引。

因为西图斯是Postgres的延伸,我们站在Postgres的肩膀上,利用那里存在的所有令人敬畏的基础。这意味着Postgres在一秒钟内聚合每个核心200万条记录的能力适用于CITUS,但是由于我们的水平规模,您可以预期集群中的每个核心会有200万条记录。

类似地,对于写入,一次写入可能需要1ms,但是由于CUTUS允许您在幕后拥有多个Postgres实例来执行写入,所以您可以开始以同样的方式向外扩展写入。在没有使用拷贝的情况下,我们看到CUTUS MX扩展到每秒超过500,000个插入,而当利用拷贝时,这个数字可能会超过每秒500万次写入。

想了解更多关于我们可以促进的规模的信息吗?请查看Heap的CTO Dan Robinson关于他们如何利用CUTUS对超过50 TB的数据执行实时分析的演讲:

Postgres不仅是先进的,而且也可以表现得相当好。因此,不要认为一个已经存在了20年的陈旧数据库不能处理您的工作负载。是的,Postgres的性能确实取决于底层的硬件,但Postgres的整体性能在以下方面表现出色:

单行插入主要与往返网络延迟相关,当与并发Web服务器一起运行时,在单节点数据库上最多可插入10,000个单行或更多单行。

当然,如果您需要将Postgres性能的界限扩展到单个节点之外,那么您可以指望CUTUS来扩展您的Postgres数据库。如果您确实发现自己担心扩展或在单节点Postgres上遇到限制,无论是从读取还是从吞吐量的角度来看,请让我们知道,我们很乐意帮助您确定CUTUS是否适合您和您的SaaS应用程序。