【问题标题】:What is the performance/logical difference between jsonb_path_match and ->> in where clausewhere 子句中 jsonb_path_match 和 ->> 之间的性能/逻辑差异是什么
【发布时间】:2020-06-15 09:32:20
【问题描述】:

我正在尝试在 PostgreSQL 数据库中查询 FHIR 数据。数据存储在 jsonb 字段中。虽然以下查询产生相同的结果,但我想知道在性能或执行计划方面是否存在任何重大差异。

查询 1 - 使用 ->> 运算符

SELECT resource->'subject' FROM resourcetable 
WHERE resource ->> 'resourceType' = 'MedicationRequest' AND resource ->> 'status' = 'active';

查询 2 - 使用 jsonb_path_match 函数

SELECT jsonb_path_query(resource, '$.subject') from resourcetable 
WHERE jsonb_path_match(resource, '$.resourceType == "MedicationRequest"') 
AND jsonb_path_match(resource, '$.status=="active"');

【问题讨论】:

  • 两者都尝试会发生什么?
  • 同样的结果;我最感兴趣的是性能和执行方面
  • 您需要使用EXPLAIN ANALYZE ouptut 比较执行计划。

标签: postgresql jsonb


【解决方案1】:

你应该在你自己的数据上试试看。如果您在查询文本前使用EXPLAIN,您将获得执行计划。如果你把EXPLAIN (ANALYZE, BUFFERS)放在查询之前,它实际上会运行那个计划并报告时间和统计信息。

您的第一个公式可能会受益于这样定义的功能索引:

create index on resourcetable ((resource ->> 'resourceType'),(resource ->> 'status'));

您的第二个公式无法从索引中受益,但如果您将其重写为可操作格式:

SELECT jsonb_path_query(resource, '$.subject') from resourcetable 
WHERE resource @@ '$.resourceType == "MedicationRequest"'                       
  AND resource @@ '$.status=="active"';

然后它可以从定义为的索引中受益:

create index on resourcetable using gin (resource jsonb_path_ops);

没有jsonb_path_ops 定义的索引也可以使用,但可能效率较低。

您还可以重写条件以使用 JSON_PATH 的 &&,而不是 SQL 的 AND。

第二个索引也可用于使用包含 @> 而不是 json_path @@ 的查询,我觉得这不太容易混淆。

SELECT resource->'subject' FROM resourcetable 
WHERE resource @> '{"resourceType": "MedicationRequest", "status":"active"}';

最后,您的两个查询在某些条件下实际上返回不同的结果,例如匹配 WHERE 的行没有键“主题”。

【讨论】:

  • 我经历了你提到的关于结果差异的最后一点。我猜这是这两种方法之间最重要的区别。另外,第一种方法也能从杜松子酒指数中受益吗?
  • 第一种方法不能直接从 gin 索引中受益。您可以将其重写为可以(见编辑)但在这一点上它真的仍然与第一种方法相同的东西吗?
  • 为什么 postgres 会在 jsonb_path_match 和 @@ 调用之间产生如此大的差异?
  • @Bergi 这是一个古老的决定,即索引仅适用于运算符,而不适用于函数。我不在身边。我认为它可能已在版本 12 中通过引入功能规划器支持功能 (postgresql.org/docs/12/xfunc-optimization.html) 进行了“修复”,但几乎没有重写历史代码以挂钩此功能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多