如何加快大表上的Postgres查询

时间:2019-03-30 19:44:27

标签: json postgresql performance

我有一个约140万行的表。每行大约有5列具有常规信息,而第6列具有约1700个JSON键值对。

我正在通过选择存在特定键值的行从称为所有权的列中构建一些摘要。下面的查询在14.5秒内运行

SELECT ownership,
SUM (TO_NUMBER(jsonfield->>'firstvalue','9G999g999')) AS total
FROM
mytable
WHERE
jsonfield->>'firstvalue' IS NOT NULL
group by ownership

我的查询会更大,我知道我需要对jsonfield中的许多键值进行选择。例如,如果添加另一个键值,查询时间将增加到22.9s

SELECT ownership,
SUM (TO_NUMBER(jsonfield->>'firstvalue','9G999g999')) AS total,
SUM (TO_NUMBER(jsonfield->>'secondvalue','9G999g999')) AS totaltwo
FROM
mytable
WHERE
jsonfield->>'firstvalue' IS NOT NULL
OR
jsonfield->>'secondvalue' IS NOT NULL
group by ownership

在某些情况下,我需要查询jsonfield中的数百个潜在值。关于如何优化查询以加快速度的任何建议?

下面的答案很不错。作为一个供参考,我必须先将json转换为jsonb,然后才能创建索引。我首先创建了一个名为jsonbsummary的json列的副本,然后将其转换为jsonb

ALTER TABLE mytable
  ALTER COLUMN jsonbsummary
  SET DATA TYPE jsonb
  USING jsonbsummary::jsonb;

作为一个附加的FYI-最初耗时22秒以上的带有分组的查询现在可以在200毫秒内使用GIN索引运行!见下文

SELECT ownership,
SUM (TO_NUMBER(jsonbsummary->>'firstvalue','9G999g999')) AS total,
SUM (TO_NUMBER(jsonbsummary->>'secondvalue','9G999g999')) AS totaltwo
FROM
mytable
WHERE
jsonbsummary ?| array['firstvalue','secondvalue']
group by ownership

1 个答案:

答案 0 :(得分:3)

您需要在JSONB列上添加一个GIN index

CREATE INDEX idx_json ON mytable USING GIN (jsoncolumn);

要检查密钥是否存在,您需要使用?| operator,它可以利用该索引:

select ...
from mytable
where jsoncolumn ?| array['firstvalue', 'secondvalue'];

那等于您的OR条件。如果要查找包含所有这些键的行,请改用?&