【问题标题】:PostgreSQL optimize query performance that contains Window function with CTEPostgreSQL 使用 CTE 优化包含 Window 函数的查询性能
【发布时间】:2021-04-08 22:52:15
【问题描述】:

这里 amenity_categoryparent_path 列是 JSONB 列,其值分别类似于 ["Tv","Air Condition"] 和 ["20000","20100","203"]。除此之外,其他列是普通的varcharnumeric 类型。我在id 上有大约 250 万行 主键,它已被索引。基本上,当 rp.parent_path 匹配多行时,初始 CTE 部分需要时间。

样本数据集:

当前查询:

WITH CTE AS
(
  SELECT id,
  property_name,
  property_type_category,
  review_score, 
  amenity_category.name, 
  count(*) AS cnt FROM table_name rp, 
  jsonb_array_elements_text(rp.amenity_categories) amenity_category(name)
  WHERE rp.parent_path ? '203' AND number_of_review >= 1
  GROUP BY amenity_category.name,id 
),
CTE2 as
(
  SELECT id, property_name,property_type_category,name,
  ROW_NUMBER() OVER (PARTITION BY property_type_category,
  name ORDER BY review_score DESC),
  COUNT(id) OVER (PARTITION BY property_type_category,
  name ORDER BY name DESC) 
  FROM CTE
)

SELECT id, property_name, property_type_category, name, COUNT 
FROM CTE2
where row_number = 1

电流输出:

所以我的基本问题是有没有其他方法可以重写此查询或优化当前查询?

【问题讨论】:

  • 请描述你想要做什么。
  • @GordonLinoff 先生,我正在尝试计算每个 property_type_categories 及其舒适组合窗口的数量,并在每个窗口上获取顶部 id 和 property_name。
  • 例如,如果您看到输出,类别:客舱和便利设施:电视的计数为 273,我从 273 中获取 TOP ROW 的 id, property_name

标签: sql postgresql common-table-expression window-functions jsonb


【解决方案1】:

如果可以安全地假设 amenity_categories 中的数组元素是不同的(没有重复的数组元素),我们可以从根本上简化为:

SELECT DISTINCT ON (property_type_category, ac.name)
       id, property_name, property_type_category, ac.name
     , COUNT(*) OVER (PARTITION BY property_type_category, ac.name) AS count
FROM   table_name rp, jsonb_array_elements_text(rp.amenity_categories) ac(name)
WHERE  parent_path ? '203'
AND    number_of_review >= 1
ORDER  BY property_type_category, ac.name, review_score DESC;

如果 review_score 可以为 NULL,则设为:

...
ORDER  BY property_type_category, ac.name, review_score DESC NULLS LAST;

这是可行的,因为DISTINCT ON 作为最后一步应用(在窗口函数之后)。见:

parent_pathnumber_of_review 可能应该被索引。取决于您未披露的WHERE 条件的数据分布和选择性。

关于DISTINCT ON

假设idNOT NULLcount(*) 更快并且等效于count(id)

【讨论】:

  • 感谢您的回答先生,我会在检查此优化时回复您。非常感谢您的回答。
  • 它的工作原理和它的计划和执行时间比以前更好。
猜你喜欢
  • 2020-04-02
  • 2021-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多