我们有一个存储过程,用于为报告准备数据。请注意,架构并不像它应该的那样规范化,但它就是它,我们无法修改它,因此为报告构建临时表。 MySQL版本是5.1.70。
有一个更新语句将临时表从连接更新为选择。请注意,此查询中应具有索引的所有列都包括,包括临时表(OI):
UPDATE `tmpOrderInquiry` OI
INNER JOIN (
SELECT `SalesOrderNo`,
GROUP_CONCAT(Inv.`InvoiceNo` ORDER BY `InvoiceNo` ASC SEPARATOR '~|~') as `InvoiceNoGRP`,
GROUP_CONCAT(DATE_FORMAT(date(`ShipDate`), ' %c/%d/%y') ORDER BY `ShipDate` ASC SEPARATOR '~|~') as `ShipDateGRP`,
GROUP_CONCAT(DATE_FORMAT(date(`LastPmtDate`), ' %c/%d/%y') ORDER BY `LastPmtDate` ASC SEPARATOR '~|~') as `LastPmtDateGRP`
FROM `InsynchInvoiceHistoryHeader` Inv
GROUP BY Inv.`SalesOrderNo`
) as OrdInv ON OI.`SalesOrderNo` = OrdInv.`SalesOrderNo`
SET OI.`InvoiceNo` = OrdInv.`InvoiceNoGRP`, OI.`ShipDate` = OrdInv.`ShipDateGRP`, OI.`LastPmtDate` = OrdInv.`LastPmtDateGRP`
此查询平均需要大约70秒才能完成。 select本身执行sub-second。经过多次敲击后,我用一条云雀替换了上面的:
CREATE TEMPORARY TABLE `tempWorking` AS SELECT
`SalesOrderNo`,
GROUP_CONCAT(Inv.`InvoiceNo` ORDER BY `InvoiceNo` ASC SEPARATOR '~|~') as `InvoiceNoGRP`,
GROUP_CONCAT(DATE_FORMAT(date(`ShipDate`), ' %c/%d/%y') ORDER BY `ShipDate` ASC SEPARATOR '~|~') as `ShipDateGRP`,
GROUP_CONCAT(DATE_FORMAT(date(`LastPmtDate`), ' %c/%d/%y') ORDER BY `LastPmtDate` ASC SEPARATOR '~|~') as `LastPmtDateGRP`
FROM `InsynchInvoiceHistoryHeader` Inv
GROUP BY Inv.`SalesOrderNo`;
UPDATE `tmpOrderInquiry` OI
INNER JOIN tempWorking as OrdInv ON OI.`SalesOrderNo` = OrdInv.`SalesOrderNo`
SET OI.`InvoiceNo` = OrdInv.`InvoiceNoGRP`, OI.`ShipDate` = OrdInv.`ShipDateGRP`, OI.`LastPmtDate` = OrdInv.`LastPmtDateGRP`
此查询在大约2秒内运行。由于选择本身很快,我无法解释为什么第一个查询太慢了。因为问题很严重我把这个改变发布到了生产中,但是我不喜欢引入一个所有条件相同的修复程序,我希望实际上会让事情变得更慢。
有关第一次更新声明为何如此缓慢的任何见解将不胜感激。