所以我有三张桌子: 产品,优惠和offer_lines
offer_lines是一个连接表,用于生成并属于许多关系:
offer_lines有一个名为 calculated_price 的列。这是基于优惠表的 discount_percentage 列和产品表的价格列。
我想创建一个sql语句,可以根据商品表中存储的折扣百分比计算产品的折扣价。
这是我到目前为止所得到的:
UPDATE offer_lines
SET discounted_price = (products.price - (products.price * offers.discount_percentage / 100))
FROM offer_lines AS o
INNER JOIN products ON o.product_id = products.id
INNER JOIN offers ON o.offer_id = offers.id
WHERE offer_lines.offer_id = 2;
这似乎工作得很好,除了它需要大约一分钟才能运行。
以下是解释:
Update on offer_lines (cost=77.16..1131.37 rows=10670 width=87)
-> Hash Join (cost=77.16..1131.37 rows=10670 width=87)
Hash Cond: (o.product_id = products.id)
-> Hash Join (cost=9.44..836.90 rows=10670 width=77)
Hash Cond: (o.offer_id = offers.id)
-> Seq Scan on offer_lines o (cost=0.00..620.74 rows=26674 width=14)
-> Hash (cost=9.38..9.38 rows=4 width=71)
-> Nested Loop (cost=0.29..9.38 rows=4 width=71)
-> Index Scan using index_offer_lines_on_offer_id on offer_lines (cost=0.29..8.30 rows=1 width=53)
Index Cond: (offer_id = 13)
-> Seq Scan on offers (cost=0.00..1.04 rows=4 width=18)
-> Hash (cost=62.88..62.88 rows=388 width=18)
-> Seq Scan on products (cost=0.00..62.88 rows=388 width=18)
我有什么想法可以让它跑得更快?
答案 0 :(得分:1)
首先,Postgres的语法不应重复FROM
子句中正在更新的表:
UPDATE offer_lines ol
SET discounted_price = (p.price - (p.price * o.discount_percentage / 100))
FROM products p, offers o
WHERE ol.offer_id = o.id AND
ol.product_id = p.id AND
ol.offer_id = 2;
(哇,我无法相信我在FROM
条款中使用过逗号.Arrrgh。)
然后,对于此查询,您希望offer_lines(offer_id, product_id)
上的索引,products(id, price)
(价格是可选的),offers(id, discount_percentage)
(discount_percentage
是可选的)。
如果我不得不猜测性能问题是因为order_lines
语句和update
子句中都存在from
。
编辑:
我应该清楚。您可以重复FROM
子句中的表格。但它需要与更新的版本联系起来:
UPDATE offer_lines ol
SET discounted_price = (p.price - (p.price * o.discount_percentage / 100))
FROM offer_lines ol2 INNER JOIN
products p
ON ol2.product_id = p.id INNER JOIN
offers o
ON ol.offer_id = o.id
WHERE ol2.offer_id = 2 AND ol.id = o.id;
这假设offer_lines
有一个主键列,我称之为id
。坦率地说,就可读性而言,我可以看到以这种方式进行更新的好处。