PostgreSQL Index on JSON
使用Postgres 9.4,我想在json列上创建一个索引,该索引将在搜索列中的特定键时使用。
例如,我有一个带有json列'animals'的'farm'表。
animals列具有一般格式的json对象:
1 | '{"cow": 2,"chicken": 11,"horse": 3}' |
我已经尝试了许多索引(单独):
1 2 3 | (1) CREATE INDEX animal_index ON farm ((animal ->> 'cow')); (2) CREATE INDEX animal_index ON farm USING gin ((animal ->> 'cow')); (3) CREATE INDEX animal_index ON farm USING gist ((animal ->> 'cow')); |
我想运行如下查询:
1 | SELECT * FROM farm WHERE (animal ->> 'cow') > 3; |
并让该查询使用索引。
当我运行此查询时:
1 | SELECT * FROM farm WHERE (animal ->> 'cow') IS NULL; |
然后(1)索引起作用,但我不能让任何索引适用于不等式。
这样的指数可能吗?
农场表只包含约5000个农场,但其中一些包含100个动物,查询对我的用例来说只需要太长时间。 像这样的索引是我能想到的加速查询的唯一方法,但也许还有另一种选择。
您的其他两个索引将无法正常工作,因为
要制定出最佳的索引策略,您必须更详细地定义要覆盖的查询。你只对奶牛感兴趣吗?还是所有动物/所有标签?哪些运营商可能?您的JSON文档是否还包含非动物密钥?怎么办?是否要在索引中包含行(其中cows(或其他)根本没有出现在JSON文档中?
假设:
- 我们只对第一级筑巢的奶牛感兴趣。
-
该值始终为有效
integer 。 - 我们对没有奶牛的行感兴趣。
我建议使用功能性btree索引,就像你已经拥有的那样,但是将值转换为整数。我不认为您希望比较评估为
1 | CREATE INDEX animal_index ON farm (((animal ->> 'cow')::INT)); -- ! |
转换速记需要额外的括号集,以使索引表达式的语法明确无误。
在查询中使用相同的表达式使Postgres意识到索引适用:
1 | SELECT * FROM farm WHERE (animal ->> 'cow')::INT > 3; |
如果您需要更通用的
- 在Postgres jsonb中查询数组结构的正确索引是什么?
对于一个已知的,静态的,微不足道的动物(就像你评论过的那样),我建议使用以下部分索引:
1 2 3 4 5 | 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; |
等等。
您可能必须将索引条件添加到查询中:
1 2 3 | SELECT * FROM farm WHERE (animal ->> 'cow')::INT > 3 AND (animal ->> 'cow') IS NOT NULL; |
似乎多余,但可能是必要的。用