sql - JSON 上的 PostgreSQL 索引

使用 Postgres 9.4,我想在 json 列上创建一个索引,该索引将在搜索列中的特定键时使用。

例如,我有一个带有 json 列“动物”的“农场”表。

animals 列有一般格式的 json 对象:

'{"cow": 2, "chicken": 11, "horse": 3}'

我已经尝试了一些索引(分别):

  1. create INDEX animal_index ON farm ((animal ->> 'cow'));
  2. create INDEX animal_index ON farm using gin ((animal ->> 'cow'));
  3. 使用 gist ((animal ->> 'cow')) 在农场创建 INDEX animal_index;

我想运行如下查询:

SELECT * FROM farm WHERE (animal ->> 'cow') > 3;

并让该查询使用索引。

当我运行这个查询时:

SELECT * FROM farm WHERE (animal ->> 'cow') is null;

那么 (1) 索引有效,但我无法让任何索引为不等式工作。

这样的索引可能吗?

农场表仅包含约 5000 个农场,但其中一些包含 100 只动物,对于我的用例而言,查询时间太长。像这样的索引是我能想到的加快查询速度的唯一方法,但也许还有另一种选择。

最佳答案

您的其他两个索引将无法正常工作,因为 ->> operator返回 text,而您显然已经记住了 jsonb gin 运算符类。请注意,您只提到了 json,但实际上需要 jsonb用于高级索引功能。

要制定最佳索引策略,您必须更仔细地定义要覆盖的查询。你只对牛感兴趣吗?还是所有动物/所有标签?哪些运算符是可能的?您的 JSON 文档是否还包含非动物键?这些怎么办?您想在索引中包含牛(或其他)根本没有出现在 JSON 文档中的行吗?

假设:

  • 我们只对第一层嵌套的奶牛感兴趣。
  • 该值始终是有效的整数
  • 我们对没有奶牛的行不感兴趣。

我建议使用功能性 btree 索引,就像您已经拥有的那样,但将值转换为 integer。我认为您不希望将比较评估为 text(其中 '2' 大于 '1111')。

CREATE INDEX animal_index ON farm (((animal ->> 'cow')::int));  -- !

强制转换速记需要额外的一组括号,以使索引表达式的语法明确。

在查询中使用相同的表达式让 Postgres 意识到索引是适用的:

SELECT * FROM farm WHERE (animal ->> 'cow')::int > 3;

如果您需要更通用的 jsonb 索引,请考虑:

  • What's the proper index for querying structures in arrays in Postgres jsonb?

对于已知的、静态的、微不足道的数量的动物(就像您评论的那样),我建议使用部分索引,例如:

CREATE INDEX animal_index ON farm (((animal ->> 'cow')::int))
WHERE (animal ->> 'cow') IS NOT NULL;

CREATE INDEX animal_index ON farm (((animal ->> 'chicken')::int))
WHERE (animal ->> 'chicken') IS NOT NULL;

等等

您可能需要在查询中添加索引条件:

SELECT * FROM farm
WHERE (animal ->> 'cow')::int > 3
AND   (animal ->> 'cow') IS NOT NULL; 

可能看起来多余,但可能是必要的。使用 ANALYZE 进行测试!

https://stackoverflow.com/questions/36075918/

相关文章:

c# - 如何将 IEnumerable 转换为 JSON?

ruby - 将不间断空格转换为 Ruby 中的空格

json - 使用绝对或相对路径在 curl 请求中发送 json 文件

java - 我如何反序列化以 jackson 为单位的时间戳?

jquery - 如何在 jQuery 中使用 json 数据填充下拉列表?

java - 使用 gson 反序列化对象的特定 JSON 字段

java - Spring MVC Controller 中的JSON参数

java - 如何从 JSON 对象中获取日期

jquery - 通过 GET 将 JSON 数组传递给 MVC Web API

java - 对象序列化为 JSON(使用 Gson)。如何在 UpperCamelCase 中设置