2012-01-03 9 views
4

私はソリューションを実装するために必要な特別なシナリオのために、単一のテーブルでデータベースを設計しています。テーブルは短時間で数億行になりますが、各行はかなりコンパクトです。行がたくさんある場合でも、すばやく高速に挿入、更新、選択する必要があるため、そのジョブに最適なインデックスを選択する必要があります。SQL Serverのインデックス - 非常に大きな値域に対してwhere句を持つ非常に大きなテーブル - where句のインデックスが必要ですか?

私のテーブルには、次のようになります。

create table dbo.Domain 
(
    Name varchar(255) not null, 
    MetricType smallint not null, -- very small range of values, maybe 10-20 at most 
    Priority smallint not null, -- extremely small range of values, generally 1-4 
    DateToProcess datetime not null, 
    DateProcessed datetime null, 

    primary key(Name, MetricType) 
); 

選択クエリは次のようになります。

select Name from Domain 
where MetricType = @metricType 
    and DateProcessed is null 
    and DateToProcess < GETUTCDATE() 
order by Priority desc, DateToProcess asc 

更新の第1のタイプは次のようになります。

merge into Domain as target 
using @myTablePrm as source 
on source.Name = target.Name 
    and source.MetricType = target.MetricType 
when matched then 
    update set 
     DateToProcess = source.DateToProcess, 
     Priority = source.Priority, 
     DateProcessed = case -- set to null if DateToProcess is in the future 
      when DateToProcess < DateProcessed then DateProcessed 
      else null end 
when not matched then 
    insert (Name, MetricType, Priority, DateToProcess) 
    values (source.Name, source.MetricType, source.Priority, source.DateToProcess); 

2番目のタイプのアップデートは次のようになります:

update Domain 
set DateProcessed = source.DateProcessed 
from @myTablePrm source 
where Name = source.Name and MetricType = @metricType 

これらは最適な挿入、更新、選択速度の指標ですか?

-- for the order by clause in the select query 
create index IX_Domain_PriorityQueue 
    on Domain(Priority desc, DateToProcess asc) 
    where DateProcessed is null; 

-- for the where clause in the select query 
create index IX_Domain_MetricType 
    on Domain(MetricType asc); 

答えて

4

観察:行も狭くするためにtinyint型(0〜255の範囲)を使用しないのはなぜ

  • あなたのアップデートはPK
  • を使用する必要がありますか?
  • 日時が必要ですか? smalledatetimeを使用できますか?

アイデア:

  • あなたのSELECTクエリがそれをカバーするためにインデックスを持っていません。あなたは(DateToProcess, MetricType, Priority DESC) INCLUDE (Name) WHERE DateProcessed IS NULL `上のいずれかが必要:あなたは)あなたは、インデックスがあまりにもMetricTypeあたりのフィルタのインデックスを持っているという程度(DateProcessedを維持することができる最高の1

  • がNULLフィルタであり、取得するキー列の順序で実験する必要があります。私は

+0

ああ、私はインクルード句を認識していませんでした。 –

+0

@NathanRidley:私の回答をもっと更新しました。 – gbn

+0

ああ、それはいい考えです。あなたはそれが真剣に大きな違いをもたらすと思いますか?最初の実行では、データベースには約1億5000万行の行があるはずです。 –

1

は、私はあなたの最高のパフォーマンスがPriorityMetricTypeにはインデックスを持たないから来ると思われます。カーディナリティは、インデックスがあまりにも低すぎる可能性が非常に高いです。

DateToProcessのインデックスは、その列に高いカーディナリティがあり、WHEREおよびORDER BY節で使用されているため、ほぼ確実に役立ちます。私はまずそれから始めます。

インデックスがDateProcessedにあるかどうかが議論の対象になるかどうか。これは、この列に何パーセントの値を入力するかによって異なります。通常どおり、実際のデータでクエリプランを調べることをお勧めします。

+0

をテストするために数百万行を持っていないとき、私は他のものの後にこれを行うと思いますので、あなたは私の最初のインデックスはちょうどDateToProcessになると優先順位を無視すべきではないでしょうか?それがインデックスを引き起こすのに、私が持っているでしょうあらかじめ用意された順番に並べ替えると、SQL Serverの処理が少なくなるでしょう。 –

0

テーブルスキーマのセクションでは、 'MetricType'が2つのプライマリキーのうちの1つであることを強調しています。したがって、これは必ず名前列と共に索引付けする必要があります。 'Priority'フィールドと 'DateToProcess'フィールドは、where句に表示されるので、インデックスを作成することはできませんが、 'DateProcessed'のインデックスがwhereであるwhere句は推奨しませんデータのセットだけを索引付けするのは良い考えではありません。これを削除して、両方の列の全体を索引付けします。

+0

インデックスのwhere句は、関連するクエリから除外され、インデックスサイズを小さくしてスキャンと更新を高速化します。 –

+0

'DateProcessed'がnullでないクエリの将来の必要性はありませんか?私はちょっと前に考えています。そうでない場合は –

+0

いいえ、このテーブルは非常に大きなデータセットのバッチ処理の優先順位をアシストするためのものですのデータ。クエリのルールは既にかなりの部分が設定されており、いつでも変更することができれば、テーブルは実際には壊れてしまい、プライマリデータソースから再構築される可能性があります。 –

関連する問題