我正在设计一个并发安全的增量聚合汇总系统,track_commit_timestamp (pg_xact_commit_timestamp) 听起来很完美。但是我发现很少有关于它的评论,并且无法从源代码中弄清楚它是如何工作的。
希望有人知道我的一个或多个问题的答案:
提交时间戳功能是否有可能产生乱序时间?我所追求的是一种识别自特定时间以来已更改的记录的方法,以便我可以获取任何以后的更改以进行处理。如果有相同的时间戳,我不需要它们以完美的提交顺序。
最终实现中每行添加多少字节?我看到的讨论似乎在 12-24 个字节之间。曾讨论过为“以防万一”添加额外字节。这是 9.5 之前的版本,所以是一个世界之前的版本。
时间戳是否在内部编入索引?用 B 树?我询问容量规划的原因。
我在 StackOverflow 和设计讨论中看到时间戳不是无限期保留的,但无法找到它们存储时间的详细信息。
关于启用 track_commit_timestamp 的性能影响的任何经验法则?我不需要所有表上的数据,但是,在我需要的地方,听起来它可能工作得很好。
有什么问题吗?我尝试在测试表上运行 VACUUM FULL 并且 pg_xact_commit_timestamp 都没有改变。看起来像 VACUUM 这样的物理操作不应该改变任何东西,但很容易有一些我没有想到的东西。而且,老实说,我的快速 VACUUM 测试甚至可能没有任何意义。
非常感谢您的帮助!
我编辑了我的问题以阐明我要完成的任务,我希望根据更新标记跟踪已处理和未处理的数据。
select max(pg_xact_commit_timestamp(xmin)) from scan;-- 2019-07-07 20:46:14.694288+10
update scan set quantity = 5 where quantity = 1; -- Change some data.
select max(pg_xact_commit_timestamp(xmin)) from scan; -- 2019-07-10 09:38:17.920294+10
-- Find the changed row(s):
select *
from scan
where pg_xact_commit_timestamp(xmin) > '2019-07-07 20:46:14.694288+10';
Run Code Online (Sandbox Code Playgroud)
这个想法是对行进行增量和定期汇总。所以,
-- 跟踪上次汇总的时间戳。-- 等待 5 分钟(或其他时间)。 -- 查找当前的最大提交时间戳。-- …
我对tsvector字段(重新)感到困惑。这是很常见的,看文字的例子被连接成的tsvector字段,然后索引。如果您查找 PG 12 生成的列,您会发现快速显示tsvector字段填充的示例。
既然这个字段的唯一目的就是支持索引,那为什么不用表达式构建索引,跳过向量列呢?我之前顺便问过这个问题(找不到),记得听到回复“这个专栏毫无意义”。这对我来说很有意义。最近,我一直在关注这篇文章的一些评论:
这件作品相当不错,顺便说一句。有这样的评论:
实现 tsvector 的一个原因是不在重新检查时评估表达式,这本身可能非常昂贵。
在解释分析中勾选'Recheck Cond',条件可以被真正检查,因此条件(to_tsvector)将被计算。
\d t1
Table “public.t1”
Column | Type | Collation | Nullable | Default
--–----+---------+----------–+----------+---
id | integer | | |
t | text | | |
Indexes:
"t1_to_tsvector_idx" gin (to_tsvector('english'::regconfig, t))
explain analyze select * from t1 where to_tsvector(‘english’, t) @@ to_tsquery(‘english’,’foo’);
Run Code Online (Sandbox Code Playgroud)
\d t1
Table “public.t1”
Column | Type | Collation | Nullable | Default
--–----+---------+----------–+----------+---
id …Run Code Online (Sandbox Code Playgroud) Postgres 11.7。
我正在尝试解压一个数组,其中每个项目都有多个元素,并且似乎无法获得正确的语法。我希望有人能指出我所缺少的东西。这是一个例子:
select
unnest(array[
('Red Large Special', 1),
('Blue Small', 5),
('Green Medium Special', 87)
]) as item_list
Run Code Online (Sandbox Code Playgroud)
这就是我要的:
item_name item_id
Red Large Special 1
Blue Small 5
Green Medium Special 87
Run Code Online (Sandbox Code Playgroud)
这就是我得到的:
base_strings
("Red Large Special",1)
("Blue Small",5)
("Green Medium Special",87)
Run Code Online (Sandbox Code Playgroud)
我相信我需要一个列规格列表,如下所示:
select * from
unnest(array[
('Red Large Special', 1),
('Blue Small', 5),
('Green Medium Special', 87)
]) AS item_list(item_name citext, item_id int4)
Run Code Online (Sandbox Code Playgroud)
我得到的是:
ERROR: function return row and query-specified return row do not match
DETAIL: Returned type …Run Code Online (Sandbox Code Playgroud) 我被要求将大量数据复制到 Postgres 的新表中。数据包含装配组件列表,在下面的表定义中进行了简化:
CREATE TABLE IF NOT EXISTS assembly_item (
id uuid NOT NULL DEFAULT NULL,
assembly_id. uuid. NOT NULL DEFAULT NULL,
done_dts timestamp NOT NULL DEFAULT 'epoch',
CONSTRAINT assembly_item_pk
PRIMARY KEY (id)
);
Run Code Online (Sandbox Code Playgroud)
原来有几十个属性,现在有几亿行。这些记录分布在多个安装中,并且不存储在本地 Postgres 中。据猜测,该表上的插入量会快速增加,一年内将增长到 1B 行。日期很少更新,也从不删除。(它可能会及时发生,但不会经常发生。)相同的情况永远不会id用不同的值重复。因此,在分区级别上唯一是安全的。这里的目标是将这些数据卸载到 Postgres 上,并仅将最近的数据保留在本地服务器的缓存中。assembly_idid
这看起来像是分区的自然候选者,我正在寻找一些有关合理策略的指导。您可以从简化的结构中看到,我们有一个唯一的 row id、一个parentassembly_id和一个时间戳。我查看了原始数据库中的现有查询,主要搜索字段是assembly_id父记录标识符。assembly和之间的基数assembly_item约为 1:200。
为了使分区最有用,似乎需要根据一个值来分割数据,该值使查询规划器能够智能地修剪分区。我已经想到了一些想法,但还没有 200M 行来再次测试。与此同时,我正在考虑的是:
RANGE使用或LIST按YYYY-MM的进行按月分区done_dts。按日期范围重写所有查询。
HASH根据 的前两个字符进行分区assembly_id::text,得到 256 个大小相当相等的分区。我认为这可以让我们搜索assembly_id并删除许多不匹配的分区,但当我设置它时,它看起来很奇怪。 …