何か助けを求めています。かなり大きなテーブル(200万レコード)に対して実行されているクエリがあります。
私はインデックスが効率的に機能するように努めています。このテーブルに対するクエリは他にもいくつかありますが、これが圧倒的に最も頻繁なクエリです。私はそれを1秒未満で実行するのに真剣に取り組んでおり、プロファイラーを使用して3〜5秒で実行されるのをよく見かけます。
可能な限り高速かもしれませんが、確認/拒否するための入力をお願いします。
注:開発者はクエリやスキーマをまったく変更しません。最適化はデータベースでのみ行うことができ、スキーマは変更されません。
テーブル:
CREATE TABLE [dbo].[Notifications](
[ntID] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[NotificationID] [int] NOT NULL,
[NotificationType] [nvarchar](50) NOT NULL,
[UserName] [nvarchar](50) NULL,
[CreatedBy] [nvarchar](50) NULL,
[CreatedOn] [datetime] NULL,
[Status] [nvarchar](50) NOT NULL,
[Result] [nvarchar](50) NULL,
[Extension] [nvarchar](50) NULL,
[ShiftRate] [nvarchar](255) NULL,
[ResponseMinutes] [int] NULL,
[ResponseWindow] [datetime] NULL,
[caNotificationID] [int] NULL,
[AwardedBy] [nvarchar](50) NULL,
[AwardedOn] [datetime] NULL,
[CancelledBy] [nvarchar](50) NULL,
[CancelledOn] [datetime] NULL,
[CancelledReasonID] [int] NULL,
[CancelledReasonText] [nvarchar](255) NULL,
[AwardingDate] [datetime] NULL,
[ScheduledLaunchDate] [datetime] NULL,
[CustomMessage] [nvarchar](160) NULL,
[SystemName] [nvarchar](4000) NULL,
[AutoClose] [bit] NOT NULL,
CONSTRAINT [PK_ESP_Notifications_ntID] PRIMARY KEY CLUSTERED
(
[ntID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[ESP_Notifications] ADD DEFAULT ((0)) FOR [AutoClose]
GO
テーブルデータのスナップショット:
クエリ:
Update Notifications
set Status = 'Awarding' OUTPUT deleted.*
where ntID = (
select top(1) ntID
from Notifications
where NotificationType = 'Shift'
and (Status = 'Done')
and ResponseWindow < '2019-02-04 10:40:03'
order by ntID)
試行されたインデックス:
CREATE INDEX [IX_Notifications_Status_NotificationType_ResponseWindow_ntID]
ON [dbo].[Notifications](
[Status] ASC,[NotificationType] ASC,[ResponseWindow] DESC,[ntID] DESC
)
CREATE INDEX [IX_Notifications_Status_ScheduledLaunchDate_ntID]
ON [dbo].[Notifications](
[ScheduledLaunchDate] DESC,[Status] ASC,[ntID] ASC
)
CREATE INDEX [IX_Notifications_NotificationType_caNotificationID_NotificationID_ntID]
ON [dbo].[Notifications](
[NotificationType] DESC, [caNotificationID] DESC, [NotificationID] DESC, [ntID] DESC
);
NotificationTypeには3つの異なるタイプが含まれ、そのうち70%はタイプ「Shift」ステータスが10タイプですが、「In Flight」レコードは約100から200のみで、4つのステータスに分割されます
ご協力いただきありがとうございます。
その更新のサブクエリがこれら2つの述語値を一貫して使用する場合、フィルター選択されたインデックスが非常に役立ちます。次のようなもの(コメント Erik Darling を提供してください):
CREATE INDEX IX_ntID_ResponseWindow_Includes ON dbo.Notifications (ntID, ResponseWindow)
INCLUDE (NotificationType, Status)
WHERE (Status = 'Done' AND NotificationType = 'Shift');
これにより、サブクエリはStatus
とNotificationType
に一致するIDの関連グループを検索し(インデックス内の唯一の行であるため)、データのソートを回避します(すでにntIDで並べ替えられているため)インデックスの先頭列)。
それは、各行のResponseWindow
値をチェックする必要があります。最悪の場合、クエリの日付要件を満たす行がない場合(または最初の一致が非常に高いntIDである場合)、ほとんどまたはすべてのインデックスが読み取られます。そのため、このアプローチの効果はデータの配布に応じて制限されます。