2016-12-30 3 views
2

多くのテーブルの結合で複雑なクエリが発生します。複雑さのために実際のクエリを入れるのは難しいです。IN節内の項目の数が4を超えると、SQL Serverのクエリが非常に遅い

それは私が見つけた

select t1.id, t2.id, t1.name, t2.name 
from table1 t1, table2 t2 
left join table3 t3 ON t2.id = t3.id 
where t2.id = t1.ref_id 
    and t1.ref_id IN ('id1', 'id2', 'id3', 'id4', 'id5', ...) 

、その私がIN句内部の持っている場合( 'ID1'、 'ID2'、 'ID3' このIN t1.ref_idようにのみ4つの以下の値、 'のような何かid4 ')非常に高速に動作します(16 ms)。 tidref_id IN( 'id1'、 'id2'、 'id3'、 'id4'、 'id5')の実行時間が40倍になり、600ミリ秒になります。

私は、この動作を制御し、いくつかのパラメータがあるように見えますSQL Server上で2014

をそれを得ました。私は別のSQLサーバー(SQL Server 2008)でこのクエリを試してみましたが、何も検索できませんでした。

私の質問:この種の動作を制御するパラメータはありますか?またはこの奇妙な限界を例えば50に増やす方法。

私はちょうど4ではなく30-50まで増やしたいと思います。もちろん、数百から数千の値を持つIN節を作成したくありません。私はその理由を見つけたよう

select t1.id, t2.id, t1.name, t2.name, t3.name 
from table1 t1, table2 t2 
left join table3 t3 ON t2.id = t3.id 
where t2.id = t1.ref_id 
    and t1.ref_id IN ('id1', 'id2', 'id3', 'id4', 'id5', ...) 

がアップデート2

が見える:

UPDATE1

申し訳ありませんが、私はそれ以外の場合は、私は必要はありませんt3のように見える、選択しt3.nameを入れるのを忘れていました。問題はIN内のアイテムの数ではありませんでした。後でこの問題を4つのID(1つでも)で再現しました。いくつかのIDがt1.ref_idに表示されなかったために起こります。 t1.ref_idには存在しないidがあったとき、速いときにidを追加したときにt1.ref_idに存在し、遅くなったとき。前の例ではid1 - id4はt1.ref_idには表示されず、id5が提示されていました。このため、id5を追加すると遅くなります。 IN句の中にid(id5)を1つだけ入れても遅くなります。最後にt1.ref_idのインデックスが問題を解決しました。 4つまたは5つのidsの周りに魔法はありませんでした。私の具体例では偶然のことです。

+0

t1.ref_idにインデックスを作成しましたか? –

+0

あなたは違いを絞り込むためにうまくいっています。次に、低速バージョンと高速バージョンの間でクエリプランを比較します。あなたは何を見ますか?クエリプランを表示するには、CTRL-Lキーを押します。 –

+2

暗黙の結合構文と明示的な結合構文を混在させないでください。明示的な構文に書き換える必要があります。 1992年以来のANSI規格です!このクエリはストアドプロシージャの一部ですか? 'OPTION(RECOMPILE)'を追加すれば助けになりますか? – HoneyBadger

答えて

1

まず、クエリを修正します。単純なルール:は、FROM句にカンマを使用します。

select t1.id, t2.id, t1.name, t2.name 
from table1 t1 join 
    table2 t2 
    on t2.id = t1.ref_id left join 
    table3 t3 
    on t2.id = t3.id 
where t1.ref_id in ('id1', 'id2', 'id3', 'id4', 'id5', ...); 

は、クエリに基づいて、あなたはtable3を必要としない - あなたは重複行を気にしない限り。私はそれを削除します。

次に、インデックスを検討する必要があります。私はtable1(ref_id, id, name)table2(id, name)を提案します。

また、ref_idが実際に数値である場合は、リスト内の値を一重引用符で囲まないでください。文字列と数値を混在させると、オプティマイザが混乱する可能性があります。

+0

答えをありがとう。しかし、コンマ区切りのテーブルからJOINへの構文を変更することはできません。なぜなら、私はSQLを直接変更することができない製品を使用しているからです。 表3私はそれからデータを選択するのを忘れました。 UPDATE1でクエリを変更しました。 ref_idは文字列です。 idは、097777778018f16bのような数字と文字を持つ種類のGUIDです。 インデックス常に遅い場合はわかります。なぜ4 idsで速く、5 idsで遅いのですか?同様のように見えるが、異なるテーブルからデータを受け取り、同じ問題がある別のクエリもあります。細かい場合は4つの値、5の場合は遅い。 – Zlelik

+1

古い結合構文でクエリを生成する製品ですか? – GuidoG

+0

@GuidoG「DELL EMC Documentum」と呼ばれ、Documentum Content Serverによって自動的にSQLに変換されるDQL言語(Documentum Query Language)を提供します。私はこのDQLクエリを書いています。 LEFT結合構文がありますが、JOIN構文はありません。私はLEFT JOIN LEFT JOINのようにLEFT JOIN table2 t2 on t2.id = t1.ref_id ...のようにJOINをシミュレートしようとしましたが、どこにt2.id!= ''があり、動作します。それでもINには同じ問題があります。とにかく、このQueryをjoinで書き直すと、そのようには見えません。それはちょうど美しい構文のために戦っています:) – Zlelik

関連する問題