Sql-Server
對相當大的表(2m)上的錯誤查詢的索引幫助
我正在尋求一些幫助。我有一個針對一個相當大的表(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),則將讀取大部分或全部索引。這使得這種方法的有效性受到數據分佈的限制。