扩展 PostgreSQL 的最佳实践

免费试用

立即开始为您的 PostgreSQL 加速。

A group of elephants, from the smallest to the largest.

作者:Juan José GouvêaAna Tavares

随着数据以空前的速度不断增长,全球各地的企业都在努力寻找更有效的方式来管理和利用数据。根据国际数据公司 (IDC) 的报告,“数据圈”规模(对每年将创建的数据量的预测)预计到 2026 年将翻番。

数据量的激增给存储和数据库系统带来了巨大压力,需要不断提高可扩展性。随着云计算的出现,数据库管理系统已经发展到令人印象深刻的规模,通常存储数 TB 或更多的数据。这种趋势在短期内不会消失,尤其是在公司和其他组织采用数据驱动策略并深入研究分析以进行决策的情况下。

为了应对数据增长的挑战,企业必须采用能够有效管理数据的现代存储解决方案。PostgreSQL 是一种经过实战检验的关系型数据库管理系统 (RDBS),经过 30 多年的发展,在全球开发者中越来越受欢迎,能够应对这一挑战吗?

在 Timescale,我们认为答案是“可以”,但您需要在扩展 PostgreSQL 时采取正确的方法。

PostgreSQL 扩展的挑战

扩展 PostgreSQL 以适应快速增长的数据量,会带来一些挑战。尽管 PostgreSQL 灵活且快速,但它最初并非旨在应对当今数据规模的爆炸式增长,正如我们在关于PostgreSQL TOAST 的这篇文章中所论述的。

让我们概述一下扩展 PostgreSQL 数据库时遇到的主要障碍。

摄取限制

PostgreSQL 可以处理大量数据摄取速率,能够插入大型数据集(例如,每秒约 100K 行)。但是,这些速率仍然有限,随着数据摄取需求的增长,这个限制可能会成为需要实时高容量数据输入的应用程序的瓶颈。

表变慢

当 PostgreSQL 中单个表的规模不断增长时,它可能会显著降低查询响应时间。对 100K 行进行排序与对 5000 万行进行排序之间的性能差异很大。这种变慢不仅会影响查询性能,还会影响数据库操作的效率,例如更新、删除和维护任务。

排序性能下降的示例

-- Example query sorting a small table
SELECT * FROM small_table ORDER BY column ASC;

-- Example query sorting a large table
SELECT * FROM large_table ORDER BY column ASC;

在上述示例中,对 large_table 的操作会由于数据量的增加而变得明显更慢,说明了表大小对性能的影响。

批处理/缓存结构

PostgreSQL 的架构旨在通过批处理和缓存来提高计算效率。但是,这种方法在处理和更新缓存数据的连续性方面引入了限制。

物化视图和缓存更新

PostgreSQL 中的物化视图提供了一种将查询结果以类似表的形式缓存到表中的方法,这可以提高对频繁执行的查询的访问速度。但是,物化视图中的数据并不总是最新的,需要完全刷新才能更新,这使得它不太适合需要实时数据的应用程序。

-- Creating a materialized view
CREATE MATERIALIZED VIEW sales_summary AS
SELECT seller_no, invoice_date, sum(invoice_amt)::numeric(13,2) as sales_amt
FROM invoice
WHERE invoice_date < CURRENT_DATE
GROUP BY seller_no, invoice_date;

-- Refreshing a materialized view
REFRESH MATERIALIZED VIEW sales_summary;

REFRESH MATERIALIZED VIEW 操作对于大型数据集来说可能代价高昂,需要对视图进行完全重新计算。这个过程限制了处理连续性和维护实时数据的新鲜度。

总体挑战

所描述的挑战强调了这样一个事实,即虽然 PostgreSQL 是一款功能强大且通用的数据库系统,但要将其扩展以满足现代应用程序和数据量的需求,需要仔细规划和实施最佳实践。

解决这些挑战涉及利用 PostgreSQL 的功能,例如分区和复制,以及考虑架构更改,例如分片或采用其他技术更有效地分发工作负载。

如何扩展 PostgreSQL

有效地扩展 PostgreSQL 需要结合针对特定需求量身定制的策略。让我们来了解一下这些策略。

多进程和批处理摄取

要优化摄取速率,请考虑将数据批处理成块,最好每插入一次在 50K 到 100K 行之间。这种方法利用了 PostgreSQL 在有效处理批量数据方面的优势。但是,对于处理时间序列数据的系统来说,数据流入速率非常高,这种方法本身可能不足。批处理的插入语句示例如下

INSERT INTO mytable (timestamp, metric1, metric2)
VALUES
('2022-06-01 12:00:00', 1, 1.11),
('2022-06-01 13:00:00', 2, 2.21);

存储成本

随着数据的增长,存储成为一个关键问题。大型表不仅会占用大量存储空间,而且维护成本也很高。PostgreSQL 提供数据压缩机制来缓解这种情况,但会以访问速度为代价。因此,设计有效的压缩策略对于在存储成本和性能需求之间取得平衡至关重要。

索引

索引 对于提高 PostgreSQL 中的查询性能至关重要。通过加速数据检索,它们可以显著加快查询速度。但是,创建和管理索引需要深入了解数据和访问模式,因为它们也会增加数据库的存储空间占用。 PostgreSQL 支持多种索引类型,包括 B 树、哈希、GiST、SP-GiST、GIN 和 BRIN,每种索引类型都针对不同类型的查询进行了优化。

表分区

将大型表分成较小的块可以显著提高查询性能,尤其是在查询针对数据特定部分时。 PostgreSQL 支持范围、列表和哈希分区,允许灵活的分区策略。按日期对表创建范围分区的示例如下

CREATE TABLE measurement (
    city_id int not null,
    logdate date not null,
    peaktemp int,
    unitsales int
) PARTITION BY RANGE (logdate);

增量物化视图

物化视图可以缓存查询结果,并使用新数据对其进行增量更新。对于在相同数据集上重复运行的查询,这种策略特别有效。但是,设置和维护增量更新可能会很复杂。

只读副本

实现只读副本 可以分发查询负载,从而提高数据库的读取能力。只读副本是主数据库的同步副本,用于为主数据库分流读取查询。这种方法需要仔细管理同步过程,以确保数据一致性。

介绍 Timescale

对于难以应对时间序列数据扩展需求的数据库, Timescale 能够为 PostgreSQL 增强性能,使其能够应对苛刻的工作负载,并提供针对时间序列数据优化的自动扩展解决方案。它简化了许多传统的扩展挑战,提供针对时间序列模式而设计的有效数据存储、压缩和分区的内置机制。

使用带 Timescale 的 PostgreSQL 扩展时间序列数据

在本节中,我们将深入探讨 Timescale 如何解决常见的 Postgres 扩展问题,包括数据摄取、存储优化、索引策略、表分区、连续聚合和读取扩展,所有这些都通过代码示例和文档提供支持。 有关 Timescale 工作原理的更多信息,请访问我们的文档

数据摄取

Timescale 利用 PostgreSQL 的架构提供高摄取速率,能够协调多个摄取过程。这允许将摄取操作分解成并行进程,每个进程可以处理大约每秒 100K 次插入。该策略侧重于最大限度地利用硬件和网络资源,展示了一种类似于命令模式的模式,例如

-- Pseudo code to demonstrate parallel ingest pattern
BEGIN;
INSERT INTO conditions (time, location, temperature) VALUES (NOW(), 'office', 70.0);
COMMIT;

这种方法强调使用 PostgreSQL 的高效插入机制,同时利用 TimescaleDB 的能力将这些操作分发到多个后台工作进程中。

存储空间优化

Timescale 引入了分层存储和列式压缩来应对存储空间挑战

例如,在超表上配置压缩可以像以下一样简单:

SELECT add_compression_policy('conditions', INTERVAL '7 days');

此命令为七天之前的旧数据启用自动压缩,显著减少存储需求。

高级索引

Timescale 自动处理时间序列数据的索引过程,无需您进行大量规划和实施自定义索引策略。例如,创建一个基于时间和位置的索引可能如下所示:

CREATE INDEX ON conditions (time DESC, location);

此索引通过利用时间序列数据的固有时间排序特性以及任何其他维度(例如位置)来提高查询性能。

超表分区

超表是 Timescale 的核心功能,它可以将时间序列数据自动划分为可管理的块。这种分区沿两个维度进行——时间和一个可选的附加属性,从而实现高效的数据管理和查询优化。

SELECT create_hypertable('conditions', 'time', 'location', chunk_time_interval => INTERVAL '1 week');

超表创建自动执行数据分区,通过维护更小、更易于管理的数据集来提高数据摄取和查询性能。

连续聚合

连续聚合提供了一种强大的方法,可以维护对大型数据集的实时增量视图,从而显著减少聚合查询的计算负载。

CREATE VIEW conditions_summary WITH (timescaledb.continuous) AS
SELECT time_bucket('1 day', time), AVG(temperature)
FROM conditions
GROUP BY 1;

此功能允许对聚合数据进行高效的查询性能,并在新数据到达时无缝更新。

使用副本进行读取扩展

Timescale 通过创建和管理 读取副本 来促进读取扩展,从而将查询负载分布到多个实例。这对于高可用性设置以及将分析工作负载与事务处理分离至关重要。

-- Hypothetical command to add a read replica
SELECT add_read_replica('service_id', 'replica_configuration');

此命令将为服务添加一个读取副本,从而提高读取能力和系统弹性。

通过重新设计 Postgres 最受欢迎的一些功能并引入新的功能,Timescale 将 Postgres 变成一个可扩展的时间序列数据管理解决方案,可以解决开发人员在处理大量数据时面临的核心挑战。最棒的是,您不会被陡峭的学习曲线所拖累:您仍然可以使用您熟悉和喜爱的丰富可靠的 Postgres 生态系统。

立即开始扩展 Postgres

在当今数据密集型环境中扩展 PostgreSQL 会带来独特的挑战,从摄取限制到管理大型表以及确保高效的查询性能。尽管 PostgreSQL 为用户提供了扩展工具,但有效利用这些功能需要对数据库系统及其管理的特定数据工作负载都有深刻的了解。

Timescale 凭借其旨在增强 PostgreSQL 原生功能的解决方案套件(尤其针对时间序列数据),简化了数据摄取、存储优化和实时分析的复杂性,使您能够更有效地扩展 PostgreSQL 系统。

亲身体验 TimescaleDB 的功能和优势:免费试用 Timescale,无需信用卡.