【问题标题】:Is it possible to index on enum?是否可以对枚举进行索引?
【发布时间】:2020-06-05 02:51:55
【问题描述】:

问题实际上是关于 sql 查询的优化。假设我们有这样定义的表。

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)。但是当我监控 db 资源使用情况时,毫不奇怪,这两个查询的成本很高。

我的问题是是否可以以某种方式将索引放在表上,以便我可以加快查询并节省数据库资源。

我已经简要阅读了 postgresql 文档,但没有好的解决方案。

【问题讨论】:

  • 为了性能优化,请始终从您的 Postgres 版本开始。这里也很重要:这些枚举值的基数和数据库活动的粗略特征。每个时间单位写入多少次?并且:您真的需要SELECT *,还是有限的列列表足够好?那里有任何索引吗?

标签: sql postgresql indexing postgresql-performance


【解决方案1】:

当然可以索引enum 列。但由于通常只有很少的不同值,partial indexes 通常更有效。细节取决于缺失的信息。

例如,假设只有 少数 行带有 notification_sent = false,而您需要检索的只是 id,则此索引将同时服务于两个查询:

CREATE INDEX foo ON good_records (record_status, id)
WHERE notification_sent = false;

如果有大量写入活动,请务必使用积极的 autovacuum 设置 for the table 以防止表和索引膨胀并允许仅索引扫描。

将id 添加到索引中只有当它可以给你index-only scans 时才有意义。

如果您从不过滤 id,请改用 INCLUDE 子句(Postgres 11 或更高版本)。效率稍高:

CREATE INDEX foo ON good_records (record_status) INCLUDE (id)
WHERE notification_sent = false;

相关:

【讨论】:

    猜你喜欢
    • 2021-11-06
    • 2020-04-18
    • 2021-07-16
    • 1970-01-01
    • 2016-06-23
    • 1970-01-01
    • 2014-08-04
    • 1970-01-01
    • 2011-02-08
    相关资源
    最近更新 更多