【问题标题】:Efficient way of querying string and number field from PostgreSQL's json field从 PostgreSQL 的 json 字段中查询字符串和数字字段的有效方法
【发布时间】:2021-07-30 13:01:24
【问题描述】:

我们在 postgres 中使用了 json 字段,因为我们有动态字段。字段只能是字符串或数字类型。我们在表中有数十亿行,因此查询工作太慢。我们无法添加索引,因为我们不知道查询中使用的字段名称,并且查询将在运行时动态构建。

表格设计如下,

id - integer
workspace_id - integer
data - json
created_at - timestamp
updated_at - timestamp

json字段中存储的数据如下,

{"age": 21, "city": "London", "name": "ABC", "test_filed1": "text",...}

字符串字段示例:

SELECT users.* 
FROM users 
WHERE users.workspace_id = 1 
  AND data ->> 'city' = 'London' 
ORDER BY users.id DESC 
LIMIT 50;

数字字段示例:

SELECT users.* 
FROM users 
WHERE users.workspace_id = 1 
  AND CAST(data ->> 'age' AS NUMERIC) = 21 
ORDER BY users.id DESC 
LIMIT 50;

当我们使用->> 运算符获取数据时,它会自动将结果类型转换为字符串。例如,当我得到像data ->> 'age' 这样的年龄时,结果值将被类型转换为'21',尽管它存储为数字值。如果我们需要检查任何与数字相关的条件,尽管我们将年龄数据以数字格式存储在 json 字段中,但我们需要键入 cast(如示例中所述)以检查大于、小于。也用于检查字符串,它也在对::text进行类型转换。

由于我以适当的格式存储了数据(字符串使用引号并将数字存储为不带引号的数字),有没有更好的方法来获取存储在 DB 中的数据而不是类型转换?这样我就可以在没有类型转换的情况下执行与数字相关的条件。

注意:我已经为workspace_id添加了索引。

【问题讨论】:

    标签: json postgresql performance query-optimization


    【解决方案1】:

    嗯,->> always 返回一个 text 值 - 这就是它的实现方式(它并不是真正“转换”值)。

    JSON 并没有真正的数据类型概念,因此 Postgres 中没有运算符可以在每次使用 JSON 时从 JSON 中提取值时产生不同的数据类型。由于所有内容都可以表示为text,这就是->> 返回的内容。

    这是您为数据模型去规范化所付出的代价。

    但是,相等比较可以以不同的方式进行(当您将列转换为应该以它开头的jsonb 时)。

    SELECT users.* 
    FROM users 
    WHERE users.workspace_id = 1 
      AND data::jsonb @> '{"city": "London"}'
    ORDER BY users.id DESC 
    LIMIT 50;
    
    SELECT users.* 
    FROM users 
    WHERE users.workspace_id = 1 
      AND data::jsonb @> '{"age": 21}'
    ORDER BY users.id DESC 
    LIMIT 50;
    

    @> 可以在 JSONB 值上使用 GIN 索引,例如

    create index on users (data::jsonb);
    

    显然,这受制于通常的索引使用规则。并非所有创建的索引都在使用中。

    (但最好将data转换为jsonb以避免一直转换)

    【讨论】:

    • 无法从 json 迁移到 jsonb,因为我们的代码库和表大小(超过 400GB)非常庞大。如果有其他方法,请提出建议。
    • @empr:那么你必须忍受演员阵容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-27
    • 2013-02-08
    • 2010-09-07
    • 2021-07-04
    • 2014-07-22
    • 1970-01-01
    相关资源
    最近更新 更多