如何创建 TimescaleDB Hypertable,并在非唯一时间戳上进行时间分区?

jbx*_*jbx 23 postgresql timescaledb

我刚刚开始使用 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);
Run Code Online (Sandbox Code Playgroud)

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

SELECT create_hypertable('event', 'ts');
Run Code Online (Sandbox Code Playgroud)

我有: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');
Run Code Online (Sandbox Code Playgroud)

这种方法可行,但我不确定这是否是正确的方法,或者我是否正在创建一个复杂的主键,这会减慢插入速度或产生其他问题。

当使用 TimescaleDB 超表时时间戳可能发生冲突时,正确的方法是什么?

k_r*_*rus 22

如何创建 TimescaleDB Hypertable,并在非唯一时间戳上进行时间分区?

无需在时间维度上创建唯一约束(uniqueconstraints not required)。这有效:

CREATE TABLE event (
  id serial,
  ts timestamp with time zone NOT NULL,
  details varchar(255) NOT NULL
);
SELECT create_hypertable('event', 'ts');
Run Code Online (Sandbox Code Playgroud)

请注意,上的主键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);
Run Code Online (Sandbox Code Playgroud)

也可以使用整数列作为时间维度。重要的是,此类列具有时间维度属性:该值随着时间的推移而增加,这对于插入性能很重要,并且查询将选择一个时间范围,这对于大型数据库的查询性能至关重要。常见情况是存储 unix 纪元。

由于idinevent_hyper是SERIAL,它会随着时间的推移而增加。但是,我怀疑查询是否会选择其上的范围。为了完整性,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);
Run Code Online (Sandbox Code Playgroud)