首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在非唯一时间戳上创建具有时间分区的TimescaleDB超表?

如何在非唯一时间戳上创建具有时间分区的TimescaleDB超表?
EN

Stack Overflow用户
提问于 2021-02-03 17:04:56
回答 4查看 7.8K关注 0票数 17

我刚刚开始使用TimescaleDB,并希望在包含事件的表上创建一个超表。最初,我想遵循传统的模式:

代码语言:javascript
运行
复制
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);

但是,当我尝试使用以下查询创建超表时:

代码语言:javascript
运行
复制
SELECT create_hypertable('event', 'ts');

我得到了:ERROR: cannot create a unique index without the column "ts" (used in partitioning)

在进行了一些研究之后,时间戳本身似乎需要成为(或部分)主键。

但是,我不希望时间戳ts是唯一的。这些高频事件很可能在同一微秒内重合( timestamp类型的最大分辨率)。这就是为什么我一开始就研究TimescaleDB的全部原因。

在这种情况下,最佳做法是什么?

我正在考虑可能将serial id保留为主键的一部分,并将其合成如下:

代码语言:javascript
运行
复制
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超表时,在时间戳中可能发生冲突时,什么是正确的方法?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2021-02-04 08:20:36

如何在非唯一时间戳上创建具有时间分区的TimescaleDB超表?

没有必要在时间维度上创建唯一的约束(不需要唯一的约束)。这样做是可行的:

代码语言:javascript
运行
复制
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还单独强制每个块的唯一性。保持块间的唯一性会极大地影响吞食性能。

,解决主键问题的最常用方法是创建一个复合键,并按照问题中的建议包含时间维度。如果不需要时间维度上的索引(不需要时间查询),则可以避免时间维度上的索引:

代码语言:javascript
运行
复制
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时代。

由于idevent_hyper中是串行的,它将随着时间的推移而增加。但是,我怀疑查询是否会选择其上的范围。为了完整起见,SQL将是:

代码语言:javascript
运行
复制
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);
票数 16
EN

Stack Overflow用户

发布于 2021-02-06 20:44:12

为了构建@k_rus的答案,这里生成的主键似乎并不是您要寻找的。那我有什么意思?它不只是识别一个独特的details, ts组合吗?或者有意义的是,有两个值具有相同的时间戳和相同的细节,但不同的ids实际上具有某种语义意义。在我看来,这有点荒谬,在这种情况下,我会在(details, ts)上做一个主键,它应该为您提供所需的惟一条件。我不知道您的ORM是否会喜欢这样,它们往往过于依赖生成的主键,因为,除其他外,并非所有数据库都支持复合主键。但总的来说,我对这种情况的建议是实际使用具有逻辑意义的复合主键。

现在,如果您真的关心多条在同一时间戳上具有相同细节的消息,我可能会建议一个表结构,如下所示

代码语言:javascript
运行
复制
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和一些自定义方法进行少量集成。

票数 2
EN

Stack Overflow用户

发布于 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选择

  1. 按单一列进行分区,该列是唯一的键(例如主键),
  2. 用第二个空间分区键划分,需要使2列成为一个组合的唯一键,
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66032256

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档