我继承了一个非常大且活动的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 > 0
或value <= 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生成的,因此很难确定部分索引应包含哪些列...除非有人对此提出建议那个!
答案 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,供您比较更改前后的情况。