是否可以在枚举上建立索引?
Is it possible to index on enum?
问题实际上是关于 sql 查询的优化。假设我们有这样定义的 table 。
CREATE TYPE record_type AS ENUM (
'TRANSFER',
'TRADE',
'VOUCHER'
);
CREATE TYPE record_status AS ENUM (
'NEW',
'VALIDATED',
'EXPIRED'
);
CREATE TABLE good_records (
id uuid PRIMARY KEY,
user_id uuid NOT NULL,
type record_type NOT NULL,
status record_status NOT NULL,
amount numeric(36,18) NOT NULL DEFAULT 0,
expired_at timestamp WITH TIME ZONE NOT NULL,
notification_sent boolean DEFAULT false,
);
我想 运行 每 10 分钟进行一次过期检查,也就是说,我会 运行 SELECT * FROM good_records
where record_status = 'NEW' and notification_sent = false
(和 SELECT * FROM good_records where record_status = 'VALIDATED' and notification_sent = false
)。但是当我监控数据库资源使用情况时,这两个查询的成本很高也就不足为奇了。
我的问题是是否可以以某种方式在 table 上建立索引,以便我可以加快查询速度并节省数据库资源。
我已经简要阅读了 postgresql 文档,但没有好的解决方案。
当然可以索引 enum
列。但是由于通常只有几个不同的值,partial indexes 通常更有效。详细信息取决于缺少的信息。
例如,假设只有 很少 行 notification_sent = false
,而您需要检索的只是 id
,该索引将同时服务于查询:
CREATE INDEX foo ON good_records (record_status, id)
WHERE notification_sent = false;
如果有大量写入 activity,请务必积极 autovacuum settings for the table 以防止 table 和索引膨胀并允许仅索引扫描。
将 id
添加到索引只有在它可以给你 index-only scans 时才有意义。
如果您从不过滤 id
,请改用 INCLUDE
子句(Postgres 11 或更高版本)。效率稍微高一点:
CREATE INDEX foo ON good_records (record_status) INCLUDE (id)
WHERE notification_sent = false;
相关:
- Optimize Postgres deletion of orphaned records
- Aggressive Autovacuum on PostgreSQL
- Can Postgres use an index-only scan for this query with joined tables?
问题实际上是关于 sql 查询的优化。假设我们有这样定义的 table 。
CREATE TYPE record_type AS ENUM (
'TRANSFER',
'TRADE',
'VOUCHER'
);
CREATE TYPE record_status AS ENUM (
'NEW',
'VALIDATED',
'EXPIRED'
);
CREATE TABLE good_records (
id uuid PRIMARY KEY,
user_id uuid NOT NULL,
type record_type NOT NULL,
status record_status NOT NULL,
amount numeric(36,18) NOT NULL DEFAULT 0,
expired_at timestamp WITH TIME ZONE NOT NULL,
notification_sent boolean DEFAULT false,
);
我想 运行 每 10 分钟进行一次过期检查,也就是说,我会 运行 SELECT * FROM good_records
where record_status = 'NEW' and notification_sent = false
(和 SELECT * FROM good_records where record_status = 'VALIDATED' and notification_sent = false
)。但是当我监控数据库资源使用情况时,这两个查询的成本很高也就不足为奇了。
我的问题是是否可以以某种方式在 table 上建立索引,以便我可以加快查询速度并节省数据库资源。
我已经简要阅读了 postgresql 文档,但没有好的解决方案。
当然可以索引 enum
列。但是由于通常只有几个不同的值,partial indexes 通常更有效。详细信息取决于缺少的信息。
例如,假设只有 很少 行 notification_sent = false
,而您需要检索的只是 id
,该索引将同时服务于查询:
CREATE INDEX foo ON good_records (record_status, id)
WHERE notification_sent = false;
如果有大量写入 activity,请务必积极 autovacuum settings for the table 以防止 table 和索引膨胀并允许仅索引扫描。
将 id
添加到索引只有在它可以给你 index-only scans 时才有意义。
如果您从不过滤 id
,请改用 INCLUDE
子句(Postgres 11 或更高版本)。效率稍微高一点:
CREATE INDEX foo ON good_records (record_status) INCLUDE (id)
WHERE notification_sent = false;
相关:
- Optimize Postgres deletion of orphaned records
- Aggressive Autovacuum on PostgreSQL
- Can Postgres use an index-only scan for this query with joined tables?