MYSQL将子查询的慢速更新转换为(更快?)连接

时间:2012-04-27 01:15:59

标签: mysql performance join subquery

我有一个查询在mysql中使用一个非常慢的子查询,需要几分钟,而我所做的所有其他查询都非常快。

正如我发现subquerys很可能是一个坏主意,所以我想转换 这个子查询与我所做的所有其他查询一样,使用了对性能有重大影响的subquerys。

我的大多数其他查询都非常简单,但是这个让我疯狂。

这是一个例子。

我有客户和账单。客户有多个账单。法案有州。票据有一个参数“无论如何”。

我需要更新 “所有账单都处于状态1或2且所有账单都不是2的客户”

因为我无法找到如何做到这一点,我使用了反转  “所有没有账单的客户都没有处于状态1,而不是状态2并且账单无关 - 参数不是2”

这是我正在使用的subquerys的两个变体,一个使用count而一个使用“not in”,但它们似乎同样慢。

update client cl , bill bi 
set cl.parameter = "parameter1" 
where cl.parameter="parameter2" 
    and bi.whatever != "2" 
    and bi.client_id = cl.id  
    and (select count(cl.id) 
            from bill bi 
                where bi.client_id = cl.id 
                    and bi.state!="state0" 
                    and bi.state != "state1" 
        ) = 0;

在mysql状态“发送数据”中变慢

update client cl , bill bi 
set cl.parameter = "parameter1"  
    where  cl.parameter="parameter2" 
        and bi.whatever != "2" 
        and bi.client_id = cl.id  
        and cl.id not in  (select distinct cl.id 
                                from bill bi  
                                    where bi.client_id = cl.id 
                                        and  ( bi.state!="state1" 
                                        and bi.state != "state2" 
                            ) ;

在mysql状态“复制到临时表”时变慢了

我试了好几个小时,但是如果没有那么缓慢的子查询,我无法将其转换为有用的东西。  任何人都可以让我知道如何使用连接或比现在更快的东西这样做?

更新

感谢DRapp,这会产生完全相同的结果并且速度更快。对于我现在可以测试的内容,查询时间可以缩短到几秒钟,而且还需要几分钟。

select
  c.id,
  sum( if( b.State IN ( "State1", "State2" ), 1, 0 )) as OkStatesCnt,
  sum( if( b.State NOT IN ( "State1", "State2" ) or b.whatever=2, 1, 0 )  ) as AnyOtherState
from
  client c
     join bill b
        ON c.id = b.client_id
where
  c.parameter = "parameter2"
   group by
      c.id
  having
      OkStatesCnt > 0
  AND AnyOtherState = 0

UPDATE client cl,
  ( full select query from above ) as PreQualified
 set cl.parameter = "parameter1"
 where cl.id = PreQualified.id

1 个答案:

答案 0 :(得分:0)

要预先确保包含哪些客户,您可以自行运行此查询...

select
      c.id,
      sum( if( b.State IN ( "State1", "State2" ), 1, 0 )) as OkStatesCnt,
      sum( if( b.State IN ( "State1", "State2" ), 0, 1 )) as AnyOtherState
   from
      client c
         join bill b
            ON c.id = b.client_id
           AND b.whatever != "2"
   where
      c.parameter = "parameter2"
       group by
          c.id
   having
          OkStatesCnt > 0
      AND AnyOtherState = 0

如果这实际上是您正在寻找的内容,您可以像

一样实施更新
UPDATE client cl,
      ( full select query from above ) as PreQualified
   set cl.parameter = "parameter1"
   where cl.id = PreQualified.id