选项 3 最快
如果并且当您遇到性能问题并且无法以任何其他方式解决这些问题时,选项#3 是您的最佳选择。
使用触发器进行更新
您应该在插入、更新和删除之后使用触发器,以使订单表中的小计与基础数据保持同步。
在追溯更改价格和内容时要特别小心,因为这需要对所有小计进行全面重新计算。
因此,您将需要很多触发器,而这些触发器通常不会在大多数情况下发挥作用。
如果税率发生变化,将来会发生变化,对于您还没有的订单 em>
如果触发器需要很长时间,请确保在非高峰时间进行这些更新。
定期运行自动检查以确保缓存值正确
您可能还希望保留一个 golden 子查询,以计算所有值并根据订单表中存储的值检查它们。
每晚运行此查询并让它报告任何异常,以便您可以查看非规范化值何时不同步。
不对验证查询未处理的订单开具任何发票
向表 order 添加一个名为 timeoflastsuccesfullvalidation 的额外日期字段,如果验证不成功,则将其设置为 null。
仅在不到 24 小时前为 dateoflastsuccesfullvalidation 开具发票。
当然,您不需要检查已完全处理的订单,只需检查待处理的订单即可。
选项 1 可能足够快
关于#1
它也很慢。
这在很大程度上取决于您如何查询数据库。
你提到了子选择,在下面的大部分完成骨架查询中,我看不到需要很多子选择,所以你让我有点困惑。
SELECT field1,field2,field3
, oifield1,oifield2,oifield3
, NettItemCost * (1+taxrate) as TotalItemCost
, TotalShippingCost
, TotalHandlingCost
, NettItemCost * taxRate as TotalTaxCost
, (NettItemCost * (1+taxrate)) + TotalShippingCost + TotalHandlingCost as TotalCost
, TotalPaid
, somethingorother as TotalProfit
FROM (
SELECT o.field1,o.field2, o.field3
, oi.field1 as oifield1, i.field2 as oifield2 ,oi.field3 as oifield3
, SUM(c.productprice * oi.qty) as NettItemCost
, SUM(IFNULL(sc.shippingperkg,0) * oi.qty * p.WeightInKg) as TotalShippingCost
, SUM(IFNULL(hc.handlingperwhatever,0) * oi.qty) as TotalHandlingCost
, t.taxrate as TaxRate
, IFNULL(pay.amountpaid,0) as TotalPaid
FROM orders o
INNER JOIN orderitem oi ON (oi.order_id = o.id)
INNER JOIN products p ON (p.id = oi.product_id)
INNER JOIN prices c ON (c.product_id = p.id
AND o.orderdate BETWEEN c.validfrom AND c.validuntil)
INNER JOIN taxes t ON (p.tax_id = t.tax_id
AND o.orderdate BETWEEN t.validfrom AND t.validuntil)
LEFT JOIN shippingcosts sc ON (o.country = sc.country
AND o.orderdate BETWEEN sc.validfrom AND sc.validuntil)
LEFT JOIN handlingcost hc ON (hc.id = oi.handlingcost_id
AND o.orderdate BETWEEN hc.validfrom AND hc.validuntil)
LEFT JOIN (SELECT SUM(pay.payment) as amountpaid FROM payment pay
WHERE pay.order_id = o.id) paid ON (1=1)
WHERE o.id BETWEEN '1245' AND '1299'
GROUP BY o.id DESC, oi.id DESC ) AS sub
考虑一下,您需要将此查询拆分为与每个订单和每个 order_item 相关的内容,但我现在懒得这样做。
速度提示
确保您对连接条件中涉及的所有字段都有索引。
对较小的表使用MEMORY 表,例如tax 和shippingcost,并为内存表中的id 使用hash 索引。