Mysql 如何加速这个(相对简单的)查询
我有一个相对简单的查询,它简单地汇总了我的网站接受的所有贝宝付款,使用每天更新的货币转换表将它们全部转换为英镑Mysql 如何加速这个(相对简单的)查询,mysql,Mysql,我有一个相对简单的查询,它简单地汇总了我的网站接受的所有贝宝付款,使用每天更新的货币转换表将它们全部转换为英镑 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
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中有30000行,CC中有5000行,在一个强大的框中,查询大约需要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和MCU货币的指数,以及一个关于MCU货币和tIPN的指数。两者都没有帮助。我认为可能是DATE函数出了问题,所以创建了一个列tIPNdate并修改了相关的索引以使用它,这没有任何区别
我觉得我错过了一些明显的东西,有人能帮忙吗
谢谢对于这么多的数据来说,9秒并不是一个极端的性能问题 尽管如此,将其分解为两个不同的求和运算可能是有意义的 首先,对GBP交易进行查询
SELECT SUM(PPI.mc_gross)
FROM paypal_payment_info PPI
WHERE PPI.mc_currency = 'GBP'
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'
mc_gross是一个关于mc_货币的复合索引,它将尽可能快地进行查询。这可能会让您获得大部分事务,而不需要任何连接。希望更快
然后,处理非GBP事务
SELECT SUM(PPI.mc_gross)
FROM paypal_payment_info PPI
WHERE PPI.mc_currency = 'GBP'
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'
不确定的是,我认为paypal_payment_info tPN、mc_currency、mc_gross上的复合索引将有助于此查询。我认为一个关于货币转换的指数也会有所帮助
然后可以使用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
首先,我将简化select表达式,在货币转换表中添加一行,将英镑转换为自身的汇率为1.00 接下来,恢复tIPNdate列,使其值为DATEPPI.tIPN-这肯定会有所帮助 您需要关于货币换算的索引: 这将对您的查询产生最大影响。此外,索引中列的顺序也很重要-始终将变化最大且完全匹配的列放在第一位 并在paypal\u payment\u信息上创建索引: 这两个索引都是覆盖索引,这意味着查询所需的所有数据都可以在索引中找到,从而避免了访问表的需要 删除冗余零件后的查询应如下所示:
SELECT SUM(mc_gross * fConv)
FROM paypal_payment_info
JOIN currency_conversions ON sFrom = mc_currency
AND tConv = tIPNdate
最后,您可能会发现颠倒表的顺序效果更好:
SELECT SUM(mc_gross * fConv)
FROM currency_conversions
JOIN paypal_payment_info ON sFrom = mc_currency
AND tConv = tIPNdate
你能编辑这篇文章并解释一下这段代码是如何使SQL更快的吗?只有代码的答案并不总是很有用……特别是当OP在问题中陈述他们已经尝试在tIPN和mc_Currency上建立索引时,这是连接两个完整的表。为什么你认为它会很快?这确实使它下降到3.5秒左右,但由于它是一个非常简单的和/积,在相对较少的行数上,我仍然觉得它应该快得多,几乎是即时的。也许我不得不放弃,并将货币转换存储在PPI表中,与每笔交易一起。尝试以下索引:paypal\u payment\u infomc\u currency、mc\u gross、tIPN、currency\u conversionstConv、sFrom、FCONVac。实际上,首先在原始查询上尝试这些索引,然后查看其执行情况。我不确定我是否理解清理无法组织的东西的方法。。。这是答案的一部分。感谢您的贡献,但在您键入时,我正忙于更改模式,以便将货币转换存储在PPI表中,与每笔交易一起。现在是0.05秒。也许我可以修复原来的查询,但这似乎简单、直接,并且易于维护。
SELECT SUM(mc_gross * fConv)
FROM paypal_payment_info
JOIN currency_conversions ON sFrom = mc_currency
AND tConv = tIPNdate
SELECT SUM(mc_gross * fConv)
FROM currency_conversions
JOIN paypal_payment_info ON sFrom = mc_currency
AND tConv = tIPNdate