具有超过十亿行的表的 Postgres 性能

Posted

技术标签:

【中文标题】具有超过十亿行的表的 Postgres 性能【英文标题】:Postgres performance for a table with more than Billion rows 【发布时间】:2017-08-11 07:51:36 【问题描述】:

我正在做一个 PoC 来检查 Postgres 是否适合我们的用例。

我有以下工作量:

数据查询: 表示层将在过去 2 周内每 15 分钟检索一次数据

数据加载: 每 15 分钟,就有 500 万行数据加载到一个表中,我观察到该加载消耗了 375MB。 每天将有 4.8 亿行,表大小为 36GB。

在我加载数据几天后(表中大约有 10 亿行),我运行了几个查询,我观察到选择查询几个小时都没有响应。例如select count(*) .. 和 select * .. 简单但繁重的查询。没有连接。

我的要求是每 15 分钟加载一次数据并将其存储几个月,但我还没有达到那么远。即使有几天的上述工作量数据,我观察到选择查询没有响应。

我想知道 postgres 是否对这种工作负载有任何限制,或者我是否没有正确调整它!我错过了配置任何关键参数吗?

我已经阅读了有关限制的 postgres 官方文档 (https://www.postgresql.org/about/),但我的要求并没有真正达到 postgres 中指定的理论限制。

Postgres 配置: 下面是我配置的postgres参数。

checkpoint_completion_target | 0.9
default_statistics_target    | 500
effective_cache_size         | 135GB
maintenance_work_mem         | 2GB
max_connections              | 50
max_stack_depth              | 2MB
max_wal_size                 | 8GB
min_wal_size                 | 4GB
shared_buffers               | 45GB
wal_buffers                  | 16MB
work_mem                     | 471859kB

服务器配置:

虚拟化硬件!

vCPU:32

内存:200GB

我想知道 postgres 是否需要物理专用硬件。也许它无法处理虚拟化硬件上的这种负载!

如果您对此有 cmets 或建议,请不胜感激。 BR/唠叨

【问题讨论】:

您正在运行哪种查询?对于这种数据量,您通常需要 OLAP 类型的分析查询和数据重组/汇总。 ... simple but heavy queries. no joins... 这种查询没有优化空间。需要所有行的查询将需要获取所有页面。 您需要优化硬件以实现快速磁盘读取,因为您不希望在内存中缓存那么多数据。对于某些查询,您可能会提供物化视图或其他优化以提高性能。 到目前为止,您所做的一切都是 IO 密集型的。而且您还没有告诉我们有关您的 IO 子系统的任何信息。 【参考方案1】:

问题不在于 PostgreSQL,而在于硬件以及如何调整数据库。事实上,雅虎、Reddit、Yandex 和其他公司都在使用它。 从 9.6 开始,有parallel queries,因此您可以更有效地利用您的 CPU。

【讨论】:

绝对应该让其他 31 个 CPU 工作。【参考方案2】:

您可以考虑一些配置步骤,以便对如此大量的数据做出更好更快的响应。您可以使用多租户方法、索引数据库、使用 Linux 基础系统而不是 Windows。

This 链接将帮助您整理这些方面以及其他方面。

【讨论】:

【参考方案3】:

从开源数据库的角度来看,Postgres 是公认的用于处理和处理大型数据集的数据库之一。 Postgres 不会是问题,但还需要考虑其他重要因素,例如数据库设计和硬件配置。

对于存储和查询大型数据集,表分区和索引的概念在数据库设计方面会更有帮助。表分区功能在 postgres 11 / 10 / 9.6 / 9.5 中可用。文档链接 - Table Partition

    CREATE TABLE IF NOT EXISTS parent_tbl
    (
      id                bigint,
      sp_id             integer,
      name              varchar,
      month_year        date,
     );

PARTITION TABLE (PARTITION BY sp_id) INHERT TABLE parent_tbl

    CREATE TABLE IF NOT EXISTS tbl_partition_1
    (
      CHECK (sp_id=1)
    )INHERITS (parent_tbl);
    CREATE INDEX ON tbl_partition_1(month_year);

    CREATE TABLE IF NOT EXISTS tbl_partition_2
    (
     CHECK (tsp_id=2)
    )INHERITS (parent_tbl);
    CREATE INDEX ON tbl_partition_2(month_year);

    CREATE TABLE IF NOT EXISTS tbl_partition_3
    (
     CHECK (tsp_id=3)
    )INHERITS (parent_tbl);
    CREATE INDEX ON tbl_partition_3(month_year);

【讨论】:

您的代码显示了旧的已弃用的基于继承的分区 - 但为了获得适当的性能,您应该使用新的声明性分区

以上是关于具有超过十亿行的表的 Postgres 性能的主要内容,如果未能解决你的问题,请参考以下文章

如何在超过 100 亿行的海量数据集上执行选择

我应该在包含超过十亿行的mysql数据库设计中使用啥方法来使用最少的时间找到特定的值?

mysql在具有1亿行的表上创建索引

从包含数万亿条记录的 Oracle 表中删除数十亿条记录

无法理解数十亿行的更新计数 INSERT

在 postgres 中更新具有大量删除的表的主键序列