こんにちは、私は次のSQLサーバーデータベーステーブルを持っています:
複合主キーに注意してください。これは3つの理由で行われました。
このテーブルはサイズを考慮して設計されていることにも注意してください。このテーブルには数百万行のデータが格納されます。
私の実際の質問にはこれでOKです。 Azure SQLサーバーを使用してこのデータベースをホストしています。自動チューニングを有効にしました。そして不思議なことに、それはその後、新しいインデックスを作成して作成したことがわかりました。 (下記参照)
同じ列がインデックス付けされているので、今私の考えではこれは重複したインデックスのようです。
これで、テーブルに2つのインデックスができました。
オリジナル(私のPK):
ALTER TABLE [dbo].[SensorDataRaw] ADD CONSTRAINT [PK_SensorDataRaw] PRIMARY KEY CLUSTERED
(
[DateTime] ASC,
[SensorId] ASC,
[Key] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO
新しく追加された(Azureチューニングによって自動作成):
CREATE NONCLUSTERED INDEX [nci_wi_SensorDataRaw_DC9789077DA75B4440AC8BFE3E2AA198] ON [dbo].[SensorDataRaw]
(
[Key] ASC,
[SensorId] ASC,
[DateTime] ASC
)
INCLUDE ( [Value]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO
所見:
インデックスに関する私の知識は進んでいないので注意してください。
だから私の質問は:
追加情報:
ここではクエリのタイプが重要になると想定しているので、いくつかの例を挙げました。
すべてのクエリには、DateTime
、SensorId
、およびKey
が含まれます。
シンプルなクエリ:
Select SensorId Where average value for key w is greater than x where time between (y,z)
グラフデータ:
SELECT AVG([Value]) AS 'AvgValue',
DATEADD( MINUTE,
(DATEDIFF(MINUTE, '1990-01-01T00:00:00', [dbo].[SensorDataRaw].
[DateTime]) / @IntervalInMinutes) * @IntervalInMinutes,
'1990-01-01T00:00:00'
) AS 'TimeGroup'
FROM [dbo].[SensorDataRaw]
where
[dbo].[SensorDataRaw].[SensorId] = @SensorId
and [dbo].[SensorDataRaw].[Key] = @KeyValue
and [dbo].[SensorDataRaw].[DateTime] Between @DateFrom and @DateTo
and [dbo].[SensorDataRaw].[Value] IS NOT NULL
GROUP BY (DATEDIFF(MINUTE, '1990-01-01T00:00:00', [dbo].[SensorDataRaw].
[DateTime]) / @IntervalInMinutes)
システムが提案するインデックスは、表示したクエリにはるかに適しています。主要な列として、等式述部を持つ列を目指す必要があります。
lastname, firstname
によって注文された電話帳を検討してください。 「Brown」と「Yates」の間の姓と「John」の名を持つすべての人を検索する必要がある場合は、ほとんどの電話帳を読む必要があります。電話帳が代わりにfirstname, lastname
で注文された場合、「John」セクションとセクションの最初の「Brown」を簡単に見つけることができます。次に、lastname
が表示されるまですべての名前を読み取るだけで済みます。 「イェーツ」または新しい名に遭遇した後。
理想的なインデックスではない可能性があります。ただし、クラスター化インデックスのキー列を新しい順序で作成するのではなく、この順序に変更するだけでよい場合もあります。ワークロードの知識に基づいてこれを評価する必要があります。
新しく追加されたインデックスが最初に作成したインデックスよりも優れている理由を誰かが説明できますか
インデックスはclustered
oneです。つまり、リーフレベルとしてすべてのデータが含まれています。
サーバーが提供するインデックスは狭いkey fields
+ included field
リーフレベル。
クエリに必要なのはkey fields
+ value
フィールドなので、サーバーによって提供される非クラスター化インデックスで十分であり、サーバーによって、可能な最も狭いカバリングインデックスとして選択されます。
2つのインデックスを削除して、両方のケースをカバーするインデックスを作成するにはどうすればよいですか。
非クラスター化インデックスは削除でき、クラスター化はもちろん1つをカバーします。追加フィールドが2つしかない場合は、非クラスター化に関してdatetime2(2)+ decimal(19,4)を使用します。クラスター化。
推奨されるインデックスはより狭く、クエリがそのインデックスでカバーされる列のみを処理する場合により効率的になります。
列の順序も異なるため、特定のクエリに対してより効率的になる可能性があります(実行プランを確認しないと確実に判断できません)。列の順序は違いを生みます。
非クラスター化インデックスはその特定のクエリには適しているかもしれませんが、すべてを網羅しているわけではありません。さらに、クラスター化インデックスを削除することはできず、両方を保持しても問題はありません。
2つを試してみて、クラスター化インデックスを強制し、実行プランとIO statsを確認してから、非クラスター化を強制して比較します。