我们在运营Postgres 13中学到的东西

2020-09-22 00:58:10

Postgres 13号快要到了。它自5月份以来一直处于测试阶段,正式发布随时都会到来。我们一直密切关注Postgres 13在pganalyze上的情况,并且已经在我们的一个试运行环境中运行了测试版好几个月了。

Postgres13没有大的新特性,但有很多小而重要的渐进式改进。让我们来看看吧。

Postgres 13的性能改进包括内置的优化和启发式方法,它们将使您的数据库开箱即可运行得更好,还包括一些附加功能,使您在优化模式和查询时具有更大的灵活性。

DEVIDATE_ITEMS=OFF DEVIDATE_ITEMS=ON(Postgres 13中的新功能)Postgres 13为B-Tree索引引入了一种方法,以避免在某些情况下存储重复条目。通常,B-Tree索引由索引值的树组成,每个叶节点指向特定的行版本。因为每个叶指向一个行版本,所以如果要索引非唯一值,则需要重复这些值。

重复数据删除机制通过让一个叶节点尽可能指向多个行版本来避免这种情况,这会导致较小的索引。

下面是我们自己的pgAnalyze应用程序模式中的一个示例:我们有一个查询表来跟踪我们监视的所有查询,还有一个database_id字段来跟踪它们属于哪个数据库。Weindex database_id(这样我们就可以快速获取特定数据库的查询),并且因为每个数据库通常都有多个查询,所以这个索引中有很多重复项。

默认情况下,Postgres 13中的新B-Tree索引使用重复数据删除功能,但如果由于某些原因需要将其关闭,您可以使用DEVIDATE_ITEMS存储参数进行控制。在这里,我们以两种不同的方式创建相同的索引,明确启用和禁用重复数据消除(不过,您不需要指定启用-这是默认设置):

CREATE INDEX QUERIONS_db_id_idx_no_dedup on query(Database_Id)with(DEDPLATE_ITEMS=OFF);CREATE INDEX QUERIONS_db_id_idx_yes_dedup on query(database_id=on);SELECT RENAME,PG_SIZE_PRYTY(PG_RELATION_SIZE(OID))FROM PG_CLASE WHERE RENAME IN(';queries_db_id_idx_no_dedup';,';(';query_db_id_idx_no_dedup';,';Query_db_id_idx_yes_dedup';);

使用重复数据删除后,新索引小了三倍多!较小的索引从磁盘加载的速度更快,占用的内存空间也更少,这意味着有更多的空间来存放您的数据。

这里一个有趣的注意是,索引项指向行版本(如在中,行在一个特定MVCC状态中的存在方式),而不是行本身,因此此功能可以改进索引大小,即使对于唯一索引也是如此,在这种情况下不会发生任何复制。

请注意,并非所有情况下都可以进行重复数据消除(有关详细信息,请参阅上面的链接),如果通过pg_upgrade升级,您需要重新编制索引才能利用它。

Postgres 10引入了扩展统计的概念。Postgres保留了一些关于数据形状的统计信息,以确保它可以有效地计划查询,但是默认情况下保存的统计信息不能跟踪列间依赖关系之类的事情。引入扩展统计信息是为了解决这个问题:这些是数据库对象(如索引),您可以使用CREATE STATISTICS手动创建这些对象,以便为查询规划者提供更多有关更具体情况的信息。对于Postgres来说,自动确定这些内容的代价很高,但是了解了您的模式的语义之后,您就可以提供额外的信息了。如果使用得当,这可以带来巨大的性能提升。

Postgres 13对扩展统计进行了一些小但重要的改进,包括支持将它们与OR子句和IN/ANY常量列表一起使用,允许在计划查询时考虑多个扩展统计对象,以及支持设置扩展统计的统计目标:

与常规统计目标一样,这是额外的计划时间(和更长的分析运行时间)与更精确的计划之间的权衡。我们建议以有针对性的方式使用它,使用解释计划来确认计划更改。

Postgres多版本并发控制意味着您需要定期运行Vacuum(通常您可以依赖于自动Vacuum进程,尽管它可能需要一些调整)。在Postgres 13中,一个显著的改进是可以并行清理单个表的多个索引。这可以大大提高真空作业的性能。平行真空是默认真空,可以使用并行选项进行控制:

信息:正在清空#34;public.queries";信息:已启动2个并行真空工作器进行索引清空(计划:2)信息:已扫描的索引";index_query_on_database_id";删除并行真空工作器的1403418个行版本详细信息:cpu:用户:0.98s,系统:0.15s,已用时间:2.37sinfo:扫描的索引";index_queries_on_last_occurred_at";要通过并行真空工作器删除1403418行版本详细信息:cpu:用户:0.88s,系统:0.27s,已用时间:2.60s...

有足够的并行工作线程可用,这取决于max_parallel_maintenance_worker设置的系统范围限制(缺省值为2)。

表上有多个索引(一次只能由一个工作进程处理一个索引)。

请注意,自动真空目前不支持平行真空。此新功能旨在用于需要快速完成的手动真空运行,例如,当自动真空调谐不足导致即将发生TXID环回时,您需要进行干预以修复该问题。

在这一点上,Postgres 13中的一个重要的自动真空改进是,自动真空后台进程现在可以由只追加表的INSERT语句触发。Vacuum的主要用途是清理已更新和已删除行的旧版本,但也必须将页面设置为MVCC簿记全部可见。全可见页面允许仅对索引进行扫描,以避免逐行检查可见性状态,从而提高速度。

对于我们的TimeSeries数据,我们在pgAnalyze中广泛使用了仅附加的表,这一改进将使我们的工作变得非常容易,避免了偶尔对这些表进行手动真空操作。此新行为可由AUTOVUIUS_VACUUM_INSERT_THRESHOLD和AUTOVUAUM_VACUUM_INSERT。

对数据进行排序是一项常见的数据库任务,Postgres有许多特性可以避免这里不必要的工作。例如,如果您在一列上有一个B-Tree索引,并且您查询按该列排序的表,则它只需扫描该索引即可获得排序的数据。

在Postgres 13中,对此进行了改进,以处理部分排序的数据。如果您有一个关于(a,b)的索引(或者由于其他原因,数据已经按(a,b)排序),并且您发出一个按(a,b,c)排序的查询,Postgres会认为输入数据已经部分排序,可以避免对整个数据集进行重新排序。如果您的查询有限制,这尤其有用,因为这样可以避免更多的工作。

Postgres13中的监控改进包括更多关于WAL使用的详细信息,更多用于记录您的查询的选项,以及更多关于查询规划的信息。

预写日志(WAL)可确保您的数据在崩溃时保持一致,即使在写入过程中也是如此。一致性是数据库的一个基本属性-它确保您的事务要么已提交,要么未提交;您不必担心中间状态。但在繁忙的系统上,WAL写入通常会成为瓶颈。为了帮助诊断这一问题,Postgres 13包含了有关您查询的WAL使用情况的更多信息。

查询计划-删除用户。(成本=100000..5409.00行=100000宽度=6)(实际时间=108.910..108.911行=0循环=1)WAL:记录=100000 fpi=741字节=11425721->;用户序列扫描(成本=0.00..5409.00行=100000宽度=6)(实际时间=8.519..51.850行=100000循环=1)计划时间:6.083毫秒执行时间:108.955毫秒(5行)。

您可以看到WAL行包括生成的记录数、整页图像(FPI)数和生成的WAL字节数。只有非零值才以默认文本格式打印。

这在pg_stat_Statements中也可用。例如,在我们的暂存环境中,我们运行以下命令来获取生成最多WAL记录的语句:

-[Record 1]-query|创建临时表upsert_data(服务器id uuid不为空,后端id uuid不为空,|查询开始时间戳不为空,QUERY_FRAPHING BY TEA NOT NULL,QUERY_TEXT NOT NULL)调用|7974948wal_Records|966960816wal_fpi|1018412wal_bytes|100086092097。

与PG_STAT_STATEMENTS中的许多其他值一样,此处的WAL_RECORDS、WAL_FPI和WAL_BYTES值是自上次PG_STAT_STATEMENTS_RESET调用以来累计的。

此信息可以帮助您识别编写繁重的查询,并根据需要进行优化。请注意,写入繁重的查询也会影响复制:如果您看到复制延迟,您可以使用这些新功能来更好地了解是哪些语句导致了复制延迟。

LOG_MIN_DURATION_STATEMENT这样的设置可以帮助您理解慢查询,但是慢到什么程度才算慢呢?与在Web请求上下文中运行的5S查询相比,夜间运行的报告查询是否较慢?与在加载主页时运行20次的100ms查询相比,在一个很少使用的端点上运行一次的5s查询慢吗?

到目前为止,LOG_MIN_DATION_STATEMENT对于所有这些情况都是一种迟钝的工具,但是Postgres 13为基于采样的语句日志记录带来了一定的灵活性。可以设置LOG_MIN_Duration_SAMPLE以启用采样,然后设置LOG_STATEMENT_SAMPLE_RATE或LOG_TRANSACTION_SAMPLE_RATE来控制采样。

这两个设置的工作方式相似:它们的范围从0到1,并确定随机选择语句进行记录的可能性。前者适用于单个语句,后者确定事务中所有语句的日志记录。如果同时设置LOG_MIN_DATION_STATEMENT和LOG_MIN_DATION_SAMPLE,则前者应该是记录所有内容的较高阈值,而后者可以是较低的阈值,仅偶尔记录。

语句日志记录的另一个重大改进是能够使用log_Parameter_max_length_on_error记录失败语句的参数。下面是将其设置为-1(无限制)并尝试在语句_超时为1秒的连接上运行SELECT PG_SLEEP($1)(参数$1设置为3)的示例:

2020-09-17 12:23:03.161 pdt[321349]maciek@maciek错误:由于语句超时取消语句2020-09-17 12:23:03.161 pdt[321349]maciek@maciek上下文:带参数的扩展查询:$1=';3';2020-09-17 12:23:03.161 pdt[321349]maciek@maciek语句:SELECT PG_SLEEP($1)。

超时情况特别有用:由于查询文本和参数现在都在日志中可用,您可以对任何失败的查询运行EXPLAIN,以找出导致DIT达到超时的查询计划(注意:不能保证您会得到与失败的计划相同的计划,但根据您的工作负载,可能性很大)。

慢查询的罪魁祸首通常是查询执行本身,但是对于复杂的模式和复杂的查询,规划也可能需要大量的时间。Postgres 13引入了两个新变化,使关注规划变得更容易:

首先,要解释的Buffers选项为您提供了有关查询计划期间内存使用情况的更多信息。Postgres使用缓冲池管理数据和索引的内存,而Buffers选项可以显示查询的哪些部分正在使用该内存以及如何使用该内存。解释文档有更多详细信息。Newin Postgres 13能够查看在查询规划期间如何使用缓冲区:

PG_-上的查询计划类别序列扫描(开销=0.00..16。.86行=386Width=265)(实际时间=0.014..0.120行=390循环=1)缓冲区:共享命中=13规划时间:1.021毫秒缓冲区:共享命中=118执行时间:0.316毫秒(5行)

-[Record 1]----+----query|SELECT QUERY,PLAN,TOTAL_PLAN_TIME,+|MIN_PLAN_TIME,MAX_PLAN_TIME,Mean_PLAN_TIME,Stddev_plan_time+|from pg_stat_Statements where queryId=$1plan|1total_plan_time|0.083102min_plan_time|0.083102max_plan_time|0.083102均值_plan_time|0.083102stddev_plan_time|0。

由于某些工作负载的性能开销,这在默认情况下是关闭的,但是如果您怀疑计划时间是一个问题,那么它绝对值得一试。有关性能回归的更多详细信息,请参阅此邮件列表讨论;预计将来会解决此问题,默认设置可能会更改。

Postgres13的可用性改进包括更好的文档、更好的内置UUID支持和一些方便的psql增强。

任何复杂的系统都会发展出自己的行话,Postgres也不例外。有些来自一般的数据库字段,有些是Postgres特定的。有专门的语言来准确地谈论具体的技术概念是非常有用的,但它可能会让新手感到困惑。

按固定顺序的属性集合。该顺序可以由包含元组的表(或其他关系)来定义,在这种情况下,元组通常被称为行。它也可以由结果集的结构定义,在这种情况下,它有时被称为记录。-PostgreSQL Glossary。

你可能熟悉上面的术语,但是如果你曾经遇到过一些你不清楚的东西,这些术语和其他许多术语现在都被记录在一个新的词汇表中。现在已经有了一个固定的地方可以这样做,我们可以期待将来在这里添加其他的技术术语。

如果您在系统中使用UUID(您应该考虑一下--它们非常方便),那么您可能非常熟悉UUID-OSSP扩展。基本的UUID类型是内置的,但默认情况下,没有自动生成新类型的简单机制。UUID-OSSP扩展随Postgres一起提供,但必须显式启用才能创建UUID生成函数,如常见的UUID_GENERATE_v4。

Postgres 13附带了gen_Random_uuid函数,该函数等同于uuid_GENERATE_v4,但默认情况下可用。如果该函数仅使用UUID-OSSP,则不再需要扩展名:

=>;\dx已安装扩展的列表名称|版本|架构|Description-+-(0行)=>;SELECT GEN_RANDOM_uuid();gen_random_uuid--07b45dae-e92e-4f91-8661-5fc0ef947d03(1行)。

Postgres 13中有许多小的psql改进。我最喜欢的是,在当前查询缓冲区上调用$EDITOR的命令\e现在将在您保存并退出时显示查询文本(除非您以分号或\g结尾直接提交查询文本)。以前,查询文本已保存,但处于隐藏状态。将打开编辑器与在psql 11中保存SELECT 1进行比较:

Postgres 13还包括定制psql提示符的其他方式。您可以一如既往地使用\set(通常在.psqlrc中)执行此操作,但有几个新的替代选项可用:

%x将显示当前事务的状态:noTransaction的空字符串,*在打开的事务中时,!当处于失败的事务中时,或者?当事务状态未知时(通常在没有连接到服务器时)。

%w会将PROMPT2(在需要更多输入时使用)填充为与PROMPT1相同的宽度,以保持整齐对齐。

还有其他一些小的改进。而且这些都是客户端的更改,所以如果您在旧服务器上使用新的psql,它们也会起作用!

这些只是Postgres 13带来的众多小改进中的一小部分。还有许多其他改进,比如部分toast解压缩、可信扩展(这样您无需成为超级用户就可以启用它们)、PL/pgSQL性能改进,等等。您可以在Postgres网站上查看完整的发行说明。

我们对此次发布感到非常兴奋。我们已经在pgAnalyze中支持监控Postgres 13,并且已经在努力将新的监控功能直接集成到产品中,以便让您更好地洞察您的数据库。

分享这篇文章:如果你喜欢这篇文章,你可能想把它转发给你的同龄人。

很少收到关于网络上有趣的postgres内容、新的pganalyze功能版本和新的pganalyze电子书的电子邮件。我们保证不会有垃圾邮件。