在 Kubernetes 上针对小数据量数据库的 PostgreSQL 与 TimescaleDB 存储比较
Source: Dev.to
目的
在 Kubernetes 上进行 两个独立的部署(vanilla PostgreSQL + TimescaleDB),使用小数据集比较存储使用情况。
注意: TimescaleDB 本身运行在 PostgreSQL 上。这里所说的 “TimescaleDB 部署” 指的是包含 PostgreSQL + Timescale 扩展的独立部署。我们也会部署 “vanilla PostgreSQL”,以便结果更清晰。
前置条件
- 正在运行的 Kubernetes 集群以及
kubectl访问权限 - Helm
- 安装在单节点集群上,且
StorageClass为 local‑path。
1. 阶段 – 安装
1.1 Namespace
kubectl create namespace database
1.2 Helm 仓库
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add timescaledb https://charts.timescale.com
helm repo update
第2阶段 – Vanilla PostgreSQL(Bitnami)安装
创建 postgres-values.yaml
# postgres-values.yaml içeriği burada tanımlanacak
注意: 我们连接到两个独立的 pod。我们将在两个不同的数据库安装中执行相同的操作。
第5阶段 – 使用小数据集进行测试
我们将在两个环境中执行以下SQL:
- 在 PostgreSQL 中,
sensor_pg将是普通表。 - 在 TimescaleDB 中,
sensor_ts将是 hypertable。
为了让数据量少,生成 1 天 的数据。
5.1 PostgreSQL
psql 中:
CREATE TABLE sensor_pg (
time TIMESTAMPTZ NOT NULL,
device_id INT,
temperature FLOAT
);
CREATE INDEX sensor_pg_time_idx ON sensor_pg(time);
INSERT INTO sensor_pg
SELECT
generate_series(NOW() - INTERVAL '1 day', NOW(), INTERVAL '1 minute'),
(random() * 10)::int,
random() * 100;
SELECT count(*) FROM sensor_pg;
5.2 TimescaleDB
psql 中:
CREATE EXTENSION IF NOT EXISTS timescaledb;
CREATE TABLE sensor_ts (
time TIMESTAMPTZ NOT NULL,
device_id INT,
temperature FLOAT
);
SELECT create_hypertable('sensor_ts', 'time');
CREATE INDEX sensor_ts_time_idx ON sensor_ts(time);
INSERT INTO sensor_ts
SELECT
generate_series(NOW() - INTERVAL '1 day', NOW(), INTERVAL '1 minute'),
(random() * 10)::int,
random() * 100;
SELECT count(*) FROM sensor_ts;
Not: 在 TimescaleDB 中,hypertable 看起来像普通表,但在后台会被划分为 chunk。即使是少量数据的测试,也会至少生成一个 chunk。
第6阶段 – 存储测量
通过在两个层面进行测量,我们可以获得更具体的结果:
- Relation size(使用SQL) – 表 + 索引 大小
- Data directory(使用文件系统) – 实际磁盘使用情况
6.1 PostgreSQL – 使用SQL获取表大小
SELECT
pg_size_pretty(pg_table_size('sensor_pg')) AS table_only,
pg_size_pretty(pg_indexes_size('sensor_pg')) AS indexes,
pg_size_pretty(pg_total_relation_size('sensor_pg')) AS total;
6.2 TimescaleDB – 使用SQL获取 hypertable(按 chunk)大小
SELECT
pg_size_pretty(SUM(pg_table_size(chunk.id::regclass))) AS table_only,
pg_size_pretty(SUM(pg_indexes_size(chunk.id::regclass))) AS indexes,
pg_size_pretty(SUM(pg_total_relation_size(chunk.id::regclass))) AS total
FROM show_chunks('sensor_ts') AS chunk(id);
说明: Hypertable 实际上由 chunk 表组成;因此真实的数据 + 索引大小等于所有 chunk 的总和。
7. 我的环境输出
PostgreSQL
postgres=# SELECT count(*) FROM sensor_pg;
count
-------
1441
(1 row)
TimescaleDB
postgres=# SELECT count(*) FROM sensor_ts;
count
-------
1441
(1 row)
(持续的测量结果和比较可以在此添加。)
7.1 SQL(关系)大小
表和索引在 PostgreSQL 中占用的空间。
PostgreSQL (sensor_pg)
table_only | indexes | total
------------+---------+--------
112 kB | 48 kB | 160 kB
(1 row)
TimescaleDB (sensor_ts)
table_only | indexes | total
------------+---------+--------
112 kB | 72 kB | 184 kB
(1 row)
table_only 在两侧相同,而 indexes 部分在 Timescale 侧更多。
8. 为什么 Timescale 在小数据上可能显示更大?
- 在 TimescaleDB 中,hypertable 实际上由 chunk 表 组成。每个 chunk 都拥有自己的表/索引结构。
- 在小数据集下,这种结构的 “overhead” 更加明显。
结论: 在数据量不大的表场景中,由于 Timescale hypertable 的 chunk/索引开销,PostgreSQL 看起来会更小一些。