【问题标题】:Faster search by indexing timestamp column on postgresql?通过在 postgresql 上索引时间戳列来更快地搜索?
【发布时间】:2021-05-04 04:52:27
【问题描述】:

我有一个 PostgreSQL 数据库和一个包含事件的表。这些事件有列 end_time,它有一个类型的时间戳(没有时区信息)。在我的应用程序中,我经常查询表,试图选择未来发生的所有事件。所以基本上我在做这种 SQL 查询:

SELECT * FROM events WHERE end_time >= ?::timestamp

我目前在 end_time 列上没有索引。我担心一旦我的表行大小变大(实际上它已经做了很多),未来事件的搜索查询会变慢吗?因为现在数据库搜索必须遍历所有行以选择将来发生(或更准确地说,结束)的行。我以前使用过索引,但不能说我最熟悉它们。我想知道通过创建默认的 Postgres 索引来索引 end_time 列是否会提高查询的性能?我还没有真正的问题,但我不想等待它在数据量增加时出现。因为那时有点晚了,至少最终应用的用户体验已经下降了。

我想指出我确实使用了没有时区的时间戳,因为我的应用程序始终假定为当地时间,我不需要时区信息。但我听说它可能对索引有影响?此外,我的时间戳目前不受任何限制。所以他们理论上可以从现在到无限的未来。我想知道设置一些约束是否可以使索引更好?像活动时间应该在 15 年内还是什么?

另一种选择是将事件移动到另一个过去的表(archived_events)。这样事件的表大小就不会变得太大。例如,我可以有一个定期执行的 cron 作业。

我还听说对数据库运行分析/解释实际上可以提高它的性能?如果是这种情况,我应该多久运行一次?

PostgreSQL 版本:12.3

【问题讨论】:

  • 实际定义(CREATE TABLECREATE INDEX 语句)是规范的事实来源。优于一切口头描述。请务必公开您的 Postgres 版本。

标签: postgresql indexing timestamp postgresql-performance


【解决方案1】:

我想知道索引 end_time 列 [...] 是否会提高查询的性能?

如果 Postgres 预计只有百分之几或更少符合条件(将来有 end_time),它将在“索引扫描”或“位图索引扫描”中使用列上的索引。

如果这个估计不太远,它实际上也会提高性能。这就是为什么您应该按照默认设置启用 autovacuum:以使列统计信息保持最新。

如果您实际上并不需要查询 (SELECT *) 中的所有列(您通常不需要),那么只列出您实际需要的列以使其更快。甚至可能允许“仅索引扫描”。见:

我想知道设置一些约束是否可以使索引更好?像活动时间应该在 15 年内还是什么?

不。对您的查询没有任何影响。未来的行数是决定因素。

我会将事件移至另一个过去的表 (archived_events) ...?

Btree 索引可以很好地扩展。这意味着,只要只有几行符合条件,消除的行数就无关紧要。如果您的表巨大(数百万或数十亿行)并且其中大部分是过去的,那么partial index 可能会更好,这主要是由于索引大小的减少和索引维护成本。

特殊难度:“现在”是一个动态值。索引定义需要不可变值。解决方法是选择一个任意的“现在”来切断大部分行。比如:

CREATE INDEX ON events(end_time) WHERE end_time > '2021-01-30';

现代 Postgres 足够聪明,可以理解它可以将索引用于未来日期。 旧版本可能需要一个多余的WHERE 子句,以使其了解部分索引适用:

SELECT * FROM events
WHERE  end_time >= ?::timestamp
AND    end_time > '2021-01-30';  -- match index

索引的实用性会随着时间的推移而下降,这也取决于行流失率。您可能会不时重新创建索引以切断更多行。


除此之外,不要让类型名称timestamp with time zone 误导您。它不存储时区信息。它通常是最佳选择。见:

【讨论】:

  • “如果 Postgres 预计只有百分之几或更少的人符合条件(未来有 end_time),它将在“索引扫描”或“位图索引扫描”中使用列上的索引。只是为了清楚我正确理解这一点:如果它存在,它将使用索引,如果它不是首先手动创建的,它不会自动使用?此外,我认为只有百分之几或更少的人符合条件。但 Postgres 是否期待,我不知道?
  • 这是一个很好的答案,谢谢!综上所述,我应该使用索引,使用不时重新创建的部分索引会更好。
  • @VilleMiekk-oja:显然,索引只能在创建后使用。它是自动维护的。部分索引更适合这个特定的查询。但是,如果您还对较早的日期有查询,则最好使用完整索引。 EXPLAIN 让您查看实际的查询计划。
猜你喜欢
  • 2015-03-08
  • 1970-01-01
  • 2012-05-23
  • 2015-06-27
  • 1970-01-01
  • 2011-03-07
  • 2015-03-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多