このようなテーブルがあります:
CREATE TABLE Updates
(
UpdateId INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
ObjectId INT NOT NULL
)
基本的に、IDが増加するオブジェクトの更新を追跡します。
このテーブルのコンシューマーはUpdateId
、特定のから順に特定の100個のオブジェクトIDのチャンクを選択しますUpdateId
。基本的に、中断した場所を追跡し、更新をクエリします。
私はクエリのみ書き込むことによって最大限に最適なクエリプランを生成することができましたので、これは興味深い最適化問題であることがわかってきましたが起こる私はインデックスのためにやりたいが、ないが保証する私が欲しいもの:
SELECT DISTINCT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
@fromUpdateId
ストアドプロシージャのパラメーターはどこにありますか。
次の計画:
SELECT <- TOP <- Hash match (flow distinct, 100 rows touched) <- Index seek
UpdateId
使用されているインデックスのシークにより、結果は既に素晴らしく、必要な更新IDの最低から最高まで並べられています。そして、これはフロー別の計画を生成します。それは私が望むものです。しかし、順序は明らかに動作を保証するものではないため、使用したくありません。
このトリックにより、同じクエリプランが得られます(ただし、冗長なTOPがあります)。
WITH ids AS
(
SELECT ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
ORDER BY UpdateId OFFSET 0 ROWS
)
SELECT DISTINCT TOP 100 ObjectId FROM ids
ただし、これが本当に順序付けを保証するかどうかはわかりません(疑わない)。
SQL Serverが単純化するのに十分スマートであることを期待していたクエリの1つが、非常に悪いクエリプランを生成することになりました。
SELECT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
GROUP BY ObjectId
ORDER BY MIN(UpdateId)
次の計画:
SELECT <- Top N Sort <- Hash Match aggregate (50,000+ rows touched) <- Index Seek
インデックスのシークUpdateId
と重複したs を削除するフローを区別して最適なプランを生成する方法を見つけようとしていますObjectId
。何か案は?
必要に応じてサンプルデータ。オブジェクトはめったにつ以上の更新を持っていないだろう、と私は後だ理由である100行のセット内に複数の、持っていることはほとんどないはずです明確な流れをそこの何かが良く、私が知らない場合を除き、?ただし、ObjectId
1つのテーブルに100行を超えないという保証はありません。テーブルには1,000,000行を超える行があり、急速に拡大することが予想されます。
これのユーザーが適切な次を見つける別の方法を持っていると仮定してください@fromUpdateId
。このクエリで返す必要はありません。