处理庞大的 postgres 数据库的最佳方法

Posted

技术标签:

【中文标题】处理庞大的 postgres 数据库的最佳方法【英文标题】:Best way to deal with huge postgres database 【发布时间】:2021-05-15 13:42:51 【问题描述】:

我创建了一个将大量数据收集到 Postgres 数据库的刮板。其中一张表有超过 1.2 亿条记录,并且还在增长。 即使是简单的选择也会产生明显的问题,但是当我运行聚合时 像COUNT() 这样的函数,需要很长时间才能得到结果。我想使用 Web 服务显示这些数据,但是直接这样做肯定太慢了。我考虑过物化视图,但即使在那里我运行一些更高级的查询(使用子查询查询以显示趋势),它也会抛出内存不足的错误,如果查询很简单,则需要大约一个小时才能完成。我在询问处理如此庞大的数据库的一般规则(我还没有找到任何规则)。 我使用的示例查询:

简单的查询大约需要一个小时才能完成(Items 表有 1.2 亿条记录,ItemTypes 有大约 30k - 它们保留了 Items 的名称和所有信息)

SELECT 
  IT."name", 
  COUNT("Items".id) AS item_count,
  (CAST(COUNT("Items".id) AS DECIMAL(10,1))/(SELECT COUNT(id) FROM "Items"))*100 as percentage_of_all
FROM "Items" JOIN "ItemTypes" IT on "Items"."itemTypeId" = IT.id
GROUP BY IT."name"
ORDER BY item_count  DESC;

当我使用返回 COUNT("Items".id) AS item_count % 趋势的子查询运行上述查询时,这是一周前的计数与现在的计数相比,它会引发超出内存的错误。

正如我在上面所写的,我正在寻找提示,如何优化它。我计划优化上述查询的第一件事是将名称从 ItemTypes 移动到 Items,再到 Items。不再需要加入 ItemTypes,但我已经尝试模拟它,结果并没有好很多。

【问题讨论】:

您可以改用count(*) 来稍微加快速度 - 但不是很多。 “通则”就是解决你所面临的具体问题。 【参考方案1】:

您不需要子查询,因此等效版本是:

SELECT IT."name", 
       COUNT(*) AS item_count,
       COUNT(*) * 100.0 / SUM(COUNT(*)) OVER () as percentage_of_all
FROM "Items" JOIN 
     "ItemTypes" IT 
     ON "Items"."itemTypeId" = IT.id
GROUP BY IT."name"
ORDER BY item_count  DESC;

我不确定这是否能解决您的资源问题。此外,这假定所有项目都有一个有效的ItemType。如果不是这种情况,请使用LEFT JOIN 而不是JOIN

【讨论】:

以上是关于处理庞大的 postgres 数据库的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

将大量数据从 DataFlow 加载到外部 postgres 数据库的最佳方法是啥?

使用 Postgres 全文搜索搜索完全匹配的最佳方法是啥?

Postgres使用JDBC Kafka Connect进行流式传输

从 React->ExpressJS->Postgres 修补 Postgres JSONB 列的最佳方法是啥?

最佳实践:优化Postgres查询性能(下)

最佳实践:优化Postgres查询性能(下)