【问题标题】:Can PostgreSQL json index arrays using b-tree indices?PostgreSQL json 可以使用 b-tree 索引来索引数组吗?
【发布时间】:2020-12-14 00:30:28
【问题描述】:

我测试了以下脚本:

CREATE TABLE test (
    id serial NOT NULL PRIMARY KEY,
    obj jsonb NOT NULL
);

INSERT INTO test (obj)
VALUES('{ "a": "foo", "b": ["cat" , "dog", "horse"]}'),
      ('{ "a": "bar", "b": ["cat" , "dog", "mouse"]}'),
      ('{ "a": "baz", "b": ["dog" , "pig", "cow"]}');
      
create index on test (((obj #>> '{a}')), ((obj #>> '{b}')) );     

EXPLAIN ANALYZE SELECT *
FROM test
WHERE  (obj #>> '{a}') = 'bar'  AND  (obj #> '{b}') ? 'mouse';

实际上我插入了几千行只是为了确保 pg 尽可能使用索引。

我希望查询将使用索引的两个路径。它不是。即使我将索引定义替换为:

create index on test (((obj #>> '{a}')), ((obj #> '{b}')) );

它将仅使用定义的 {a} 部分,然后对我的查询的 {b} 部分使用过滤。

我知道至少有一个 (xml) 数据库,在多次出现的元素上使用 btree 索引定义只会在每次出现的索引中放置一个键(结合其余索引值)。当然,这会产生一个大索引,但查询又好又快。

当然,对于 pg/json,我可以使用 GIN 索引,但总的来说我更喜欢多个目标索引。

所以,我的问题是双重的:

  • 当我根据上述语句创建索引时,pg/json 究竟意味着什么?因为 pg 愉快地接受了索引的创建,所以没有错误。
  • 是否可以使用 btree 索引对数组进行索引并使其支持使用包含数组的谓词进行查询?

【问题讨论】:

  • 查询obj #>> '{a}') = 'bar'返回多少行。
  • GIN 索引正是为这个用例创建的。
  • 如果我尝试 "= 'bar'" 查询,则返回 0 行。该谓词实际上是您将在 xquery/xml 中用于此类搜索的内容,并且在我通过 b-tree 索引引用的 XML 数据库中得到支持。

标签: json postgresql indexing


【解决方案1】:

不能使用 b 树索引,因为您正在搜索数组元素。

与 GIN 索引协调并修改查询:

CREATE INDEX ON test USING gin (obj);

SELECT * FROM test
WHERE obj @> '{ "a": "bar", "b": [ "mouse" ] }';

如果您不喜欢 GIN 索引,则不应使用 JSON。

【讨论】:

  • 我只喜欢其中一个 :-),所以我只是想验证一下。然后是 GIN 索引。感谢您的确认。
  • @Mark:GIN 索引的一大优势是您只需要一个涵盖范围广泛的查询谓词的索引。您不必在每次有新类型的查询时都创建新索引。如果您添加更多键并想要查询它们,也可以使用该索引。或者,如果您重命名密钥。
猜你喜欢
  • 2011-05-02
  • 1970-01-01
  • 2015-10-13
  • 1970-01-01
  • 2015-05-08
  • 2011-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多