【问题标题】:What makes that postgreSQL query slow?是什么让 postgreSQL 查询变慢?
【发布时间】:2022-01-08 06:34:06
【问题描述】:

我有这个查询,在我看来加入太多了。

目标是检索具有特定产品最昂贵(最高价格)运输详细信息的所有位置。请注意,我们可能有两种不同的运输方式:快递标准

SELECT DISTINCT on(l.id, sm.id) l.id as location_id, sm.id as shipping_method_id,
    sm.name as shipping_method_name, sd.price
FROM location AS l

JOIN product_location_shipping AS pl_s 
    ON l.id = pl_s.location_id 
    
JOIN product_location_shipping_details AS pl_sd
    ON pl_s.id = pl_sd.product_location_shipping_id

JOIN shipping_details AS sd
    ON sd.id = pl_sd.shipping_details_id

JOIN shipping_method AS sm
    ON sm.id = sd.shipping_method_id
WHERE pl_s.product_id = 1
ORDER BY l.id, sm.id, sd.price DESC;

结果是:

location_id shipping_method_id shipping_method_name price
1 1 Standard 230
1 2 Express 500
6 1 Standard 3900
6 2 Express 5230

这是表格的结构。 (每一列代表一个表)

location shipping_method shipping_details product_location_shipping product_location_shipping_details
id id id id id
name name price location_id product_location_shipping_id
zip_code ... estimated_time product_id shipping_details_id
.. ... shipping_method_id ... ...

还有其他方法可以更快地实现这一目标吗?或者我做错了什么。

【问题讨论】:

  • 如果没有 EXPLAIN(ANALYZE, VERBOSE, BUFFERS) 的结果,很难判断问题出在哪里。
  • 请按照此处的说明提供正确的信息:stackoverflow.com/tags/postgresql-performance/info
  • 您需要向我们展示表和索引定义,以及每个表的行数。也许您的表格定义不佳。也许索引没有正确创建。也许您认为您在该列上没有索引。没有看到表和索引定义,我们无法判断。我们需要行计数,因为这会影响查询计划。如果您知道如何执行EXPLAIN 或获取执行计划,请将结果也放入问题中。如果您没有索引,请访问use-the-index-luke.com
  • 我不明白这里DISTINCT ON() 部分的目的。我猜您对于某些l.idsm.id 组合的每个组合有多个价格并尝试摆脱这些组合?我也不确定ORDER BY sd.price 是否会始终为您提供此构造中的最高价值..(也许确实如此?我觉得很奇怪)。恕我直言,GROUP BYMAX() 如果这是您的目标,那么可读性会更高。
  • 我想避免过多的连接,这就是目的。我最终以另一种方式做到了。所以我要删除那个问题!

标签: sql postgresql query-optimization postgresql-performance


【解决方案1】:

您必须至少具有以下索引:

id 所有表的字段都必须是 PRIMARY KEY。例如:

ALTER TABLE location ADD CONSTRAINT location_pk PRIMARY KEY (id);
ALTER TABLE product_location_shipping  ADD CONSTRAINT product_location_shipping_pk PRIMARY KEY (id);
ALTER TABLE product_location_shipping_details  ADD CONSTRAINT product_location_shipping_details_pk PRIMARY KEY (id);
ALTER TABLE shipping_details  ADD CONSTRAINT shipping_details_pk PRIMARY KEY (id);
ALTER TABLE shipping_method   ADD CONSTRAINT shipping_method_pk PRIMARY KEY (id);

用于join 条件和order by 命令之后的字段必须是btree 类型的索引。例如:

CREATE INDEX product_location_shipping_location_id_idx 
ON product_location_shipping (location_id);

CREATE INDEX product_location_shipping_details_product_location_shipping_id_idx 
ON product_location_shipping_details (product_location_shipping_id);

CREATE INDEX shipping_details_shipping_details_id_idx 
ON shipping_details (shipping_details_id);

CREATE INDEX shipping_method_shipping_method_id_idx 
ON shipping_method (shipping_method_id);

CREATE INDEX shipping_details_price_idx 
ON shipping_details (price);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-13
    • 1970-01-01
    • 1970-01-01
    • 2011-02-28
    • 2011-05-21
    • 1970-01-01
    • 2010-11-03
    • 2019-07-27
    相关资源
    最近更新 更多