我应该使用复合主键来加速 PostgreSQL 中基于时间戳的选择吗?

Posted

技术标签:

【中文标题】我应该使用复合主键来加速 PostgreSQL 中基于时间戳的选择吗?【英文标题】:Should I use composite primary key to speed up timestamp-based select in PostgreSQL? 【发布时间】:2020-03-31 05:59:52 【问题描述】:

我在 PostgreSQL 11 中有一张表 worker_activity_events

列1:worker_id integer not null 栏目2:created_at timestamp default now() not null 第三栏:event_type text

每条记录必须有一个worker_idcreated_at。我想经常运行的查询是

SELECT * FROM worker_activity_events
WHERE worker_id = $1
  AND created_at BETWEEN $2 AND $3

为了快速运行查询,添加PRIMARY KEY(worker_id, created_at)是否合理?

一个问题可能是:在一个示例时间戳,生成了同一个工作人员的 2 个事件,第二个事件将因为主键 (worker_id, created_at) 被违反而被拒绝。假设在我的应用上我可以防止这种情况发生。

【问题讨论】:

【参考方案1】:

从数据库理论的角度来看,我会说您应该根据真正唯一标识行的内容来定义主键,而不是基于性能考虑。

因此,如果没有自然主键,请定义一个人工主键,并使用CREATE INDEX 创建查询所需的索引。

但是,在现实生活中,您有时不得不偏离理论理想。如果性能考虑要求您拥有尽可能少的索引,并且您可以使用建议的主键,那就去吧。否则坚持理论 - 过早优化是万恶之源。

【讨论】:

【参考方案2】:

如果不考虑这个因素,主键会是什么?

您可以在(worker_id, created_at) 上创建复合索引。没有理由将其声明为主键只是为了将其作为索引。

但您也可以在(worker_id, created_at, event_type) 上创建索引,甚至可能是主键。该索引应该能够做其他索引可以做的所有事情,甚至更多。除非 event_type 非常宽,否则它不应该大很多。一个缺点是,如果您更新行以仅更改 event_type(这似乎不太可能,仅基于列名),此索引将禁用 Heap-Only-Tuple 优化。

【讨论】:

以上是关于我应该使用复合主键来加速 PostgreSQL 中基于时间戳的选择吗?的主要内容,如果未能解决你的问题,请参考以下文章

Clojure jdbc 创建复合主键

PostgreSQL 简单键与复合键

如何在 SQL 中定义复合主键?

如何在 Room 持久库中使用复合主键时使主键自动递增?

如何识别任何 Mysql 数据库表中的复合主键?

MySQL 中的复合主键性能缺陷