考虑这样一种情况:有一个非常大的表(高达几个 TB),并且由于某种原因应用程序想要完整扫描该表。应用程序和 PostgreSQL 服务器端都有多个 CPU 核心,因此它给我们带来了将表分成多个部分并在并行线程中并发读取它们的想法。实现这一目标的最佳方法是什么?
像这样用 OFFSET / LIMIT 模拟表“分页”有意义吗?
SELECT * FROM table LIMIT 1000000 OFFSET 0
SELECT * FROM table LIMIT 1000000 OFFSET 1000000
SELECT * FROM table LIMIT 1000000 OFFSET 2000000
(...)
这样每个 SELECT 将在不同的应用程序线程中执行。
或者也许值得尝试使用 PostgreSQL 原生表分区,这样每个表分区(实际上是一个不同的表)将被独立读取?
另一个重要的一点是一致性。当然,在扫描过程中,表格可能会发生变化。 PostgreSQL 是否为独立的
SELECT
提供任何类型的事务,以使它们能够使用一致的表视图,而无需后续请求引入数据?
PostgreSQL 支持并行查询。
PostgreSQL 可以设计可以利用多个 CPU 的查询计划,以便更快地回答查询。此功能称为并行查询。
但是并行化并不是灵丹妙药。
许多查询无法从并行查询中受益,要么是由于当前实现的限制,要么是因为没有可以想象的比串行查询计划更快的查询计划。然而,对于可以受益的查询,并行查询的加速通常非常显着。使用并行查询时,许多查询的运行速度可以提高两倍以上,某些查询的运行速度可以提高四倍甚至更多。涉及大量数据但仅向用户返回几行的查询通常会受益最多。
我不打算详细介绍,文档中都有关于如何配置 Postgres 以使用并行工作程序并执行并行 seq 扫描。
在某个时刻,无论您拥有多少个 CPU,您都会遇到磁盘 I/O 的限制。即使最好的 SSD 也只能读取 10 GB/s,几个 TB 至少需要几分钟。最好问一下是否可以避免 seq 扫描表。
或者也许值得尝试使用 PostgreSQL 本机表分区,因此每个表分区(实际上是一个不同的表)将被独立读取?
有可能,但表分区也不是神奇的性能子弹。没有更多细节我不能说。
第三个选择是将大量数据移动到针对此类大型查询进行优化的数据仓库中。