将表打包以将时间戳更新为时间戳

问题描述 投票:1回答:1

简短版

  • Postgres 11.4部署在RDS上。
  • 是否有内置或直接的方法可以拆分表中的行以进行批处理更新?
  • 一旦有了存储桶方案,如何在SQL中运行循环以处理每个存储桶,并稍作暂停以使服务器喘口气?
  • 甚至有必要分批处理工作,还是我没有充分的理由担心?

详细版本:

我们已经收集了一段时间,并使用timestamptz字段。我弄错了,应该使用时间戳。我们要做的是从不同的位置收集大量数据,然后自己计算UTC,然后再将数据推送到Postgres。据我了解,时间戳和时间戳数据两者都是相同的8个字节,时间戳为您提供了神奇(且不可见)的AT TIME ZONE转换。意思是,数据没有什么不同,这就是Postgres处理不同数据的方式。在我们的案例中,这意味着我们正在通过将数据作为UTC推送到Postgres中,然后再次将其拉出到本地来搞砸。我们服务器的数据没有一个时区,这就是为什么我们像Postgres在内部将其设置为UTC的原因。为了使报告更简单,分析表通常具有一个用于local_dts和utc_dts的冗余列。这样,我们可以运行报告,比较不同时区中不同设施的“ 8月11日星期一早上”。不同的设施具有不同的时区,因此我们使用“本地”值,即此类查询的本地值。但是,如果我们需要统一的时间表,则可以使用UTC。简而言之:同一张表中的行可能来自具有不同时区的源。[好吧,那是背景,现在我要更新的行数达千万。结构修改看起来很简单:

-- Change the data type, this is instantaneous. ALTER TABLE assembly ALTER COLUMN created_dts SET DATA TYPE timestamp; -- Reset the default, it's probably not necessary, but the ::timestamptz is misleading/confusing here otherwise. ALTER TABLE assembly ALTER COLUMN created_dts SET DEFAULT '-infinity'::timestamp

我必须删除并重新创建一些视图,但这仅是运行一些备份脚本的问题。

我的问题是如何在不拖拽服务器的情况下有效地进行更新?我正在想象一次按5K行进行批处理等。为了简单起见,假设我们所有的服务器都设置为“美国/中央”。当我们最初将数据作为UTC推送时,它又由Postgres转换,因此现在数据由于服务器时间和UTC之间的偏移而消失了。 (我认为。)如果是这样,最简单的更新可能如下所示:

SET TIME ZONE 'UTC'; -- Tell Postgres we're in UTC to line up the data with the UTC clock it's set to. UPDATE analytic_scan SET created_dts = created_dts at time zone 'US/Central' -- Tell Postgres to convert the value back to where we started.

这似乎可行(?),但忽略了处理夏时制的明显遗漏。我可以添加WHERE子句来处理该问题,但这不会改变我的问题。现在的问题是,我的记录数是这样的:

analytic_productivity 728,708 analytic_scan 4,296,273 analytic_sterilizer_load 136,926 analytic_sterilizer_loadinv 327,700 record_changes_log 17,949,132

因此,不是巨大的,但并非没有。有没有一种方法可以合理地对SQL中的数据进行切片,以便

    每行更新一次
  • 没有行被更新超过一次
  • 一次没有更新太多行
  • [所有表都有一个UUID ID PK字段,一对表都有一个生成的标识列,就像从此报告表中摘录的一样:

CREATE TABLE IF NOT EXISTS "data"."analytic_productivity" ( "id" uuid NOT NULL DEFAULT NULL, "pg_con_id" integer GENERATED BY DEFAULT AS IDENTITY UNIQUE, "data_file_id" uuid NOT NULL DEFAULT NULL, "start_utc" timestamptz NOT NULL DEFAULT '-infinity', "start_local" timestamptz NOT NULL DEFAULT '-infinity', "end_utc" timestamptz NOT NULL DEFAULT '-infinity', "end_local" timestamptz NOT NULL DEFAULT '-infinity')

我的一个主意是使用UUID::text的子字符串或散列来进行较小的批处理:

select * from analytic_sterilizer_loadinv where left(id::text,1) = 'a'

这似乎很慢而且很恐怖。哈希似乎更好一些:

select abs(hashtext(id::text)) % 64, count(*) from analytic_sterilizer_loadinv

存储桶的大小不是均匀的,但这可能已经足够了,如果需要,我可以增加存储桶的数量。不幸的是,我不知道如何使用存储桶在SQL循环中运行代码。如果有人指出如何做,我将不胜感激。而且,如果有一个简单的内置分块功能,我很想知道。

我还没有考虑过如何处理即将被修改所困扰的传入数据的明确问题,只是没有锁定整个表。我可能可以做到。

部署在RDS上的精简版Postgres 11.4。是否有内置或直接的方法来拆分表中的行以进行批处理更新?一旦有了桶方案,如何在...

postgresql timestamp alter-table timestamp-with-timezone
1个回答
0
投票
[如果您负担得起,则不要分批执行UPDATE,而要一次完成。主要缺点是,这会使表膨胀,因此之后应在表上运行VACUUM (FULL),这将导致停机。
© www.soinside.com 2019 - 2024. All rights reserved.