【问题标题】:Pagination for complex postgres queries复杂 postgres 查询的分页
【发布时间】:2020-04-23 14:05:31
【问题描述】:

我正在处理一个复杂的规范化数据库,并生成一个动态产品。

Current 查询运行比较快,但生成了 1K+ 行,我需要实现分页解决方案。

在查询中获取构建动态数据所需的所有信息相对复杂

FROM pulse_templates pt
INNER JOIN taggings ptags on ptags.taggable_type = 'PulseTemplate' AND ptags.taggable_id = 
pt.id AND ptags.context = 'available_for'
INNER JOIN schools s on s.id = 1
LEFT JOIN mascots m on m.id = s.mascot_id
LEFT JOIN pulse_designs pd on pd.id = m.silhouette_id
INNER JOIN colors_pulse_templates cpt ON cpt."pulse_template_id" = pt."id"
INNER JOIN items i on (pt.template_type = 'static' AND cpt."color_id" = i."primary_color_id") OR (pt.template_type = 'primary' AND s.primary_color_id = i.primary_color_id AND i.primary_color_id = cpt.color_id) or (pt.template_type = 'standard' AND i.primary_color_id = cpt.color_id AND (i.primary_color_id = s.primary_color_id OR i.primary_color_id = s.secondary_color_id OR i.primary_color_id = s.tertiary_color_id))
INNER JOIN taggings itags on itags.taggable_type = 'Item' AND itags.taggable_id = i.id AND itags.tag_id = ptags.tag_id AND ptags.context = 'available_for'
INNER JOIN tags tag on tag.id = itags.tag_id
INNER JOIN categories c on (c.id = i.category_id)
INNER JOIN pulse_products pp on pp.id = i.pulse_product_id
INNER JOIN product_lines pl on pl.id = i.product_line_id
WHERE
        s.id = 1 AND ((pt.all_identifiers LIKE '%mascot_name%' AND pd.id IS NOT NULL) OR pt.all_identifiers NOT LIKE '%mascot_name%')
GROUP BY s.id,pp.id,i.id,pt.id,pl.price

性能还可以

Total query runtime: 1 secs 810 msec.
1365 rows affected.

但是当我尝试使用 LIMIT/OFFSET 实现分页时,它会消失。

Total query runtime: 10 secs 737 msec.
25 rows affected.

由于这种性能损失,我几乎可以将分页移出数据库并移入服务器代码。

有没有一种很好的方法来为一个没有这么多额外处理时间的公共网站实施分页?

【问题讨论】:

  • "最好将分页移出数据库,移入服务器代码。"确实是的。这是一个很好的地方。
  • 如果您需要帮助以使其在数据库中更快,请在快速和慢速版本中显示EXPLAIN (ANALYZE, BUFFERS)

标签: postgresql performance pagination


【解决方案1】:

你可以使用WITH HOLD光标:

DECLARE c CURSOR WITH HOLD FOR SELECT ...;

然后你可以获取页面

FETCH 25 FROM c;

此类游标在服务器上实现,因此您必须确保在完成释放资源后关闭游标:

CLOSE c;

请注意,当数据库会话结束时,此类游标会自动关闭。

【讨论】:

  • 感谢您的建议,请原谅我在这里的无知。您提到我们需要在完成后关闭光标。由于这是面向公众的,我们不知道用户何时完成浏览,所以我们不需要为每个请求重建光标吗?
  • @tezyn,您知道用户何时注销,无论是显式注销还是会话到期?
  • Laurenz Albe 和 jjanes 感谢您的意见。我需要阅读更多关于光标处理的内容,然后才能看到这是否对我们有用。但我很感谢你抽出时间给我一些想法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-22
  • 1970-01-01
  • 2015-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-15
相关资源
最近更新 更多