特定のクエリで使用されている実行プランに問題があるため、CPUスパイクが100%になるという大きな問題があります。私は今、自分で解決するのに数週間を費やしています。
私のデータベース
私のサンプルDBには、3つの簡略化されたテーブルが含まれています。
[データ・ロガー]
CREATE TABLE [model].[DataLogger](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[ProjectID] [bigint] NULL,
CONSTRAINT [PK_DataLogger] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
【インバーター】
CREATE TABLE [model].[Inverter](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[SerialNumber] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Inverter] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY],
CONSTRAINT [UK_Inverter] UNIQUE NONCLUSTERED
(
[DataLoggerID] ASC,
[SerialNumber] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [model].[Inverter] WITH CHECK
ADD CONSTRAINT [FK_Inverter_DataLogger]
FOREIGN KEY([DataLoggerID])
REFERENCES [model].[DataLogger] ([ID])
[InverterData]
CREATE TABLE [data].[InverterData](
[InverterID] [bigint] NOT NULL,
[Timestamp] [datetime] NOT NULL,
[DayYield] [decimal](18, 2) NULL,
CONSTRAINT [PK_InverterData] PRIMARY KEY CLUSTERED
(
[InverterID] ASC,
[Timestamp] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF)
)
統計とメンテナンス
[InverterData]
表には、毎月のジャンクに分割(複数のインスタンスのPaaSの点で異なる)複数の万行が含まれています。
すべてのインデクサーは最適化され、すべての統計情報は、必要に応じて毎日/毎週の順番で再構築/再編成されます。
私のクエリ
クエリはEntity Frameworkで生成され、また単純です。しかし、私は毎分1,000回実行し、パフォーマンスは不可欠です。
SELECT
[Extent1].[InverterID] AS [InverterID],
[Extent1].[DayYield] AS [DayYield]
FROM [data].[InverterDayData] AS [Extent1]
INNER JOIN [model].[Inverter] AS [Extent2] ON [Extent1].[InverterID] = [Extent2].[ID]
INNER JOIN [model].[DataLogger] AS [Extent3] ON [Extent2].[DataLoggerID] = [Extent3].[ID]
WHERE ([Extent3].[ProjectID] = @p__linq__0)
AND ([Extent1].[Date] = @p__linq__1) OPTION (MAXDOP 1)
MAXDOP 1
ヒントは遅いparalel計画に別の問題のためです。
「良い」計画
時間の90%以上で、使用済みプランは非常に高速で、次のようになります。
問題
その日のうちに、良い計画はランダムに悪い遅い計画に変わりました。
「悪い」計画は10〜60分間使用され、その後「良い」計画に変更されます。「悪い」計画では、CPUが最大100%まで急上昇します。
これはどのように見えるかです:
これまでにやってみたこと
私が最初に思ったのHash Match
は、悪い子だということでした。そこで、新しいヒントを使用してクエリを変更しました。
...Extent1].[Date] = @p__linq__1) OPTION (MAXDOP 1, LOOP JOIN)
LOOP JOIN
使用することを強制する必要があるNested Loop
の瞬間をHash Match
。
その結果、90%の計画は以前のようになります。しかし、計画はまた、ランダムに悪い計画に変更されました。
「悪い」計画は次のようになります(テーブルループの順序が変更されました)。
「新しい悪い」計画の間、CPUは100%までピークします。
解決?
「良い」計画を強制することが私の心に浮かびます。しかし、これが良い考えかどうかはわかりません。
計画内には、すべての列を含む推奨索引があります。しかし、これによりテーブル全体が2倍になり、頻繁に発生する挿入が遅くなります。
私を助けてください!
更新1-@Jamesコメントに関連
以下は両方のプランです(実際のテーブルからのものであるため、いくつかの追加フィールドがプランに表示されています)。
アップデート2-@David Fowler answereに関連
悪い計画は、ランダムなパラメーター値を実行しています。だから私@p__linq__1 ='2016-11-26 00:00:00.0000000' @p__linq__0 =20825
は通常、ホールデイと同じ価値で来る悪い計画よりも。
ストアドプロシージャからのパラメータスニッフィングの問題と、SP内でそれらを回避する方法を知っています。私のクエリでこの問題を回避する方法についてのヒントはありますか?
推奨インデックスを作成すると、すべての列が含まれます。これにより、テーブル全体が2倍になり、頻繁に発生する挿入が遅くなります。これは、テーブルを複製するだけのインデックスを作成する「感覚」ではありません。また、この大きなテーブルのデータサイズを2倍にすることを意味します。
更新3-@David Fowlerコメントに関連
それも機能しなかったし、できなかったと思います。理解を深めるために、クエリの呼び出し方法について説明します。
[DataLogger]
テーブルに3つのエンティティがあるとします。1日の間に、同じ3つのクエリを何度も往復で呼び出します。
基本クエリ:
...WHERE ([Extent3].[ProjectID] = @p__linq__0) AND ([Extent1].[Date] = @p__linq__1)
パラメータ:
@p__linq__0 = 1; @p__linq__1 = '2018-01-05 00:00:00.0000000'
@p__linq__0 = 2; @p__linq__1 = '2018-01-05 00:00:00.0000000'
@p__linq__0 = 3; @p__linq__1 = '2018-01-05 00:00:00.0000000'
パラメータ@p__linq__1
は常に同じ日付です。しかし、以前は適切なプランで数千回実行されるクエリで、ランダムに悪いプランを選択します。同じパラメーターで!
更新4-@Nicコメントに関連
メンテナンスは毎晩実行され、次のようになります。
インデックス
インデックスが5%以上断片化されている場合、再編成されます...
ALTER INDEX [{index}] ON [{table}] REORGANIZE
インデックスがさらに断片化されている場合、30%が再構築されます...
ALTER INDEX [{index}] ON [{table}] REBUILD WITH (ONLINE=ON, MAXDOP=1)
インデックスがパーティション化されている場合、フラグメント化について証明され、パーティションごとに変更されます...
ALTER INDEX [{index}] ON [{table}] REBUILD PARTITION = {partitionNr} WITH (ONLINE=ON, MAXDOP=1)
統計
がmodification_counter
0より大きい場合、すべての統計が更新されます...
UPDATE STATISTICS [{schema}].[{object}] ([{stats}]) WITH FULLSCAN
またはパーティションに分割されています。
UPDATE STATISTICS [{schema}].[{object}] ([{stats}]) WITH RESAMPLE ON PARTITIONS({partitionNr})
メンテナンスには、すべての統計情報と、自動生成された統計情報が含まれます。