【发布时间】:2012-05-07 18:47:52
【问题描述】:
我有一个使用 mysql 中的子查询的查询,它变得非常慢,最多需要几分钟,而我所做的所有其他查询都非常快。
我发现子查询很可能是个坏主意,所以我想转换 就像我对所有其他使用对性能有很大影响的子查询的查询所做的那样,这个子查询到一个连接。
我的大多数其他查询都非常简单,但这个让我抓狂。
这是一个例子。
我有客户和账单。客户有多个账单。法案有状态。账单有一个参数“随便”。
我需要更新 “所有账单都处于状态 1 或 2 并且账单参数不是 2 的所有客户”
由于我不知道该怎么做,所以我使用了 invert,它是 "所有没有账单的客户不在状态 1 和状态 2 中并且账单参数不是 2"
这是我现在使用的两个带有子查询的变体,一个使用 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
【问题讨论】:
-
您能否确认以下内容...看起来您想要更新 Bill 表中存在的所有客户...并且不在“state1”或“state2”中...作为cl.id NOT IN 的结果并正在寻找 Bill 客户 NOT State1 或 State1。
-
我想更新所有有账单的客户(账单引用了 client.id)并且所有账单都处于状态 1 或状态 2。这意味着没有更多的账单处于任何其他状态。
标签: mysql performance join subquery