Quyết định nằm ở tốc độ ghi, cardinality và vòng đời dữ liệu, không ở chỗ "dữ liệu có cột thời gian".
Postgres đủ dùng khi ghi dưới vài chục nghìn dòng/giây, số chuỗi (series) hữu hạn, và cần join metrics với dữ liệu nghiệp vụ. Điều kiện bắt buộc là partition theo thời gian:
create table metrics (
ts timestamptz not null,
device_id bigint not null,
value double precision not null
) partition by range (ts);Partition theo ngày/tuần cho phép xoá dữ liệu cũ bằng DROP TABLE partition — thao tác tức thì, không sinh bloat như DELETE hàng loạt. Thiếu partition thì bảng metrics sẽ trở thành vấn đề vận hành trong vài tháng.
Chuyển sang TSDB chuyên dụng (Prometheus, VictoriaMetrics, TimescaleDB, InfluxDB) khi:
- Cardinality cao: mỗi tổ hợp label tạo một chuỗi riêng. Thêm một label kiểu user_id hay request_id làm số chuỗi tăng theo cấp số nhân — đây là nguyên nhân sập phổ biến nhất của hệ thống metrics, và TSDB được thiết kế quanh chính bài toán này.
- Cần nén mạnh: dữ liệu chuỗi thời gian nén rất tốt nhờ delta-of-delta cho timestamp và XOR cho giá trị; TSDB đạt tỉ lệ nén mà bảng Postgres thường không đạt.
- Cần downsampling và retention theo tầng: giữ độ phân giải 15s trong 7 ngày, 5 phút trong 90 ngày, 1 giờ trong 2 năm — TSDB làm sẵn, Postgres phải tự viết job.
- Cần hàm truy vấn theo miền: rate(), histogram_quantile(), cửa sổ trượt, gap filling.
Chốt lựa chọn: metrics hạ tầng và ứng dụng → TSDB. Dữ liệu chuỗi thời gian mang tính nghiệp vụ (lịch sử giá, số đọc công tơ) cần chính xác giao dịch và join với bảng quan hệ → giữ trong Postgres có partition, cân nhắc TimescaleDB nếu muốn cả hai.