【发布时间】:2017-05-10 12:11:06
【问题描述】:
我正在尝试编写一个存储过程,用于从一个大表中及时选择 X 个井分布点。
我有一张桌子points:
"Userid" integer
, "Time" timestamp with time zone
, "Value" integer
它包含数亿条记录。每个用户大约有一百万条记录。
我想选择 X 个点(比如说 50 个),这些点从时间 A 到时间 B 都分布得很好。问题是这些点分布不均(如果一个点在 6:00:00,下一个例如,点可能在 15 秒、20 或 4 分钟之后)。
为一个 id 选择所有点最多可能需要 60 秒(因为大约有一百万个点)。
有没有什么方法可以快速选择我想要的精确点数,并尽可能地分散?
样本数据:
+--------+---------------------+-------+
| UserId | Time | Value |
+--------+---------------------+-------+
1 | 1 | 2017-04-10 14:00:00 | 1 |
2 | 1 | 2017-04-10 14:00:10 | 10 |
3 | 1 | 2017-04-10 14:00:20 | 32 |
4 | 1 | 2017-04-10 14:00:35 | 80 |
5 | 1 | 2017-04-10 14:00:58 | 101 |
6 | 1 | 2017-04-10 14:01:00 | 203 |
7 | 1 | 2017-04-10 14:01:30 | 204 |
8 | 1 | 2017-04-10 14:01:40 | 205 |
9 | 1 | 2017-04-10 14:02:02 | 32 |
10 | 1 | 2017-04-10 14:02:15 | 7 |
11 | 1 | 2017-04-10 14:02:30 | 900 |
12 | 1 | 2017-04-10 14:02:45 | 22 |
13 | 1 | 2017-04-10 14:03:00 | 34 |
14 | 1 | 2017-04-10 14:03:30 | 54 |
15 | 1 | 2017-04-10 14:04:00 | 54 |
16 | 1 | 2017-04-10 14:06:00 | 60 |
17 | 1 | 2017-04-10 14:07:20 | 654 |
18 | 1 | 2017-04-10 14:07:40 | 32 |
19 | 1 | 2017-04-10 14:08:00 | 33 |
20 | 1 | 2017-04-10 14:08:12 | 32 |
21 | 1 | 2017-04-10 14:10:00 | 8 |
+--------+---------------------+-------+
我想从上面的列表中为 ID 为 1 的用户选择 11 个“最佳”点, 从 2017-04-10 14:00:00 到 2017-04-10 14:10:00。
目前它在服务器上完成,为用户选择所有点后。 我通过除以时间差来计算“最佳时间”并得到一个列表,例如:14:00:00,14:01:00,....14:10:00(11 个“最佳时间”,作为点数)。比我寻找尚未选择的每个“最佳时间”的最近点。 结果将是点:1、6、9、13、15、16、17、18、19、20、21
编辑:
我正在尝试这样的事情:
SELECT * FROM "points"
WHERE "Userid" = 1 AND
(("Time" =
(SELECT "Time" FROM
"points"
ORDER BY abs(extract(epoch from '2017-04-10 14:00:00' - "Time"))
LIMIT 1)) OR
("Time" =
(SELECT "Time" FROM
"points"
ORDER BY abs(extract(epoch from '2017-04-10 14:01:00' - "Time"))
LIMIT 1)) OR
("Time" =
(SELECT "Time" FROM
"points"
ORDER BY abs(extract(epoch from '2017-04-10 14:02:00' - "Time"))
LIMIT 1)))
这里的问题是:
A) 它不考虑已经选择的积分。
B) 因为ORDER BY,每增加一次查询的运行时间就会增加约 1 秒,50 分我回到 1 分钟标记。
【问题讨论】:
-
样本数据、期望的结果和您当前的代码真的很有帮助。
-
已经完成了,先生。
-
因为他们的时间太接近第一个点,并且为了得到 11 个最好的(分散良好的)点,我需要一个尽可能接近时间 14:00, 14 的点: 01、14:02、14:03.... 14:10
-
"best" points仍然没有很好的定义。 “良好传播”是一个可以解释的模糊术语。您实施的方法是找到与给定时间网格最近的点,这似乎是一个很好的近似值,但它确实不一定必须最小化所选行之间的时间差总和。并且您的 Postgres 版本应该始终被披露。
标签: sql postgresql time-series nearest-neighbor postgresql-performance