Sau*_*nda 8 postgresql index index-tuning postgresql-9.2 gist-index
我有一个表,它使用列存储预订数据starts_at
,ends_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_at
和ends_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
我建议第三个选项:只要您的表包含两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 索引很可能更快,因为它可以更好地扩展。但是,磁盘上的存储空间要大得多,索引维护的成本也更高。
如果您走那条路线,将您的时间戳存储为范围(tsrange
或tstzrange
)开始会更有效。没有功能方面的普通 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 的相关答案有更多详细信息: