提高 PostgreSQL 数据仓库 (RDS) 中的更新性能

Chr*_*ull 5 postgresql performance data-warehouse update amazon-rds postgresql-performance

我正在使用 Amazon RDS 上托管的 Postgres 数据仓库。当尝试从同一数据库中的另一个表更新事实表的一列(2500 万行)时,查询需要几天时间才能运行。为什么会发生这种情况,我该如何提高这种性能?我知道 PG 是为 OLTP 而设计的,而不是 OLAP,但是在这个表上选择查询性能通常相当不错。

有问题的查询如下所示:

UPDATE a
SET a.value = b.value
FROM b
WHERE a.id = b.id
Run Code Online (Sandbox Code Playgroud)

b是不同架构中的临时表,但与a. 两个表在 上都有主键idvalue列上没有索引或约束。有依赖于表a但没有外键的视图

我在 RDS 上使用 PG 9.5。具有 256 GB 存储空间的通用型 (SSD),因此在用尽我们最初的突发 IOPS 后,我的 IOPS 应该会略低于 800。

IOPS 节流真的是这里的问题吗?在观看查询运行时,我看到写入性能约为 400 IOPS,读取性能类似。25,000,000 行 / 400 IOPS = 17 小时,但此查询的运行时间比 24 小时长得多(大约 30 小时后取消以尝试进行调整)。同一个表上还有其他一些定期更新流量,但是当我看到这个查询花费了多长时间时,我在大约 20 小时时停止了它。

我想知道我的一般更新方法是否错误,或者是否有使用 postgres 操作数据仓库(OLAP 工作负载)的一般建议。我能否通过放弃 RDS 并在 EC2 上运行 PG 来获得更好的性能?

更新:受回复和评论的启发,我对 45k 行进行了测试(通过将 pk 限制在某个范围以下)

你可以在explain analyze 这里看到结果。绝大多数时间都花在将实际更新写入表中。现在我仍然倾向于将写入 IOPS 作为一个限制因素,但我将深入研究 joanolo 提到的可能的复制问题。

此图显示了 RDS 实例监控页面。最近的峰值是有问题的查询。 在此处输入图片说明

joa*_*olo 1

这并不是要成为真正的答案,但至少是一个参考比较点,以及在非 RDS 机器上进行极其简化的设置的一些提示:

CREATE TABLE a
(
    id integer PRIMARY KEY,
    value float
) ;
CREATE TABLE b
(
    id integer PRIMARY KEY,
    value float
) ;

-- Fill table with 25M records
INSERT INTO a 
    (id, value)
SELECT
    generate_series(1, 25e6) AS id, random();
-- 3 min 44 s

-- Fill table with 25M records as well
INSERT INTO b
    (id, value)
SELECT
    generate_series(1, 25e6) AS id, random();
-- 4 min 15 s

UPDATE
    a
SET
    value = b.value
FROM
    b
WHERE
    b.id = a.id ;
-- Query returned successfully: 25000000 rows affected, 08:06 minutes execution time.
Run Code Online (Sandbox Code Playgroud)

执行查询时计算机使用的资源:

-- iostat => 22 to 24 KB/t, 366 to 428 tps, 8.65 MB/s .. 10 MB/s 

-- Activity Monitor, Disk tab
-- Before starting...
-- Process   ReadBytes WrittenBytes 
-- postgres 4,12 GB       224 KB    
-- postgres 3,51 GB     227,6 MB
-- postgres 1,98 GB       1,1 MB    

-- After finishing
-- postgres 7,71 GB 2,85 GB 
-- postgres 6,59 GB 252 KB  
-- postgres 4,17 GB 2,3 MB  

-- Diff: Read Bytes: 8,86 GB,  WrittenBytes 2,85 GB
Run Code Online (Sandbox Code Playgroud)

您可以在这里查看执行计划

此测试是在配备 i7 处理器 @1 的 MacBook Air 上的“x86_64-apple-darwin14.5.0 上的 PostgreSQL 9.6.3,由 Apple LLVM 版本 7.0.0 (clang-700.1.76) 编译,64 位”上执行的,7 GHz、512 GB SSD 和 8 GB RAM,以及 macOS Sierra 10.12.5。PostgreSQL 的设置是“开箱即用”的(通过 Postgress.app 安装),没有进一步优化。

显然,这种场景与 RDS 的场景有很大不同。

时间上的差异如此之,以至于表明:

  1. 我使用的简化模型非常糟糕地代表了您的真实情况。
  2. 您对 Am​​azon RDS 上 IOPS 的需求远远大于您的实际需求。

需要考虑的事项:

  1. 如果您正在运行 OLAP 流程,那么您很可能在其他地方拥有原始数据并进行复制。这意味着您不需要安装具有复制功能的数据库。如果RDS已经设置了复制,我建议将其删除

  2. EC2 r3.large 实例(相对)靠近我执行测试的计算机。

  3. 拥有自己的 PostgreSQL 设置意味着您必须处理备份、更新等...考虑到这一点。

  4. 如果设置 EC2 实例并执行一些试验符合您的现实可能性;我想尝试一下。