处理庞大的 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进行流式传输