2010-12-01 3 views
1

私はこのクエリを実行する場合予期しない推定行(SQL Server 2000の)

select user from largetable where largetable.user = 1155 

(私はちょうどその最も単純なケースにこれを削減するために、ユーザーを照会しています注意してください)

と見実行計画は、インデックスシーク[largetableがユーザーにインデックスを持っている]計画されている、と推定行が正しい29

ですが、私がしなければ

select user from largetable where largetable.user = (select user from users where externalid = 100) 

[サブコードの結果は、ハードコードしたときと同じように単一の値1155になります]

クエリオプティマイザは結果の117,000行を見積もります。対象となる行には約6,000,000行、ユーザーには1700行あります。クエリを実行すると、巨大な推定行にもかかわらず正しい29行が返されます。

関連インデックスの両方のテーブルでfullscanを使用して統計情報を更新しました。統計情報を見ると、正しいものとして表示されます。

注目すべきは、与えられたユーザーのために、3,000行を超えないことです。

したがって、推定された実行計画には、そのような推定行が非常に多く表示されるのはなぜですか?オプティマイザは、統計情報に基づいて、サブクエリによって選択されるユーザーがわからなくても29の対応する行を持つ結果、または3,000行の最大値を探していることを知っていないはずです。なぜこの巨大な見積もりですか?問題は、この大きな見積もりが、シークの代わりにスキャンを実行する大きなクエリの別の結合に影響を与えることです。サブクエリで大きなクエリを実行すると、1分40秒かかります。ハードコードされた1155で実行すると2秒かかります。これは私にとって非常に珍しいです...

おかげで、

クリス

答えて

0

あなたはこれを試していましたか?

SELECT lt.user 
FROM Users u 
    INNER JOIN largeTable lt 
     ON u.User = lt.User 
WHERE u.externalId = 100 

このご参照ください:subqueries-vs-joins

+1

はい、また、結合として書き直しても同じ問題が発生します。 – Querylous

1

をオプティマイザは、それができる最善を行いますが、(あなたが見ているとして)統計と行数の推定はこれまでのところに行きます。

私はあなたの複雑なクエリは、サブクエリなしで結合として簡単に書き換えられないと仮定しています。可能であれば、最初にそれを試みるべきです。

これで問題が解決しない場合は、データの性質に関する追加知識を使用して、hintsのオプティマイザを助けてください。具体的にはindexヒントのforceseekオプションをご覧ください。データが後で変更された場合、これは悪い可能性があるので注意してください。

+0

'forceseek'は2008年のみです。 OPは2000年です。 –

+0

ああ、それを認識していませんでした。しばらく前に2000年に移行したので、私はそれをテストするための何も持っていませんでした。 : – Donnie

+0

ドニーさんありがとうございました。私は参加して書き直しても同じ効果が得られます。SS 2000にはフォーステックはありませんが、私はそれをチェックします。 – Querylous

関連する問題