MYSQL嵌套查询运行很慢?

Posted

技术标签:

【中文标题】MYSQL嵌套查询运行很慢?【英文标题】:MYSQL nested query running very slow? 【发布时间】:2013-01-01 05:30:18 【问题描述】:

下面的查询不断超时,有没有一种开销更小的方式来实现同样的功能?

UPDATE Invoices SET ispaid = 0 
WHERE Invoice_number IN (SELECT invoice_number
    FROM payment_allocation
    WHERE transactionID=305)

我正在做的是从交易中取消分配发票,最多可以返回 30 多条记录,但每次我尝试运行它都会停止数据库死

【问题讨论】:

【参考方案1】:

使用 JOIN 而不是 subquery 它将提高性能。

如果您尚未创建,请在两个表中的 Invoice_number 列上创建索引。

试试这个:

UPDATE Invoices i 
INNER JOIN payment_allocation pa ON i.Invoice_number = pa.invoice_number 
SET i.ispaid = 0 
WHERE pa.transactionID = 305;

【讨论】:

工作了一次!因此,使用内部而不是嵌套来连接表以获取开销:) 令人敬畏的 thnaks @stevenmoffat 不要忘记接受所有答案中的任何一个,无论你发现哪个对你有用【参考方案2】:

我会试试EXISTS

UPDATE Invoices a set ispaid=0 
WHERE EXISTS 
(
 SELECT NULL FROM payment_allocation b 
 WHERE b.Invoice_number =a.Invoice_number AND b.transactionID=305
)

【讨论】:

为什么要尝试存在? 对我来说这似乎是合乎逻辑和清晰的 - 如果至少有记录满足另一个表中的某些条件,则更新一个表中的记录。 INNER JOIN 产生相同的执行计划,并给出相同的结果,所以从性能的角度来看没有区别【参考方案3】:

mysql 5.5 开始,无法优化子查询选择(查询中的另一个完整选择语句)。这可能就是您的查询如此缓慢的原因。重构您的查询以摆脱内部选择语句。

 UPDATE Invoices, payment_allocation
  SET ispaid=0 
  WHERE payment_allocation.transactionID=305 AND       
        Invoices.Invoice_number = payment_allocation.invoice_number 

一个有趣的旁注...但是 MariaDB(原始创建者的 MySQL 的一个分支)已经实现了子查询选择优化。

【讨论】:

【参考方案4】:
UPDATE invoices i
  JOIN payment_allocation pa
    ON pa.invoice_number = i.invoice_number
   SET i.ispaid=0 
 WHERE pa.transactionID = 305;

【讨论】:

以上是关于MYSQL嵌套查询运行很慢?的主要内容,如果未能解决你的问题,请参考以下文章

使用算术运算优化 MySQL 嵌套选择

Mysql:有没有更高效的嵌套聚合更新方式?

使用嵌套查询的 sqlite 查询性能

如何使用嵌套循环加速查询

mysql_数据查询_嵌套查询

mysql怎么在查询中嵌套子查询