我刚刚开始使用TimescaleDB,并希望在包含事件的表上创建一个超表。最初,我想遵循传统的模式:
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);
但是,当我尝试使用以下查询创建超表时:
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超表时,在时间戳中可能发生冲突时,什么是正确的方法?
发布于 2021-02-04 08:20:36
如何在非唯一时间戳上创建具有时间分区的TimescaleDB超表?
没有必要在时间维度上创建唯一的约束(不需要唯一的约束)。这样做是可行的:
CREATE TABLE event (
id serial,
ts timestamp with time zone NOT NULL,
details varchar(255) NOT NULL
);
SELECT create_hypertable('event', 'ts');
注意,id
上的主键被移除。
如果要创建唯一约束或主键,则TimescaleDB要求任何唯一约束或主键都包含时间维度。这类似于PostgreSQL在声明式分区中将分区键包含到唯一约束中的限制:
分区表上的唯一约束(因此也包括主键)必须包括所有分区键列。之所以存在此限制,是因为PostgreSQL只能在每个分区中单独强制执行唯一性。
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);
还可以使用整数列作为时间维度。重要的是,此类列具有时间维度属性:值随着时间的推移而增加,这对插入性能非常重要,查询将选择一个时间范围,这对于大型数据库上的查询性能至关重要。常见的情况是存储unix时代。
由于id
在event_hyper
中是串行的,它将随着时间的推移而增加。但是,我怀疑查询是否会选择其上的范围。为了完整起见,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);
发布于 2021-02-06 20:44:12
为了构建@k_rus的答案,这里生成的主键似乎并不是您要寻找的。那我有什么意思?它不只是识别一个独特的details, ts
组合吗?或者有意义的是,有两个值具有相同的时间戳和相同的细节,但不同的ids实际上具有某种语义意义。在我看来,这有点荒谬,在这种情况下,我会在(details, ts)
上做一个主键,它应该为您提供所需的惟一条件。我不知道您的ORM是否会喜欢这样,它们往往过于依赖生成的主键,因为,除其他外,并非所有数据库都支持复合主键。但总的来说,我对这种情况的建议是实际使用具有逻辑意义的复合主键。
现在,如果您真的关心多条在同一时间戳上具有相同细节的消息,我可能会建议一个表结构,如下所示
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
来增加它。
我希望or能够更好地处理这类事情,但是您通常可以诱使ORMs从其他表(或对它们的视图)中读取,因为他们认为不能在那里更新记录等等,这就是为什么他们需要有生成的PK)。然后,这就意味着需要编写一些定制的代码,插入到超表中。这样做通常更好,因为总的来说,我发现ORMs并不总是遵循大容量插入的最佳实践,而且通常不使用批量加载技术。
所以像这样的表,只要从表中选择‘s*就可以让您使用ORM进行读取,编写非常少量的自定义代码到timeseries表和voila中--它可以工作。关系模型的其余部分,即ORM擅长做的部分,可以驻留在ORM中,然后在这里与一些自定义SQL和一些自定义方法进行少量集成。
发布于 2022-06-05 14:21:09
限制是:
Need to make all partition columns (primary & secondary, if any) as a unique key of table.
参考:https://github.com/timescale/timescaledb/issues/447#issuecomment-369371441
在我看来,2选择:
https://stackoverflow.com/questions/66032256
复制相似问题