当前位置: 首页 > 知识库问答 >
问题:

Postgres 9.4 jsonb数组作为表

刘选
2023-03-14

我有一个json数组,其中包含大约1000个结构元素“id: aaa, example: bbb, value: ccc”。

{"_id": 37637070
, "data": [{"oid": "11.5.15.1.4", "value": "1", "instance": "1.1.4"}
         , {"oid": "11.5.15.1.9", "value": "17", "instance": "1.1.4"}
         , {"oid": "12.5.15.1.5", "value": "0.0.0.0", "instance": "0"}]}

每个json数组的oid和实例都是唯一的。如果给我更改结构的选项,我会将格式更改为键:值:

{"11.5.15.1.4-1.1.4":"1", "11.5.15.1.9-1.1.4": "17", "12.5.15.1.5-0": "0.0.0.0"}

但是,如果我需要保留旧结构

>

  • 从阵列中获取特定oid的最快方法是什么?

    获取包含oid实例value3列的表的最快方法是什么。或者更好的是以oid实例作为列标题的数据透视表。

    对于2。我尝试了以下方法,但在大桌子上速度很慢:

    select *
    from (
       select a->>'oid' oid, a->>'instance' instance, a->>'value' value1, id
       from (
          select jsonb_array_elements(config#>'{data}')  a, id
          from configuration
          ) b
       ) c
    where  oid = '1.3.6.1.4.1.7352.3.10.2.5.35.3' and instance = '0' and value1 <> '1';
    
  • 共有1个答案

    施飞鸿
    2023-03-14

    缺少表定义。假设:

    CREATE TABLE configuration (
      config_id serial PRIMARY KEY
    , config jsonb NOT NULL
    );
    

    要查找给定oid和实例的a值及其行,请执行以下操作:

    SELECT c.config_id, d->>'value' AS value
    FROM   configuration c
         , jsonb_array_elements(config->'data') d  -- default col name is "value"
    WHERE  d->>'oid'      = '1.3.6.1.4.1.7352.3.10.2.5.35.3'
    AND    d->>'instance' = '0'
    AND    d->>'value'   <> '1'
    

    这是一个隐式横向连接。比较:

    • 查询JSON类型内的数组元素

    2)获取包含id实例值3列的表的最快方法是什么。

    我假设使用jsonb\u populate\u recordset(),然后可以在表定义中提供数据类型。假设全部为文本:

    CREATE TEMP TABLE data_pattern (oid text, value text, instance text);
    

    也可以是持久化(非临时)表。此选项仅适用于当前会话。然后:

    SELECT c.config_id, d.*
    FROM   configuration c
         , jsonb_populate_recordset(NULL::data_pattern, c.config->'data') d
    

    这就是全部。重写的第一个查询:

    SELECT c.config_id, d.*
    FROM   configuration c
         , jsonb_populate_recordset(NULL::data_pattern, c.config->'data') d
    WHERE  d.oid      = '1.3.6.1.4.1.7352.3.10.2.5.35.3'
    AND    d.instance = '0'
    AND    d.value   <> '1';
    

    但这比第一个查询慢。使用更大的表实现性能的关键是索引支持:

    您可以很容易地为规范化(翻译)表或您在问题中提出的备选布局编制索引。为当前布局编制索引不是很明显,但也是可能的。为了获得最佳性能,我建议只在jsonb\u path\u ops操作符类的数据键上建立一个函数索引。根据文件:

    jsonb\u ops和GIN索引的技术区别在于前者为数据中的每个键和值创建独立的索引项,而后者仅为数据中的每个值创建索引项。

    这将为性能创造奇迹:

    CREATE INDEX configuration_my_idx ON configuration
    USING gin ((config->'data') jsonb_path_ops);
    

    人们可能会认为,只有与JSON数组元素完全匹配才能工作,例如:

    SELECT * FROM configuration
    WHERE  (config->'data') @> '[{"oid": "1.3.6.1.4.1.7352.3.10.2.5.35.3"
                                , "instance": "0", "value": "1234"}]';
    

    请注意所提供值的JSON数组表示法(包含所需的值)

    但具有键子集的数组元素也可以工作:

    SELECT * FROM configuration
    WHERE  (config->'data') @> '[{"oid": "1.3.6.1.4.1.7352.3.10.2.5.35.3"
                                , "instance": "0"}]'
    

    困难的部分是合并看似不显眼的附加谓词<代码>值

    SELECT c.*, d->>'value' AS value
    FROM   configuration c
         , jsonb_array_elements(config->'data') d
    WHERE  (config->'data') @> '[{"oid": "1.3.6.1.4.1.7352.3.10.2.5.35.3", "instance": "0"}]'
    AND    d->>'oid'      = '1.3.6.1.4.1.7352.3.10.2.5.35.3'  -- must be repeated
    AND    d->>'instance' = '0'                               -- must be repeated
    AND    d->>'value'   <> '1'                               -- here we can rule out
    

    瞧。

    如果表很大,索引大小可能是决定因素。您可以将此特殊解决方案的性能与功能索引进行比较:

    此函数用于从给定的jsonb值中提取oid实例组合的Postgres数组:

    CREATE OR REPLACE FUNCTION f_config_json2arr(_j jsonb)
      RETURNS text[] LANGUAGE sql IMMUTABLE AS
    $func$
    SELECT ARRAY(
       SELECT (elem->>'oid') || '-' || (elem->>'instance')
       FROM   jsonb_array_elements(_j) elem
       )
    $func$
    

    我们可以在此基础上构建html" target="_blank">功能索引:

    CREATE INDEX configuration_conrfig_special_idx ON configuration
    USING  gin (f_config_json2arr(config->'data'));
    

    并在此基础上进行查询:

    SELECT * FROM configuration
    WHERE  f_config_json2arr(config->'data') @> '{1.3.6.1.4.1.7352.3.10.2.5.35.3-0}'::text[]
    

    这个想法是索引应该小得多,因为它只存储没有键的组合值。数组包含运算符@

    与此相关答案中的第一个解决方案类似(但更专业):

    • 在JSON数组中查找元素的索引
    • 我不会使用oid作为列名,因为它在Postgres中也用于内部目的

     类似资料:
    • 问题内容: 我有一个json数组,其中包含大约1000个结构为“ oid:aaa,instance:bbb,value:ccc”的元素。 并且每个json数组都是唯一的。如果可以更改结构,可以将格式更改为 key:value : 但是,如果我需要保留旧结构 从阵列中获取特定信息的最快方法是什么? 什么是得到一个表的3列最快的方式,和。甚至更好的是将oid + instance作为列标题的数据透视表

    • 我想在java中使用集合而不是数组来序列化postgreSQL数组。例如INT[]、varchar(256)[]到java集合和Collection。 SQL: 创建表array_tests(string_array varchar(256)[]); 我在生成的类中出错:

    • 问题内容: 因此,在Python和Ruby中,使用splat运算符(*)可以将数组解压缩为参数。在Javascript中,有.apply()函数。Go中有没有一种将数组/切片作为函数参数解包的方法?任何资源也将是巨大的! 与此类似: 如果我犯了语法错误或各种错误,我深表歉意。我是新手。 问题答案: 您可以使用类似于C的vararg语法: 现在,您可以根据需要汇总任意多的内容。调用函数后,请注意重要

    • 问题内容: 是否可以在PHP中使数组成为会话变量? 情况是,我有一个表(第1页),其中有些单元格具有指向特定页面的链接。下一页将列出名称(第2页,我想保留在会话数组中)及其相应的复选框。提交此表单后,它将进入一个交易页面(第3页,其中已发布复选框的值保存在数据库中以用于对应名称)。现在,如果我返回首页并单击另一个单元格,则会话数组将包含新名称列表还是旧名称列表? 问题答案: 是的,PHP支持将数组

    • 问题内容: 说我有一个功能组件: 直接将其作为函数调用有什么区别: 与将其称为组件相比: 我对性能影响最感兴趣,React如何在内部对它们进行区别对待,也许对React Fiber中的情况可能有所不同,我听说功能组件的性能得到了提升。 问题答案: 调用它作为函数要快得多,事实上,几个月前就已经有讨论了。在这一点上,功能性反应组件不能是PureComponents,因此没有真正适用于它们的额外优化。

    • 问题内容: 我可以将数组作为url参数传递的最佳方法是什么?我在想这是否可能: 还是这样: 香港专业教育学院阅读示例,但我发现它很混乱: 问题答案: 有一个非常简单的解决方案:。它把您的查询参数作为一个关联数组: 将返回 为您处理所有必需的转义(=> 和=> ),因此此字符串等于。