1

我正在构建一个网络分析工具并使用 Postgresql 作为数据库。我不会在每次用户访问时插入 postgres,而只会每 5 秒聚合一次数据:

time    country    browser    num_visits
========================================
0       USA        Chrome     12
0       USA        IE         7
5       France     IE         5

正如您所看到的,我每 5 秒插入多行(每个维度组合一个)。

为了减少查询中需要扫描的行数,我想根据它们的分辨率有多个具有上述模式的表:5SecondResolution、30SecondResolution、5MinResolution、...、1HourResolution。现在,当用户询问最后一天的情况时,我将转到小于 5 秒分辨率表的小时分辨率表(尽管我也可以使用那个 - 它只是要扫描更多的行)。

现在,如果小时分辨率表包含 0、1、2、3 小时的数据,... 但用户要求查看从 1:59 到 8:59 的每小时趋势,该怎么办。为了获取 1:59-2:59 期间的数据,我可以对不同的分辨率表进行多次查询,因此我从 1MinResolution 获得 1:59:2:00,从 30MinResolution 获得 2:00-2:30 等等。 AFAIU 我已经将一个查询交易到一个巨大的表(有许多相关的行要扫描),多个查询到中型表+在客户端合并结果。

这听起来像是一个很好的优化吗?对此还有其他考虑吗?

4

2 回答 2

2

现在,如果小时分辨率表包含 0、1、2、3 小时的数据,... 但用户要求查看从 1:59 到 8:59 的每小时趋势,该怎么办。为了获取 1:59-2:59 期间的数据,我可以对不同的分辨率表进行多次查询,因此我从 1MinResolution 获得 1:59:2:00,从 30MinResolution 获得 2:00-2:30 等。

如果您希望结果准确,则不能这样做。想象一下,如果他们要求从 01:30 到 04:30 解决一小时的问题。你想象你会从 5 秒(或 1 分钟)的 res 表中获得前半小时和后半小时,然后从一小时表中获得其余的半小时。

问题是一小时表偏移了半小时,所以答案实际上并不正确;当用户想要 2:30 到 3:30 时,每小时将从 2:00 到 3:00 等。当您转向更粗略的分辨率时,这是一个更加严重的问题。

所以:这是一种完全合理的优化技术,但前提是您将用户的搜索开始精度限制为聚合表的分辨率。如果他们想要一小时的分辨率,强制他们选择1:00,2:00等,并且不允许设置分钟。如果他们想要 5 分钟的分辨率,让他们选择 1:00、1:05、1:10 等。您不必以相同的方式限制结束精度,因为不完整的结束间隔不会影响结束之前的数据,并且在显示时很容易被标记为不完整。“当前日期”、“到目前为止的时间”等。

如果您限制起始精度,您不仅会给他们正确的结果,而且会大大简化查询。如果您也限制结束精度,那么您的查询纯粹是针对聚合表,但如果您想要“最新”数据,那么编写如下内容很容易:

SELECT blah, mytimestamp
FROM mydata_1hour
WHERE mytimestamp BETWEEN current_date + INTERVAL '1' HOUR AND current_date + INTERVAL '4' HOUR
UNION ALL
SELECT sum(blah), current_date + INTERVAL '5' HOUR
FROM mydata_5second
WHERE mytimestamp BETWEEN current_date + INTERVAL '4' HOUR AND current_date + INTERVAL '5' HOUR;

...甚至使用多个级别的联合来满足对更粗略分辨率的请求。

于 2013-07-28T23:34:11.103 回答
1

您可以使用继承/分区。一个分辨率主表和许多每小时分辨率子表(也许还有许多分钟和秒分辨率子表)。

因此,您只需从主表中进行选择,让每个子表的约束来决定哪个是哪个。

当然,您必须添加一个触发器函数来将插入分隔到适当的子表中。

插入的复杂性与显示的复杂性。

PostgreSQL - 查看还是分区?

于 2013-07-29T10:51:12.553 回答