BIGINT列的最有效索引仅通过正/负符号过滤/查询过吗?

时间:2019-02-23 06:53:24

标签: database postgresql indexing

我继承了一个非常大且活动的PostgreSQL表,其中的BIGINT列包含样本的标量度量,如下所示:

CREATE TABLE sample (
    id       SERIAL    PRIMARY KEY,
    name     TEXT      NOT NULL,

    ...
);

CREATE TABLE measurement (
    id       SERIAL    PRIMARY KEY,
    sampleid INTEGER   NOT NULL,
    value    BIGINT    NOT NULL,
    created  TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW(),

    ...

    FOREIGN KEY (sampleid) REFERENCES sample (id)
);

CREATE INDEX ix_measurement_created ON measurement (created);

用户首先根据measurement.value是否大于零进行查询,然后再根据其他条件进行查询。这些查询原本非常缓慢。

添加CREATE INDEX ix_measurement_value ON measurement (value);可以将性能提高近十倍。

我应该对此结果感到满意,但我不禁感到这不是最有效的解决方案。实际上,存储在列中的实际值是不相关的,因为99%的请求是:

  • ... 始终首先作用域为value > 0value <= 0
  • ... 从不查找特定范围内的值。
  • ... 从不寻找特定值。

以下任何一种方法会更有效吗?

  • 单个 index expression,用于:

    • CREATE INDEX ix_measurement_pos ON measurement (value > 0);
  • 单独索引表达式

    • CREATE INDEX ix_measurement_pos ON measurement (value > 0);
    • CREATE INDEX ix_measurement_neg ON measurement (value <= 0);

我不确定如何足够好地模拟生产环境的统计数据/负载以自行评估方法(对此也将提供建议!)。

编辑:我忘了提到查询是由我无法控制的ORM生成/发出的-上面的sample / measurement连接只是一件非常大而可怕的事情的一部分。

编辑#2:根据供应商的要求,这是PostgreSQL 9.3数据库,不能升级到9.4以上。

编辑#3:建议使用partial index,但是由于查询是ORM生成的,因此很难确定部分索引应包含哪些列...除非有人对此提出建议那个!

1 个答案:

答案 0 :(得分:0)

没有看到您关注的特定查询,很难解决:

  

[这些特定指标]会更有效吗? […]我不确定如何足够好地模拟生产环境的统计数据/负载,以自行评估方法(也将提供建议!)。

这似乎是问题的症结所在。

要评估对特定查询有帮助的内容,您希望通过using EXPLAIN on that specific query获得执行计划。

如果您想了解以下内容的内部工作原理:

SELECT count(sampleid)
FROM measure
WHERE value > 0
;

您使用EXPLAIN语句,指定输出中应包含哪些行为。例如:

EXPLAIN (ANALYZE, BUFFERS, COSTS)
SELECT count(sampleid)
FROM measure
WHERE value > 0
;

利用该输出(如果您担心性能的其他方面,可以使用其他选项作为输出),然后可以寻求建立一个索引来解决查询执行的某些特定部分。

然后,要验证您的索引是否已改善了所需的性能,您需要一些测试运行器,该运行器将在您提出更改之前和之后对服务器进行查询。这将为您提供performance benchmark,供您比较更改前后的情况。