PostgreSQL 更好的查询性能

PostgreSQL better query performance

提问人:Pablo Alejandro 提问时间:11/17/2023 最后编辑:Erwin BrandstetterPablo Alejandro 更新时间:11/18/2023 访问量:48

问:

我有客户和访问表,我想知道这两个查询中哪一个具有更好的性能: (我为这些列定义了索引)

查询 1

SELECT
  customers.id as id,
  COALESCE(v.count, 0) as visits

FROM
  customers
  LEFT OUTER JOIN (
    SELECT customer_id, count(*)
    FROM visits
    GROUP BY customer_id
  ) as v on visits.customer_id = customers.id

EXPLAIN ANALYZE 结果

enter image description here
enter image description here

查询 2

SELECT
  customers.id as id,
  (
      SELECT count(*)
        FROM visits
        WHERE
        visits.customer_id=customers.id
  ) as visits

FROM
  customers

EXPLAIN ANALYZE 结果

enter image description here
enter image description here

如您在上面的示例中看到,第二个查询的成本较低,但执行时间比第一个查询高。

我对此感到非常困惑。 我认为这取决于过滤器选项。 你能帮我理解这一点吗,如果你有更好的查询,请告诉我。

PostgreSQL 查询优化 postgresql 性能

评论

2赞 Frank Heikens 11/18/2023
您能否分享所有涉及的表和索引的 DDL 以及您的 SQL 语句的(完整)结果?(全部以纯文本形式作为您问题的更新)explain(analyze, verbose, buffers, settings)
2赞 jjanes 11/18/2023
显示完整的计划,而不仅仅是每个计划中的一行。
0赞 Pablo Alejandro 11/18/2023
当然,路线图已添加,thnx
0赞 Frank Heikens 11/18/2023
这看起来不像纯文本,现在更难分析。DDL 也丢失
0赞 Frank Heikens 11/18/2023
这些查询计划使用不同的表,service_visits。你确定这些是正确的吗?

答:

0赞 O. Jones 11/18/2023 #1

原则上,第一个带有聚合子查询的子查询比具有相关子qquery的子查询更快。这是因为聚合结果集只能计算一次,然后哈希联接到第一个表。

但是查询计划器可能足够聪明,可以以相同的方式处理它们。

索引会有所帮助。visits.customer_id

0赞 Erwin Brandstetter 11/18/2023 #2

我认为这取决于过滤器选项。

完全。

为了计算所有或大多数客户的访问次数,第一个查询要快得多,因为它可以一举处理整个(大部分或所有相关)表。索引不是必需的,但仅索引扫描可能仍然有帮助。visits

为了计算一小部分客户的访问次数,带有相关子查询的第二个查询要快得多,因为它只处理表中实际相关的几行,这超过了为每个客户运行单独聚合的开销。索引为必填项。visits

(您的查询计划似乎与给定的设置不匹配。

看: