【问题标题】:Alternative for a many to many relation between a hypertable and a 'normal' table超表和“普通”表之间多对多关系的替代方案
【发布时间】:2020-06-19 17:04:25
【问题描述】:

我试图在名为“measurements”的超表和名为“recipe”的表之间创建多对多关系。

一个测量可以有多个配方,一个配方可以连接到多个测量。

DROP TABLE IF EXISTS measurement_ms;
CREATE TABLE IF NOT EXISTS measurement_ms
(
    id                      SERIAL,
    value                   VARCHAR(255) NULL,
    timestamp               TIMESTAMP(6) NOT NULL,
    machine_id              INT          NOT NULL,
    measurement_type_id     INT          NOT NULL,
    point_of_measurement_id INT          NOT NULL,
    FOREIGN KEY (machine_id) REFERENCES machine (id),
    FOREIGN KEY (measurement_type_id) REFERENCES measurement_type (id),
    FOREIGN KEY (point_of_measurement_id) REFERENCES point_of_measurement (id),
    PRIMARY KEY (id, timestamp)
);

CREATE INDEX ON measurement_ms (machine_id, timestamp ASC);
CREATE INDEX ON measurement_ms (measurement_type_id, timestamp ASC);
CREATE INDEX ON measurement_ms (point_of_measurement_id, timestamp ASC);
-- --------------------------------------------------------------------------
-- Create timescale hypertable
-- --------------------------------------------------------------------------
SELECT create_hypertable('measurement_ms', 'timestamp', chunk_time_interval => interval '1 day');


DROP TABLE IF EXISTS recipe;
CREATE TABLE IF NOT EXISTS recipe 
(
    id                      SERIAL PRIMARY KEY,
    name                    VARCHAR(255) NOT NULL,
    type                    VARCHAR(255) NOT NULL,
    code                    INT NOT NULL
);


DROP TABLE IF EXISTS measurement_recipe;
CREATE TABLE IF NOT EXISTS measurement_recipe
(
    id                          SERIAL  PRIMARY KEY,
    measurement_id              INT     NOT NULL,
    recipe_id                   INT     NOT NULL
    FOREIGN KEY (recipe_id) REFERENCES recipe(id),
    FOREIGN KEY (measurement_id) REFERENCES measurement_ms(id)
);

CREATE INDEX fk_measurement_recipe_measurement ON measurement_recipe (measurement_id ASC);
CREATE INDEX fk_measurement_recipe_recipe ON measurement_recipe (recipe_id ASC);

如上所示的 SQL 脚本是我要连接的表。由于时间尺度的限制,上面的解决方案不起作用。

Timescale 有一个限制,即您不能使用超表值作为外键。 是否有替代解决方案可以在不实际使用多对多关系的情况下在表之间创建多对多关系。

【问题讨论】:

  • 关系是什么意思? recipe 的值是否与 measurement 同时出现?
  • @k_rus 是的,配方值与测量值同时出现,您可以将配方视为测量的标识符。例如,测量可以针对产品。如果是这种情况,配方将包含产品类型、唯一代码和产品名称
  • 感谢您的澄清。一个测量可以有多个配方是如何发生的?由于它们结合在一起,我想知道食谱(或食谱 ID)是否可以与测量值存储在同一行中。
  • 我收到了一个大的 json 数据数组。在那个数组中,我有一个带有配方的数组,这些配方都指定了我收到的数据类型。测量可以基于多个配方。例如它是什么产品,它存放在什么盒子里。这些都是我们的食谱。也许配方术语描述性不够。
  • 感谢您的确认。听起来上述模式是传入数据的规范化。我猜你有查询,需要这种规范化,并且保持数据非规范化会使查询更加困难,对吧?

标签: sql postgresql timescaledb


【解决方案1】:

TimescaleDB 专为时间序列数据而设计,其中每个点通常都附加到某个时间点并包含所有相关数据。将每个点链接到已经存在的元数据是很常见的,但是,相反的做法并不常见。 TimescaleDB 通过分块数据针对时间序列数据进行了优化,因此 DML 和许多选择查询不需要触及所有块。但是,在超表中维护外键约束可能需要在每次插入引用表 measurement_recipe 时触及所有块。

该问题的用例是具有复杂测量的时间序列。提议的模式似乎是原始模式的规范化。我想它简化了测量数据的查询。我看到了两种处理复杂测量的方法:

  1. 借助 JSONB 或数组等复杂结构,保持数据非规范化并将配方和测量值存储在 measurement 表中的单行或几行中。缺点是某些查询很难编写,并且可能无法定义一些连续的聚合。
  2. 按照问题中的建议进行规范化,但不要强制外键约束。它将允许存储可用于连接表的引用值。由于规范化是作为转换传入复杂数据的步骤自动完成的,因此如果转换代码中没有错误,则将保留约束。这些错误可以通过回归测试来预防。仍然使用规范化模式,因为不允许连接(使用连接维护连续聚合可能需要触及所有块),所以无法使用连续聚合。

我的建议是选择选项 1 并尝试在那里变得聪明。我没有好的建议,因为不清楚 JSON 中的原始数据结构是什么,以及查询是什么。

【讨论】:

  • 感谢所有帮助,我目前正在处理选项 1
猜你喜欢
  • 2011-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多