tsrange 上的 2 个 B 树索引或 1 个 GiST 索引——哪个性能更好?

Sau*_*nda 8 postgresql index index-tuning postgresql-9.2 gist-index

我有一个表,它使用列存储预订数据starts_atends_at每当我查询表以查找重叠预订时,我都可以选择使用以下查询之一:

SELECT * FROM reservations
WHERE starts_at < '2014-01-03 00:00:00'
AND   ends_at   >='2014-01-01 00:00:00';
Run Code Online (Sandbox Code Playgroud)

或者

SELECT * FROM reservations
WHERE tsrange(starts_at, ends_at) && ('2014-01-01 00:00:00', '2014-01-03 00:00:00')
Run Code Online (Sandbox Code Playgroud)

我在starts_atends_at列上有常规的 B 树索引,因此第一个查询总是使用它们。但是,除非我在 tsrange 上定义功能性 GiST 索引,否则第二个查询会执行完整扫描。

create index tsrange_idx on reservations using gist(tsrange(starts_at, ends_at)); 
Run Code Online (Sandbox Code Playgroud)

我的问题是,随着表的增长,哪个索引会更快?查看查询执行计划,答案可能很明显,但我不精通读取EXPLAIN ANALYZE输出。

Erw*_*ter 14

带有 B 树索引的时间戳

我建议第三个选项:只要您的表包含两timestamp列(似乎已定义NOT NULL),我就会使用具有相反排序顺序的单个多列索引(如果没有其他考虑因素适用):

CREATE INDEX reservations_range_idx ON reservations using gist(starts_at, ends_at DESC);
Run Code Online (Sandbox Code Playgroud)

这些相关答案中的更多内容:

至于查询,请查看SQL 标准运算符OVERLAPS

SELECT * FROM reservations
WHERE (starts_at, ends_at) OVERLAPS ('2014-01-01 00:00:00', '2014-01-03 00:00:00');
Run Code Online (Sandbox Code Playgroud)

更多关于SO的相关问题:

应该比两个 B 树索引快。更少的磁盘空间和更便宜的维护。写操作的负担小

带 GiST 索引的范围类型

对于大表,范围类型GiST 索引很可能更快,因为它可以更好地扩展。但是,磁盘上的存储空间要大得多,索引维护的成本也更高。

如果您走那条路线,将您的时间戳存储为范围(tsrangetstzrange)开始会更有效。没有功能方面的普通 GiST 索引要快一些。

CREATE TABLE reservation (
  reservation_id serial PRIMARY KEY
 ,span tsrange
 , ...
);

CREATE INDEX reservation_span_gist_idx on reservations USING GiST (span);
Run Code Online (Sandbox Code Playgroud)

使用&&“重叠”运算符,您已在问题中显示:

SELECT *
FROM   reservation 
WHERE  span && ('2014-01-01 00:00:00', '2014-01-03 00:00:00');
Run Code Online (Sandbox Code Playgroud)

此外,您可能对排除约束感兴趣,以通过设计排除重叠,它自动实现了与上面类似的 GiST 索引。手册中有一个代码示例。关于 SO 的相关答案有更多详细信息: