【发布时间】:2019-11-13 17:50:01
【问题描述】:
我大约每 10 分钟插入约 50 条具有相同时间戳的记录。
这意味着每小时约 600 条记录或每天 7.200 条记录或每年 2.592.000 条记录。
用户想要检索最接近请求时间的时间戳的所有记录。
设计#1 - 一张在时间戳列上有索引的表:
CREATE TABLE A (t timestamp, value int);
CREATE a_idx ON A (t);
单个插入语句创建约 50 条具有相同时间戳的记录:
INSERT INTO A VALUES (
(‘2019-01-02 10:00’, 5),
(‘2019-01-02 10:00’, 12),
(‘2019-01-02 10:00’, 7),
….
)
获取最接近询问时间的所有记录
(我使用 PostgreSQL 中可用的函数 best()):
SELECT * FROM A WHERE t =
(SELECT t FROM A ORDER BY greatest(t - asked_time, asked_time - t) LIMIT 1)
我认为这个查询效率不高,因为它需要全表扫描。
我计划按时间戳对 A 表进行分区,以便每年有 1 个分区,但上面的近似匹配仍然会很慢。
设计#2 - 创建 2 个表格:
第一张表:保持唯一的时间戳和自动递增的 PK,
第二张表:在第一张表PK上保存数据和外键
CREATE TABLE UNIQ_TIMESTAMP (id SERIAL PRIMARY KEY, t timestamp);
CREATE TABLE DATA (id INTEGER REFERENCES UNIQ_TIMESTAMP (id), value int);
CREATE INDEX data_time_idx ON DATA (id);
获取最接近询问时间的所有记录:
SELECT * FROM DATA WHERE id =
(SELECT id FROM UNIQ_TIMESTAMP ORDER BY greatest(t - asked_time, asked_time - t) LIMIT 1)
与设计 #1 相比,它应该运行得更快,因为嵌套选择会扫描较小的表。
这种方法的缺点:
- 我必须插入 2 个表而不是一个
- 我失去了按时间戳对 DATA 表进行分区的能力
你可以推荐什么?
【问题讨论】:
-
如果用户请求的时间戳可能不完全存在于数据集中,那么我将采用您的第一种方法。您可以使用
RANK作为替代方案,但我看不出有任何方法可以避免某种子查询。
标签: postgresql database-design relational-database