2012-04-27 16 views
0

mysqlのサブクエリを使用するクエリは非常に遅く、数分かかるほか、他のすべてのクエリは非常に高速です。サブスクリプションを使用した低速更新のサブスクリプションへの変換(高速?)join

私がサブクエリを見つけたのはおそらく悪い考えだから、私は サブクエリをこのサブクエリに変換したいと思っていました。パフォーマンスに大きな影響を与えるサブクエリを使用した他のすべてのクエリーと同様でした。

私の他のquerysのほとんどは非常にシンプルですが、この1つは私にナットを駆動します。

ここは例です。

私はクライアントと請求書を持っています。クライアントには複数の請求書があります。法案には州があります。紙幣には「何でも」のパラメータがあります。

私はある反転を使用することを行う方法を見つけるcouldntのので、私は 「全ての紙幣が状態1または2に紙幣どんなパラメータが2ではないことをしているすべてのクライアント」

を更新する必要が

"状態1でなく状態2でない請求書を持たないすべてのクライアント"

これは私が今使っているサブクエリを使った2つの変種です。 1つは「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; 

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の状態で遅くなる「データを送信する」MySQLの状態で遅くなりますその遅いサブクエリなしで有用な何か。 誰かが今よりも早く参加するなど、これをどうやって行うのか考えてもらえますか? DRappへ

UPDATE

おかげで、これはまったく同じ結果を生成し、はるかに高速です。私が今までテストできたことは、クエリ時間が数秒にまで短縮され、数分前です。クライアントが含まれますWHAT事前に確認してください、あなたは自分自身でこのクエリを実行することができますするに

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 
+0

あなたは次のことを確認してもらえますか?Billテーブルに存在するすべてのクライアントを更新するように見えますが、cl.id NOT INの結果として "state1"または "state2" BillクライアントではないState1またはState1を探します。 – DRapp

+0

私は請求書を持っているすべてのクライアントを更新したい(請求書はclient.idへの参照を持ちます)。また、すべての請求書は状態1または状態2にあります。 – dirk

答えて

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 

この中で、事実は何であるのIFあなたは探しているだけのようにあなたの更新に実装することができます

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

hm ..これは、状態1ではなく状態2でない請求書を持つすべてのクライアントを私に与えます。しかし、私は、すべての請求書が州1または州2にあり、請求書が他の州にはないすべてのクライアントが必要です。これは、第1のクエリではinvertを使用し、第2のクエリではnot inを使用した理由です。 – dirk

+0

@dirk、チェックリビジョン。内部クエリは、OK状態の数とAnyOther状態の数を行います。 HAVINGは、Ok StateとAnyOther count = 0のうち、少なくとも資格を与えます。適用方法がわからないのは、「何か!= '2'」のコンポーネントだけです。あなたは、カウントのために考慮される= '2'項目だけ、あるいはState1/State2のものだけを望みますか?これがあなたにジャンプを与えることを願って、私はあなたのためにこの結果を絞り込むことができます。 – DRapp

+0

ああ、ありがとう、かなりそれthats。しかし、私は、任意の= 2を "sum(b.state NOT IN(" state1 "、" state2 ")またはb.whatever = 2、1、0))AnyOtherStateとして配置しました。古いクエリ私は答えを含めるために今私の質問を更新します。再度、感謝します! – dirk

関連する問題