【问题标题】:PostgreSQL Index on JSONJSON 上的 PostgreSQL 索引
【发布时间】:2016-07-04 16:59:50
【问题描述】:

使用 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. create INDEX animal_index ON farm using gist ((animal ->> 'cow'));

我想运行如下查询:

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

并让该查询使用索引。

当我运行这个查询时:

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

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

这样的索引可能吗?

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

【问题讨论】:

    标签: sql json postgresql indexing database-design


    【解决方案1】:

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

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

    假设:

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

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

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

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

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

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

    如果您需要更通用的 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进行测试!

    【讨论】:

    • 谢谢!精彩的答案。我只对第一层感兴趣。该值始终为整数。但是我对其他一些动物很感兴趣。为我感兴趣的每只动物简单地复制这个索引是否有意义?
    • @lnhubbell:对于已知的、静态的、微不足道的数量的动物,这应该是最简单和最有效的解决方案。不过,我会明确地将它们设为部分索引。见上面的附录。
    猜你喜欢
    • 1970-01-01
    • 2012-09-06
    • 2015-06-27
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多