如何在非唯一时间戳上创建具有时间分区的 TimescaleDB Hypertable?
How to create TimescaleDB Hypertable with time partitioning on non unique timestamp?
我刚开始使用 TimescaleDB,想在 table 上创建一个带有事件的 hypertable。
本来我想按照常规的模式:
CREATE TABLE event (
id serial PRIMARY KEY,
ts timestamp with time zone NOT NULL,
details varchar(255) NOT NULL
);
CREATE INDEX event_ts_idx on event(ts);
但是,当我尝试使用以下查询创建 hypertable 时:
SELECT create_hypertable('event', 'ts');
我得到了:ERROR: cannot create a unique index without the column "ts" (used in partitioning)
经过一些研究,似乎时间戳本身需要作为(或部分)主键。
但是,我不希望时间戳 ts
是唯一的。这些高频事件很可能会在同一微秒内重合(timestamp
类型的最大分辨率)。这就是我首先研究 TimescaleDB 的全部原因。
这种情况下的最佳做法是什么?
我正在考虑将 serial id
作为主键的一部分,并像这样组合它:
CREATE TABLE event_hyper (
id serial,
ts timestamp with time zone NOT NULL,
details varchar(255) NOT NULL,
PRIMARY KEY (id, ts)
);
SELECT create_hypertable('event_hyper', 'ts');
这种方法可行,但我不确定这是否是正确的方法,或者我是否正在创建一个复杂的主键,这会减慢插入速度或产生其他问题。
当使用 TimescaleDB hypertables 时时间戳可能发生冲突时,正确的方法是什么?
How to create TimescaleDB Hypertable with time partitioning on non unique timestamp?
不需要在时间维度上创建唯一约束。这有效:
CREATE TABLE event (
id serial,
ts timestamp with time zone NOT NULL,
details varchar(255) NOT NULL
);
SELECT create_hypertable('event', 'ts');
请注意,id
上的主键已删除。
TimescaleDB 要求任何唯一约束或主键都包含时间维度。这类似于 declarative partitioning 中 PostgreSQL 将分区键包含在唯一约束中的限制:
Unique constraints (and hence primary keys) on partitioned tables must include all the partition key columns. This limitation exists because PostgreSQL can only enforce uniqueness in each partition individually.
TimescaleDB 还单独强制每个块的唯一性。保持跨块的唯一性会显着影响摄取性能。
解决主键问题的最常见方法是创建一个复合键并包含问题中建议的时间维度。如果不需要时间维度上的索引(不要只查询时间),那么可以避免时间维度上的索引:
CREATE TABLE event_hyper (
id serial,
ts timestamp with time zone NOT NULL,
details varchar(255) NOT NULL,
PRIMARY KEY (id, ts)
);
SELECT create_hypertable('event_hyper', 'ts', create_default_indexes => FALSE);
也可以使用整数列作为时间维度。重要的是,此类列具有时间维度属性:值随时间增加,这对插入性能很重要,查询将 select 一个时间范围,这对大型数据库的查询性能至关重要。常见的情况是用于存储 unix 纪元。
由于event_hyper
中的id
是SERIAL,所以会随着时间增加。不过,我怀疑查询会select范围就可以了。为了完整起见,SQL 将是:
CREATE TABLE event_hyper (
id serial PRIMARY KEY,
ts timestamp with time zone NOT NULL,
details varchar(255) NOT NULL
);
SELECT create_hypertable('event_hyper', 'id', chunk_time_interval => 1000000);
以@k_rus 的答案为基础,此处生成的主键似乎并不是您要查找的内容。这个id有什么意义?不就是识别一个独一无二的details, ts
组合吗?或者是否可以有意义地存在具有相同时间戳和相同详细信息但实际上具有某种语义含义的不同 ID 的两个值。在我看来,这有点荒谬,在这种情况下,我会在 (details, ts)
上做一个主键,它应该为您提供所需的唯一性条件。我不知道您的 ORM 是否会喜欢这样,它们往往过度依赖生成的主键,因为除其他外,并非所有数据库都支持复合主键。但总的来说,我对这种情况的建议是实际使用具有逻辑意义的复合主键。
现在,如果您真的关心在同一时间戳具有相同详细信息的多条消息,我可能建议使用 table 结构,例如
CREATE TABLE event_hyper (
ts timestamp with time zone NOT NULL,
details varchar(255) NOT NULL,
count int,
PRIMARY KEY (details, ts)
);
你可以用它做一个 INSERT ON CONFLICT DO UPDATE
来增加它。
我希望 ORM 能更好地处理这类事情,但您通常可以欺骗 ORM 从其他 tables 读取(或查看它们,因为它们认为它们无法更新记录等,这就是为什么他们需要生成的 PK)。那么它只是意味着有一些自定义摄取代码可以写入到 hypertable 中。无论如何这样做通常更好,因为一般来说,我发现 ORM 并不总是遵循大容量插入的最佳实践,并且通常不使用批量加载技术。
所以像这样的 table,考虑到 select 的 * 来自 table 应该允许您使用 ORM 进行读取,写一个非常小的需要摄取到时间序列 table 中的自定义代码量,瞧 - 它有效。关系模型的其余部分,即 ORM 擅长的部分,可以存在于 ORM 中,然后在这里进行一些自定义 SQL 和一些自定义方法的小集成。
我刚开始使用 TimescaleDB,想在 table 上创建一个带有事件的 hypertable。 本来我想按照常规的模式:
CREATE TABLE event (
id serial PRIMARY KEY,
ts timestamp with time zone NOT NULL,
details varchar(255) NOT NULL
);
CREATE INDEX event_ts_idx on event(ts);
但是,当我尝试使用以下查询创建 hypertable 时:
SELECT create_hypertable('event', 'ts');
我得到了:ERROR: cannot create a unique index without the column "ts" (used in partitioning)
经过一些研究,似乎时间戳本身需要作为(或部分)主键。
但是,我不希望时间戳 ts
是唯一的。这些高频事件很可能会在同一微秒内重合(timestamp
类型的最大分辨率)。这就是我首先研究 TimescaleDB 的全部原因。
这种情况下的最佳做法是什么?
我正在考虑将 serial id
作为主键的一部分,并像这样组合它:
CREATE TABLE event_hyper (
id serial,
ts timestamp with time zone NOT NULL,
details varchar(255) NOT NULL,
PRIMARY KEY (id, ts)
);
SELECT create_hypertable('event_hyper', 'ts');
这种方法可行,但我不确定这是否是正确的方法,或者我是否正在创建一个复杂的主键,这会减慢插入速度或产生其他问题。
当使用 TimescaleDB hypertables 时时间戳可能发生冲突时,正确的方法是什么?
How to create TimescaleDB Hypertable with time partitioning on non unique timestamp?
不需要在时间维度上创建唯一约束。这有效:
CREATE TABLE event (
id serial,
ts timestamp with time zone NOT NULL,
details varchar(255) NOT NULL
);
SELECT create_hypertable('event', 'ts');
请注意,id
上的主键已删除。
TimescaleDB 要求任何唯一约束或主键都包含时间维度。这类似于 declarative partitioning 中 PostgreSQL 将分区键包含在唯一约束中的限制:
Unique constraints (and hence primary keys) on partitioned tables must include all the partition key columns. This limitation exists because PostgreSQL can only enforce uniqueness in each partition individually.
TimescaleDB 还单独强制每个块的唯一性。保持跨块的唯一性会显着影响摄取性能。
解决主键问题的最常见方法是创建一个复合键并包含问题中建议的时间维度。如果不需要时间维度上的索引(不要只查询时间),那么可以避免时间维度上的索引:
CREATE TABLE event_hyper (
id serial,
ts timestamp with time zone NOT NULL,
details varchar(255) NOT NULL,
PRIMARY KEY (id, ts)
);
SELECT create_hypertable('event_hyper', 'ts', create_default_indexes => FALSE);
也可以使用整数列作为时间维度。重要的是,此类列具有时间维度属性:值随时间增加,这对插入性能很重要,查询将 select 一个时间范围,这对大型数据库的查询性能至关重要。常见的情况是用于存储 unix 纪元。
由于event_hyper
中的id
是SERIAL,所以会随着时间增加。不过,我怀疑查询会select范围就可以了。为了完整起见,SQL 将是:
CREATE TABLE event_hyper (
id serial PRIMARY KEY,
ts timestamp with time zone NOT NULL,
details varchar(255) NOT NULL
);
SELECT create_hypertable('event_hyper', 'id', chunk_time_interval => 1000000);
以@k_rus 的答案为基础,此处生成的主键似乎并不是您要查找的内容。这个id有什么意义?不就是识别一个独一无二的details, ts
组合吗?或者是否可以有意义地存在具有相同时间戳和相同详细信息但实际上具有某种语义含义的不同 ID 的两个值。在我看来,这有点荒谬,在这种情况下,我会在 (details, ts)
上做一个主键,它应该为您提供所需的唯一性条件。我不知道您的 ORM 是否会喜欢这样,它们往往过度依赖生成的主键,因为除其他外,并非所有数据库都支持复合主键。但总的来说,我对这种情况的建议是实际使用具有逻辑意义的复合主键。
现在,如果您真的关心在同一时间戳具有相同详细信息的多条消息,我可能建议使用 table 结构,例如
CREATE TABLE event_hyper (
ts timestamp with time zone NOT NULL,
details varchar(255) NOT NULL,
count int,
PRIMARY KEY (details, ts)
);
你可以用它做一个 INSERT ON CONFLICT DO UPDATE
来增加它。
我希望 ORM 能更好地处理这类事情,但您通常可以欺骗 ORM 从其他 tables 读取(或查看它们,因为它们认为它们无法更新记录等,这就是为什么他们需要生成的 PK)。那么它只是意味着有一些自定义摄取代码可以写入到 hypertable 中。无论如何这样做通常更好,因为一般来说,我发现 ORM 并不总是遵循大容量插入的最佳实践,并且通常不使用批量加载技术。
所以像这样的 table,考虑到 select 的 * 来自 table 应该允许您使用 ORM 进行读取,写一个非常小的需要摄取到时间序列 table 中的自定义代码量,瞧 - 它有效。关系模型的其余部分,即 ORM 擅长的部分,可以存在于 ORM 中,然后在这里进行一些自定义 SQL 和一些自定义方法的小集成。