Postgres 中分析表的架构

use*_*991 5 postgresql data-warehouse optimization star-schema

我们使用 Postgres 进行分析(星型模式)。每隔几秒钟,我们就会收到大约 500 种指标类型的报告。最简单的模式是:

timestamp      metric_type     value
78930890       FOO              80.9
78930890       ZOO              20
Run Code Online (Sandbox Code Playgroud)

我们的 DBA 提出了一个建议,将所有相同 5 秒的报告展平为:

timestamp   metric1     metric2     ...  metric500
78930890    90.9        20          ...  
Run Code Online (Sandbox Code Playgroud)

一些开发人员反驳这种说法,称这增加了开发的巨大复杂性(批处理数据,以便一次性编写)和可维护性(仅查看表或添加字段更复杂)。

DBA 模型是此类系统中的标准做法还是仅在原始模型显然不够可扩展时的最后手段?

编辑:最终目标是为用户绘制折线图。因此,查询主要是选择几个指标,按小时/分钟折叠它们,然后选择每小时(或任何其他时间段)的最小值/最大值/平均值。

编辑:DBA 的主要论点是将行数减少 x500 次将允许更高效的索引和内存(在此优化之前,该表将包含数亿行)。然后在选择多个度量标准时,建议的架构将允许一个通过数据而不是每个度量的单独索引搜索。

编辑:500 个指标是一个“上限”,但实际上大部分时间每 5 秒只报告约 40 个指标(虽然不是相同的 40)

Erw*_*ter 2

正如评论所述,双方的论点都有道理。我们称它们为“star”(DBA 的扁平化模式)和“EAV”(实体-属性-值)。后者可以作为一个提示。此相关答案中的详细信息:
此数据库结构有名称吗?

好吧,如果您的 500 个指标属于众所周知的类型,并且您不会一直发明新指标/放弃旧指标,那么这不是最坏的 EAV 场景,而是相似的。

没有“标准”方法可以做到这一点。更灵活的方法是“EAV”模式。然后,您可以轻松添加和删除指标类型:向引用的表添加一行metric_type,或删除一行(级联到指标表)。这需要进行模式更改,并且在“星”模型中成本更高。

您可以使用智能覆盖/部分/多列索引为任一模型做很多事情。

一些决策指导

单个指标类型上的聚合(最小值/最大值/平均值/...) ?->“明星”
聚合考虑所有或许多不同的指标?->“EAV”

这些属性是否描述了一个共同的实体?->“星号”
或者只是一堆可以以其他方式分组/分割的数字?->“EAV”

您的数据只写入一次,然后就再也没有改变过?->“star”
或者您是否对选定的指标运行更新?->“EAV”

您的 500 个指标集完整吗?该集合几乎从不改变或从不改变?->“star”
添加新指标,现有指标一直被删除?->“EAV”

存储大小

关于您的评论:

现在,存储对于优化来说不再那么重要,我们关注的是查询时间。

存储大小是查询时间的主要因素。满足查询而必须读取的数据页数量可能是影响性能的最重要的单一因素。

让我们从您的随意评论开始:Data type is int or double

int占用4个字节。
double占用8字节。

假设所有列都是NOT NULL,500 个整数列,加上 1 个时间戳加上行开销(无填充)将在“星型”模式中占用 2036 个字节。无法进行压缩。以下是计算方法:
配置 PostgreSQL 的读取性能

如果与 混合intdouble请确保不要浪费空间用于填充。例如,对整数和双精度指标进行分组。

在“EAV”模型中,每行至少需要 44 或 52 字节。一个时间戳为 22000 或 26000 字节。11 - 13 倍。这很重要。对于一小时的数据,您需要获取 2000 个或更多数据页(默认页面大小 8k),而“星型”模式则需要大约 180 个页面。

以下是一些测量大小的工具:
测量 PostgreSQL 表行的大小

我认为存储大小可能是性能的关键。如果您是focusing on query times,并且我不得不做出疯狂的猜测,那么“星形”模式可能是更好的选择

但正如我所说,这取决于很多细节。


无论哪种方式,您可能对交叉表(“数据透视表”)感兴趣。该tablefunc模块提供crosstab()功能:
将聚合函数组结果排成一行


归档时间:

查看次数:

3608 次

最近记录:

11 年,11 月 前