SQL Server 2016データベースを実行していますが、次の表には1億を超える行があります。
StationId | ParameterId | DateTime | Value
1 | 2 | 2020-02-04 15:00:000 | 5.20
1 | 2 | 2020-02-04 14:00:000 | 5.20
1 | 2 | 2020-02-04 13:00:000 | 5.20
1 | 3 | 2020-02-04 15:00:000 | 2.81
1 | 3 | 2020-02-04 14:00:000 | 2.81
1 | 4 | 2020-02-04 15:00:000 | 5.23
2 | 2 | 2020-02-04 15:00:000 | 3.70
2 | 4 | 2020-02-04 15:00:000 | 12.20
3 | 2 | 2020-02-04 15:00:000 | 1.10
このテーブルには、StationId、ParameterId、DateTimeのクラスター化インデックスがあり、この順序で昇順になっています。
必要なのは、StationId-ParameterIdの一意のペアごとに、DateTime列から最新の値を返すことです。
StationId | ParameterId | LastDate
1 | 2 | 2020-02-04 15:00:000
1 | 3 | 2020-02-04 15:00:000
1 | 4 | 2020-02-04 15:00:000
2 | 2 | 2020-02-04 15:00:000
2 | 4 | 2020-02-04 15:00:000
3 | 2 | 2020-02-04 15:00:000
現在実行しているのは次のクエリで、実行に約90〜120秒かかります。
SELECT StationId, ParameterId, MAX(DateTime) AS LastDate
FROM MyTable WITH (NOLOCK)
GROUP BY StationId, ParameterId
私はまた、以下を提案する多くの投稿を見てきました。実行には10分以上かかります:
SELECT StationId, ParameterId, DateTime AS LastDate
FROM
(
SELECT StationId, ParameterId, DateTime
,ROW_NUMBER() OVER (PARTITION BY StationId,ParameterIdORDER BY DateTime DESC) as row_num
FROM MyTable WITH (NOLOCK)
)
WHERE row_num = 1
最良の場合でも(GROUP BY句とMAX集計関数を使用)、実行プランはインデックスシークを示しません。
より良い実行時間を達成するために、このクエリを実行する(またはインデックスを構築する)より良い方法があるかどうか疑問に思います。
(StationID、ParameterID)ペアの数が少ない場合は、次のようなクエリを試してください。
select StationID, ParameterID, m.DateTime LastDate
from StationParameter sp
cross apply
(
select top 1 DateTime
from MyTable
where StationID = sp.StationID
and ParameterID = sp.ParameterID
order by DateTime desc
) m
SQL Serverがルックアップを実行できるようにするには、各(StationID、ParameterID)ペアの最新のDateTime
を探します。
(StationID、ParameterID、DateTime)のクラスター化インデックスのみでは、SQL Serverがインデックスのリーフレベルをスキャンせずに個別の(StationID、ParameterID)ペアを検出する方法はなく、スキャン中に最大のDateTimeを見つけることができます。
また、100M以上の行では、このテーブルは、BTreeクラスター化インデックスよりもクラスター化列ストアとして優れている場合があります。
パフォーマンスが非常に重要で、テーブルに最新の日付を頻繁に要求する場合...最新のタイムスタンプを持つキーとしてステーションとパラメーターのルックアップテーブルを作成してみませんか。大きなテーブルを変更するたびにこのテーブルを更新する必要がありますが、この方法では、必要なときに結果をミリ秒で取得できます。
CTEのrow_numberアプローチでは、StationId, ParameterId, DateTime desc
に非クラスター化インデックスを作成してみてください。 partition by order句が使用する適切なソート順のインデックスがあると、パフォーマンスが向上することがわかりました。