3

3 つの関数とその下にいくつかの異なるビューを使用するクエリがありますが、複雑すぎてここに投稿できません。私が経験している奇妙なことは、最上位のクエリを実行するときです。複数の検索キーがあると、クエリの実行に約 1 時間かかります。クエリを 2 つに分割するには、クエリごとに約 5 秒かかります。

トップレベルのクエリは次のとおりです。

Select * 
from  dbo.vwSimpleInvoice i 
inner join dbo.vwRPTInvoiceLineItemDetail d on i.InvoiceID = d.InvoiceID 

このwhere句を追加すると:

Where i.InvoiceID = 109581

クエリの実行には約 3 秒かかります。同様に、このwhere句を追加すると:

Where i.InvoiceID = 109582

約3秒かかります。

ただし、このwhere句を追加すると:

Where i.InvoiceID in (109581, 109582)

約 50 分後にクエリを強制終了する必要がありましたが、結果が返されません。

これは、SQL Server 2008 R2 Express を実行しているリモート クライアントのサーバーで発生しています。ローカルで (SQL Server 2008 R2 Express でも) 実行すると、大きな遅延は発生しません。最後の where 句が返されるまでに約 30 秒かかります。ただし、クライアントは私よりも多くのデータを持っています。

これのトラブルシューティングを開始する場所はありますか?

編集:

以下のコメントの後、インデックスと統計を再構築しました。これにより、最初の 2 つの where 句のパフォーマンスが向上しましたが、3 番目の句には影響しませんでした。次に、クエリをいじってみたところ、次のように書き直すと次のことがわかりました。

Select * 
from  dbo.vwSimpleInvoice i 
inner join  
    (Select * from dbo.vwRPTInvoiceLineItemDetail) d on i.InvoiceID = d.InvoiceID 
Where i.InvoiceID in (109581, 109582)

パフォーマンスは、約 200 ミリ秒で期待されるレベルに戻ります。何が起こっているのか、今まで以上に当惑しています...

編集2:

実際、私は間違っています。そのようにクエリを書き直したのではなく、書き直し中に誤って Where 句を次のように変更しました。

Where d.InvoiceID in (109581, 109582)

i(に変更d)。

なぜこれが内部結合に大きな違いをもたらすのか、まだ少し迷っていますか?


さらに編集:

これをさらにいじっても、まだ理解できません。

Select InvoiceId from tblInvoice Where CustomerID = 2000

戻り値:

80442, 4988, 98497, 102483, 102484, 107958, 127063, 168444, 168531, 173382, 173487, 173633, 174013, 174160, 174240, 175389

Select * from dbo.vwRPTInvoiceLineItemDetail
Where InvoiceID in 
(80442, 4988, 98497, 102483, 102484, 107958, 127063, 168444, 168531, 173382, 173487, 173633, 174013, 174160, 174240, 175389)

実行: 31 行返された 110 ミリ秒

Select * from dbo.vwRPTInvoiceLineItemDetail
Where InvoiceID in 
(Select InvoiceId from tblInvoice Where CustomerID = 2000)

実行: 31 行が返され、65 分

4

1 に答える 1

3

あなたが経験している問題は、(ほぼ確実に)キャッシュされたクエリプランが原因です。これは、クエリに渡されるパラメータの一部のバージョンには適していますが、他のバージョンには適していません(別名パラメータスニッフィング)。

これはよくあることで、古い統計や不適切に断片化されたインデックスによって悪化することがよくあります。

最初のステップ: すべてのインデックスを再構築し、インデックスが作成されていない列の統計が最新であることを確認します。(また、クライアントに定期的にスケジュールされたインデックス メンテナンス ジョブがあることを確認してください)

exec sp_msforeachtable "DBCC DBREINDEX('?')"
go

exec sp_msforeachtable "UPDATE STATISTICS ? WITH FULLSCAN, COLUMNS"
go

これは正規のリファレンスです:アプリケーションで遅く、SSMS で高速ですか?

インデックスを再構築して統計を更新した後も問題が解決しない場合は、いくつかのオプションがあります。

  1. 動的 SQL を使用します (ただし、最初にこれをお読みください: The Curse and Blessings of Dynamic SQL )

  2. 使用するOPTIMIZE FOR

  3. 使用するWITH(RECOMPILE)

于 2012-09-11T03:17:09.063 に答える