Option 3 is the fastest
If and when you encounter performance problems, and if you cannot solve them in any other way, option # 3 is the way to go.
Use Triggers to Update
You must use triggers after insertion, update, and deletion so that subtotals in the order table synchronize with the underlying data.
Be especially careful when retrospectively changing prices and so on, as this will require a complete recount of all subtotals. Thus, you will need many triggers that usually do not do most of the time.
if the tax changes, it will change in the future, for orders that you do not already have.
If the triggers take a lot of time, make sure that you do these updates after hours.
Perform automatic checks periodically to ensure that the cached values are correct.
You can also save the golden
subquery in place, which calculates all the values and checks them for the stored values in the order table.
Run this query every night and report any anomalies so you can see when the denormalized values are out of sync.
Do not invoice orders that have not been processed with a validation request
Add an additional date field to the order
table called timeoflastsuccesfullvalidation
and set it to null
if the check has not been performed.
Only invoice items with dateoflastsuccesfullvalidation
less than 24 hours ago.
Of course, you do not need to check orders that are fully processed, but only orders that are expected.
Option 1 may be fast enough
Regarding No. 1
He is also slow.
It depends a lot on how you query the DB.
You specify the subqueries, in the lower main full skeletal query, I don’t see the need for many subqueries, so you are a little perplexing to me.
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
Thinking about this, you need to break this request down into things that correspond to each order and order, but I'm lazy to do it now.
Speed tips
Make sure you have indexes for all the fields involved in the join criteria.
Use the MEMORY
table for smaller tables, such as tax
and shippingcost
, and use the hash
index for id
in the memory tables.