我有一个相对简单的查询,它只是将我的网站已接受的所有 PayPal 付款相加,然后使用每天更新的货币换算表将它们全部转换为英镑。
SELECT SUM(PPI.mc_gross * IF(PPI.mc_currency='GBP', 1, CC.fConv))
FROM paypal_payment_info PPI
JOIN currency_conversions CC ON CC.sFrom = PPI.mc_currency AND CC.tConv = DATE(PPI.tIPN)
对于 PPI 中的 30,000 行和 CC 中的 5,000 行,在功能强大的机器上查询大约需要 9 秒。
解释显示:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE PPI ALL 31271
1 SIMPLE CC ref sFrom sFrom 9 db.PPI.mc_currency 1167 Using where
我已尝试在 tIPN 和 mc_currency
上建立索引,以及在 mc_currency 和 tIPN
上建立索引。都没有帮助。我认为可能是 DATE()
函数出了问题,因此创建了一个列 tIPNdate
并修改了相关索引以使用它,但没有任何区别。
我觉得我遗漏了一些明显的东西,有人可以帮忙吗?
谢谢
最佳答案
对于这么多数据来说,9 秒并不是一个极端的性能问题。
话虽如此,将其分解为两个不同的 SUM()
操作可能是有意义的。
首先,查询英镑交易。
SELECT SUM(PPI.mc_gross)
FROM paypal_payment_info PPI
WHERE PPI.mc_currency = 'GBP'
(mc_currency, mc_gross)
上的复合索引将使该查询尽可能快。这可能会让您无需任何连接即可完成大部分交易。希望更快。
然后,处理非英镑交易。
SELECT SUM(PPI.mc_gross * CC.fConv)
FROM paypal_payment_info PPI
JOIN currency_conversions CC ON CC.sFrom = PPI.mc_currency
AND CC.tConv = DATE(PPI.tIPN)
WHERE PPI.mc_currency <> 'GBP'
要清除 JOIN 中不可控制的 DATE()
部分,请执行以下操作:
SELECT SUM(PPI.mc_gross * CC.fConv)
FROM paypal_payment_info PPI
JOIN currency_conversions CC ON PPI.mc_currency = CC.sFrom
AND PPI.tPN >= CC.tConv
AND PPI.tPN < CC.tConv + INTERVAL 1 DAY
WHERE PPI.mc_currency <> 'GBP'
虽然不确定,但我认为 paypal_ payment_info( tPN, mc_currency, mc_gross)
上的复合索引将有助于此查询。我认为 currency_conversions (sFrom, tConv, fConv)
上的索引也会有所帮助。
然后,您可以使用 UNION ALL 和另一个 SUM 将两个查询的结果相加。
SELECT SUM(sums) sums
FROM (
SELECT SUM(PPI.mc_gross) sums
FROM paypal_payment_info PPI
WHERE PPI.mc_currency = 'GBP'
UNION ALL
SELECT SUM(PPI.mc_gross * CC.fConv) sums
FROM paypal_payment_info PPI
JOIN currency_conversions CC ON PPI.mc_currency = CC.sFrom
AND PPI.tPN >= CC.tConv
AND PPI.tPN < CC.tConv + INTERVAL 1 DAY
WHERE PPI.mc_currency <> 'GBP'
) s
关于mysql - 我怎样才能加速这个(相对简单的)查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39701308/