Postgres Pro Standard DBMS旨在比通过PostgreSQL更快地向用户交付产品。 那些尚未包括在PostgreSQL中但在其中可靠的功能,我们包括在Postgres Pro Standard中。 另外,Postgres Pro Standard包括一些我们客户需要的扩展,但在标准PostgreSQL发行版中不可用。
有时在Postgres Pro Standard中有例外,应用户的要求并为他们的满意,它包含了一些琐碎的功能,只有在Postgres Pro Enterprise中这才是好地方。 特别是下面的PTRACK。
不是全部,而是Postgres Professional开发了Standard中包含的其他扩展和实用程序中的相当一部分。 所有Postgres Pro补丁都是由我们自己的努力发明和实施的。 让我们从需要干预数据库引擎的改进开始。
Postgres Pro Standard在两个方面与PostgreSQL不同:程序集中的一组扩展和实用程序,以及内核本身。 一些有用的补丁已被应用到内核,以优化性能(例如,非制动锁检测器),并增加了实用程序和扩展的效率的补丁(例如,为了使pg_probackup充分发挥作用,应用了PTRACK 2.0补丁)。 Standard和PostgreSQL核心版本之间的差异被最小化,以实现最大的兼容性。 假设pg_pathman扩展是Standard的一部分,但可以从github下载,在PostgreSQL上构建和安装,不会有兼容性问题。
让我们从内核中的更改开始。
检查ICU版本
在PostgreSQL中,默认情况下,它们用于通过使用标准C库进行比较来比较字符串,但是也有可能出于相同目的使用IBM开发的
ICU库。 该库对我们来说很有价值,主要是因为它提供了与平台无关的排序。 例如,这就是为什么在1C中使用它,而PostgreSQL“ for one-es”程序集已经使用此库很长时间了。
另外,通过ICU进行的字符串比较有时比通过libc进行的字符串比较快,并且它所知道的字符数也更多。 通常,有用的库。 从第一个版本(9.5)开始,Postgres Pro Standard就开始使用它。 在PostgreSQL中,从版本10开始就可以使用ICU。
该库很有用,但是您需要记住一些紧急情况。 假设DBMS用户已决定升级操作系统。 连同操作系统一起,还可以升级ICU库,并且排序中的单词顺序也会改变。 此后,所有索引将立即变得不可用:索引搜索将给出错误的结果。 在这种情况下,该基地表示ICU的版本已更改并停止。
但这是一个痛苦而艰难的决定。 经过讨论和对客户的调查后,决定软化行为。 现在仅检查COLLATION(排序规则)的版本。 如果数据库中使用的COLLATION版本已更改,则数据库在DBMS启动时会发出警告,但不会停止。 它还会在每个会话开始时提醒用户。
优化锁,联接和GROUP BY
死锁检测机制会降低性能。 Standard不再可用:内核补丁允许它不停机运行。 在对验证机制进行重大改进之后,这些问题仅出现在大量的内核和连接上。
在存在适当索引的情况下,改进对联接结果数量的估计。
现在,您可以使用合适的索引对字段进行分组和排序。 此功能最初包含在Standard 11.1.1和Enterprise 11.2.1中。 我们的标准12也有一个。
Postgres Professional的CTO Fedor Sigaev已向社区提供了这些有用的补丁程序,正在对其进行考虑,并希望将其包含在PG 13版本中。
我们用示例说明GROUP BY操作的优化:它们清晰易懂,并且易于复制。
该补丁的要点是Postgres并未优化GROUP BY中列出的字段的顺序。 执行时间取决于分组的顺序(具有相同的查询结果)。 有关
黑客邮件列表的
讨论中有详细信息。
如果要处理的第一列中的值是唯一的,则无需进行其他比较。 如果从另一列开始,则必须进行比较。
进行测试:
DROP TABLE IF EXISTS btg; SELECT i AS id, i/2 AS p, format('%60s', i%2) AS v INTO btg FROM generate_series(1, 1000000) i;
在文本字段v中,将生成60个空格,后跟数字0或1。条目如下所示:
SELECT * FROM btg ORDER BY id DESC LIMIT 3; id | p | v
VACUUM btg; ANALYSE btg; SET enable_hashagg=off; SET max_parallel_workers= 0; SET max_parallel_workers_per_gather = 0;
将结果分组:
VACUUM btg; EXPLAIN ANALYZE SELECT count(*) FROM btg GROUP BY p, v;
PostgreSQL计划:
QUERY PLAN
现在以相反的顺序:v,然后只有p:
EXPLAIN ANALYZE SELECT count(*) FROM btg GROUP BY v, p; QUERY PLAN
事实证明,相反的情况明显较慢。 这是因为第一字段
v
的值分布很小。 您必须对其余字段(此处-字段p)进行大量检查。
让我们看看同一查询如何与为处理列选择最佳顺序的补丁一起使用:
QUERY PLAN
并以相反的顺序:
QUERY PLAN
该计划说那里和那里的处理顺序是相同的:排序键:p,v。 因此,时间大致相同。 现在比较使用索引时发生的情况。
CREATE INDEX ON btg(p, v); SET enable_seqscan=off; SET enable_bitmapscan=off; VACUUM btg; EXPLAIN ANALYZE SELECT count(*) FROM btg GROUP BY v, p ;
在PostgreSQL中:
QUERY PLAN
并以相反的顺序:
QUERY PLAN
现在处于标准状态:
QUERY PLAN
并以相反的顺序:
QUERY PLAN
时间又是相同的,这很自然:实际上,动作是相同的。
引导时替换空字节
Postgres Pro不接受数据中的零字节(0x00),因此必须使用COPY FROM替换它们,
否则将出现错误 。 这是客户从CSV文件导入数据时遇到的真正问题。 它的解决方案是用给定的ASCII字符替换空字节。 它必须与执行COPY FROM时使用的QUOTE和DELIMITER字符不同。 否则,结果可能是意外的。 默认情况下,变量nul_byte_replacement_on_import(字符串)“ \ 0”的值,即不执行任何替换。
等待LSN
LSN是
日志中的
序列号 ,即,指向WAL中位置的指针(日志序列号)。 WAITLSN命令正在等待播放指定的LSN。 如果应用程序可同时使用主数据库和副本数据库,则需要确保它们不时同步。 WAITLSN是PostgrePro中的一种进程间机制,该机制在
同步复制期间控制同步。 默认情况下,等待时间是无限的。 您可以通过按Ctrl + C或停止postgres服务器来中止等待。 您也可以通过添加TIMEOUT提示来设置超时,或者通过使用NOWAIT提示来检查目标LSN的状态而无需等待。
假设应用程序执行特定操作,从主服务器上的DBMS接收LSN号,现在要确保副本服务器上的操作将与主服务器同步,即 应用程序可以确保它在向导中记录的内容已经到达副本并可以读取。 默认情况下,通常无法保证。 WAITLSN允许您控制此交互,并从默认情况下从INFINITELY到TIMEOUT和NOWAIT选择睡眠模式。
从以前的recovery.conf重新读取变量
在SIGHUP信号上,PostgreSQL重新读取postgresql.conf,但不读取recovery.conf。 标准版和企业版10.4.1中引入了一个相对较新的内核补丁。 被迫重新读取和恢复。 但是在Postgres 12中根本没有recovery.conf文件:来自该文件的所有变量都被传输到postgresql.conf。 但是,尽管重新读取了整个文件,但是SIGHUP并未重新定义来自recovery.conf的变量,而是需要重新启动Postgres。 在Standard中,这不是必需的:读取并重新定义所有内容。
PTRACK支持
PTRACK 2.0是标准和企业版11及更早版本的重新设计的PTRACK机制。 在DBMS级别,由于内核补丁,它可以工作,现在ptrack扩展已添加到
补丁中 。 PTRACK 2.0跟踪数据页更改,并提供检索此信息的界面。 它既可以用于诊断目的,例如,可以了解实例相对于指定时间点的“突变”强度,可以在日志(LSN)中设置为序列号,还可以创建增量备份。
通常,增量备份过程中最困难,最“昂贵”的部分是将已更改页面的子集与集群中整个页面集隔离开。 由于服务器可以执行此任务并快速提供有关已更改页面的信息,因此可以大大减少使用PTRACK进行增量备份的时间。
PTRACK 2.0使用共享内存中指定大小的哈希表,该哈希表与ptrack.map文件定期同步。
由于内部操作机制的根本改变以及与旧版本不兼容的用户界面,ptrack扩展仅在PostgresPro Standard和Enterprise的第12版中可用,并且将在PostgreSQL 12上作为补丁和扩展使用。
在Windows的psql中编辑命令
使用WinEditLine实现了Windows psql中编辑输入命令的高级支持。 现在,您可以同时显示不同字母的字符(尤其是西里尔字母通常显示在非俄语Windows上)。
统一包装结构
所有Linux发行版的二进制软件包的结构都是统一的,以便简化它们之间的迁移,并允许将几种不同的基于PostgreSQL的产品一起安装而不会发生任何冲突。 可以
在文档的
第16章中找到。
现在有关扩展:
dump_stat
它最早出现在9.5。 传输或还原数据时,通常不会传输累积的统计信息。 如果使用ANALYZE命令重新组装它,那么它将对整个集群而不是指定的数据库执行。 对于大型数据库,这可能需要大量额外时间。
dump_stat扩展
提供了允许您卸载和恢复pg_statistic表内容的功能。 在执行数据上载/恢复时,可以使用dump_stat将现有统计信息传输到新服务器,而不必为整个集群运行ANALYZE命令。
dump_statistic函数卸载pg_statistic系统目录的内容。 它为pg_statistic中的每个元组生成一个INSERT,但那些包含有关information_schema和pg_catalog模式中的表的统计信息的元组除外。
jsquery
回想一下,
这是使用JSON(B)而不是JS
的扩展 。 它提供了一组处理这些数据类型的功能。 这是一种特殊的查询语言,可有效地使用索引(JSON)搜索索引(B)。 在中心上的
文章中,您可以看到jsquery的一些示例以及使用JSON(B)的替代方法,例如JSONPath(均为我们公司的开发)。
online_analyze
此扩展
提供了一组函数,可立即更新表中的INSERT,UPDATE,DELETE或SELECT INTO操作后指定的统计信息。 扩展程序的作者是Fedor Sigaev。
要使用online_analyze模块,必须加载共享库:
LOAD 'online_analyze';
可以自定义统计信息更新。 例如,设置表大小的百分比或行更改的最小(阈值)数量,然后将立即收集统计信息。
pg_pathman
Postgres Professional中的
pg_pathman扩展创建于PostgreSQL内核之前,并且实现了相当完整的用于创建分区的功能集。 因此,可以使用一个和另一个机制来完成许多带有节的操作。 仅建议不要混合由声明性分区和pg_pathman创建的部分。
但是,许多pg_pathman操作仍然更快,并且PostgreSQL中缺少一些功能。 例如,自动创建(剪切)节。 在PostgreSQL中,必须定义每个部分的边界。 如果我们填写的数据事先未知,则可以分散多少部分,应该分散多少,那么简单地设置间隔并让软件自己剪切部分就很方便-所需的多。 pg_pathman知道,PostgreSQL不知道。 但是,从PG 11开始,有一个默认部分(默认),您可以在其中转储所有不属于指定边界的部分的所有记录。
与PostgreSQL社区的领导者达成了一项基本协议,即将来最好的pg_pathman的独特功能将落入main分支。 但是在那之前,pg_pathman可以使应用程序数据库管理员和应用程序程序员的生活更加轻松。
创建扩展:
CREATE EXTENSION pg_pathman;
pg_pathman允许您将大表分成多个部分,并提供一个方便的API-一组用于创建部分和使用它们的函数。 例如,使用功能
create_range_partitions(relation REGCLASS, expression TEXT, start_value ANYELEMENT, p_interval INTERVAL, p_count INTEGER DEFAULT NULL, partition_data BOOLEAN DEFAULT TRUE);
我们可以问
SELECT create_range_partitions('log', 'dt', NULL::date, '1 month'::interval);
之后,我们添加以下部分:
SELECT add_range_partition('log', NULL, '2017-01-01'::date, 'log_archive', 'ts0'); SELECT add_range_partition('log', '2017-01-01'::date, '2017-02-01'::date, 'log_1'); SELECT add_range_partition('log', '2017-02-01'::date, '2017-03-01'::date', log_2');
存档日志将在ts0表空间中创建,其余默认情况下为。 但是您不能显式指定节,而是通过设置间隔和一步创建节来信任此DBMS操作:
SELECT create_range_partitions('log', 'dt', '2017-01-01'::date, '1 month'::interval);
在一个简单的表上,它将如下所示:
CREATE TABLE pg_pathmania(id serial, val float); INSERT INTO pg_pathmania(val) SELECT random() * 1000 FROM generate_series(1, 1000); SELECT create_range_partitions('pg_pathmania', 'id', 0, 50); test_parti=# \d+ pg_pathmania Table "public.pg_pathmania" Column | Type | Collation | Nullable | Default | Storage | S tats target | Description
在PostgreSQL中,我们必须与我们自己的团队一起创建每个部分。 当然,在这种情况下,他们编写了一个脚本,该脚本会自动生成所需的DDL代码。 您无需在pg_pathman中编写脚本,所有内容都已经存在。 但这不是最有趣的。 我们将插入一条记录,该记录不仅不会在现有的任何部分中获得ID的认可,而且不会落入最近的一条:
INSERT INTO pg_pathmania(id, val) VALUES (2000, 277.835794724524);
再次,用\ d + pg_pathmania检查表的内容:
Child tables: pg_pathmania_1, pg_pathmania_10, ... pg_pathmania_39, pg_pathmania_4, pg_pathmania_40, pg_pathmania_41,
这是发生的情况:pg_pathman看到id = 2000的记录不属于已经创建的部分,计算了需要创建多少记录,知道了表之前被分区的RANGE间隔,并创建了新记录所在的部分,当然,旧部分的上边界和新部分的下边界之间的所有部分。 这非常方便,并且在更新数据的拆分字段的值预测不佳的情况下,这是pg_pathman的重要优势。
pg_query_state
我们开发的此扩展程序
使我们
能够找出服务过程中请求
的当前状态。 它自9.5版起就存在,并且是由于客户管理员的众多请求而产生的。
事实是,EXPLAIN ANALYZE允许您查看从计划树的每个节点收集的执行统计信息,但是仅在查询完成后才收集这些统计信息。 但是,在生活中,有些情况下您需要查看请求尚未完成并且可能不会结束的情况。 pg_query_state允许您查看在外部服务过程中运行的查询的当前统计信息。 在这种情况下,结果输出的格式几乎与通常的EXPLAIN ANALYZE命令的输出相同。
实用程序:
pgBouncer
这是一个非常
流行的连接器 ,在这里谈论它很奇怪。 只是它是Standard的一部分,对于Vanilla PostgreSQL,必须将其单独安装。
pg_probackup
pg_probackup是我们最受欢迎的开发之一。 这是一个备份和恢复管理器,主要由Anastasia Lubennikova,Grigory Smolkin和用户社区开发和更新。
pg_probackup的竞争优势:具有块粒度(8KB)的增量备份,三种增量备份模式(PAGE,DELTA,PTRACK),按需备份完整性检查,PostgreSQL集群验证,备份压缩,部分恢复等。
PTRACK增量复制模式依赖于重新设计的机制PTRACK 2.0
扩展了相同的名称 ,它已经变得更快,并且无疑是pg_probackup模式中最快,最“便宜”的模式。
pg_repack
pg_repack是一个流行的实用程序,其操作类似于VACUUM FULL或
CLUSTER 。 它不仅可以重新打包表,消除空隙,而且还知道如何恢复聚集索引的物理顺序。 与CLUSTER和VACUUM FULL不同,它可以“随时随地”执行这些操作,而无需排他的表锁定,并且通常可以高效地工作。 它不包含在原始版本中。
pg_variables
关于此扩展
,我们的员工Ivan Frolkov
发表了一篇有趣的
文章 。 扩展的原因是使用中间结果有时会带来不便且昂贵。 本文探讨了替代方法。 其中最常见的是临时表。
作为一个临时数据仓库,pg_variables扩展比临时表(本文中有pgbench测试)要高效得多,并且更方便:数据集由“包-变量”对定义,可以将其作为参数传递,从函数返回等。有用于处理变量的设置/获取功能。 因此,例如,您可以存储许多变量(package是包的名称,小数点后的表达式是该包中的变量:
SELECT pgv_set_int('package','#'||n,n), n FROM generate_series(1,1000000) AS gs(n);
变量具有一个有趣的特性:不是错误或优势,而是一个功能:扩展装置存储的数据存在于事务外部-在修复事务和回滚时都将保存它们; 而且,即使执行单独的命令,也可以获得部分数据:
SELECT pgv_insert('package', 'errs', row(n)) FROM generate_series(1,5) AS gs(n) WHERE 1.0/(n-3)<>0; ERROR: there is a record in the variable "errs" with same key test_parti=# SELECT * FROM pgv_select('package','errs') AS r(i int); i
一方面,这不是很方便-在某些情况下有必要删除不正确输入的数据,但在另一些情况下却可能非常有用-例如即使在事务回滚的情况下也保存一些数据。 该
文档包含详细信息。
总之,还有更多扩展:
sr_plan,plantuner
sr_plan 保存和恢复查询计划。 包括这样:
SET sr_plan.write_mode = true;
之后,所有后续查询的计划将存储在sr_plans表中,直到将此变量设置为false。 保存所有请求(包括重复请求)的计划。
plantuner 支持提示,让调度程序在执行查询时连接或断开指定的索引。 GUC仅有两个变量:enable_index / desable_index:
SET plantuner.disable_index='id_idx2';
全文搜索的扩展名:shared_ispell,pg_tsparser
shared_ispell扩展允许您在共享内存中放置
字典 ,它是Standard而不是PostgreSQL。 我们的hunspell-dict集合包含以下语言的字典:
- hunspell_en_us,
- hunspell_fr,
- hunspell_nl_nl,
- hunspell_ru_ru
pg_tsparser扩展是
替代的文本搜索
分析器 。 此扩展名更改了标准文本解析策略,用于包含下划线以及由下划线分隔的数字和字母的单词。 除了默认返回的单词的各个部分之外,pg_tsparser还返回整个单词。 这对于像这样的技术文档或文章非常重要,在其中可以找到程序代码,并且其中包含诸如“ pg_tsparser”,“ pg_probackup”,“ jsonb_build_object”之类的词。 该解析器不仅将这些单词感知为一组组件,而且还感知为单个标记,从而提高了搜索质量。
1C扩展
- mchar是与Microsoft SQL Server兼容的可选数据类型;
- fulleq-提供附加的等于运算符以与Microsoft SQL Server兼容;
- fasttrun — - , pg_class.
, PostgresPro Standard PostgreSQL. , , , ,
.