具有超过十亿行的表的 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 性能的主要内容,如果未能解决你的问题,请参考以下文章