Sql-Server

對相當大的表(2m)上的錯誤查詢的索引幫助

  • February 20, 2019

我正在尋求一些幫助。我有一個針對一個相當大的表(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’ 類型,Status 有 10 種類型,但 ‘In Flight’ 記錄只有 100 到 200 條左右,分為 4 個 Status

謝謝您的幫助。

如果該更新中的子查詢始終使用這兩個謂詞值,則過濾索引應該會有很大幫助。像這樣的東西(埃里克·達林(Erik Darling)作為評論提供):

CREATE INDEX IX_ntID_ResponseWindow_Includes ON dbo.Notifications (ntID, ResponseWindow) 
INCLUDE (NotificationType, Status) 
WHERE (Status = 'Done' AND NotificationType = 'Shift');

這將讓子查詢找到與Status和匹配的相關 ID 組NotificationType(因為它們是索引中的唯一行)並避免對數據進行排序(因為它已經按 ntID 作為索引中的前導列排序)。

它仍然需要檢查每一行的ResponseWindow。在最壞的情況下,如果沒有滿足查詢日期要求的行(或者如果第一個匹配項具有非常高的 ntID),則將讀取大部分或全部索引。這使得這種方法的有效性受到數據分佈的限制。

引用自:https://dba.stackexchange.com/questions/228876