Indexhilfe für schlechte Abfrage auf ziemlich großem Tisch (2m)

7

Ich suche bitte Hilfe. Ich habe eine Abfrage, die für eine ziemlich große Tabelle ausgeführt wird (2 Millionen Datensätze).

Ich habe versucht, die Indizes effizient zum Laufen zu bringen. Es gibt einige andere Abfragen für diese Tabelle, aber dies ist bei weitem die häufigste. Ich habe ernsthafte Probleme damit, dass es in weniger als 1 Sekunde ausgeführt wird, und sehe es oft mit dem Profiler in 3 bis 5 Sekunden.

Es mag so schnell wie möglich sein, aber ich würde mich über eine Eingabe freuen, um dies zu bestätigen / abzulehnen.

Nur eine Anmerkung: Dev wird die Abfrage oder das Schema überhaupt nicht ändern. Optimierungen können nur in der Datenbank vorgenommen werden, und es werden keine Schemaänderungen vorgenommen.

Der Tisch:

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

Schnappschuss der Tabellendaten:

Screenshot der Beispieldaten

Die Abfrage:

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)

Versuchte Indizes:

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 enthält 3 verschiedene Typen, von denen 70% vom Typ 'Shift' sind. Der Status hat 10 Typen, aber die 'In Flight'-Datensätze sind nur etwa 100 bis 200, aufgeteilt auf 4 Status

Vielen Dank für Ihre Hilfe.

WadeH
quelle

Antworten:

15

Wenn die Unterabfrage in diesem Update diese beiden Prädikatwerte konsistent verwendet, sollte ein gefilterter Index sehr hilfreich sein. So etwas (das Erik Darling freundlicherweise als Kommentar zur Verfügung gestellt hat):

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

Dadurch kann die Unterabfrage die relevante Gruppe von IDs finden, die mit Statusund übereinstimmen NotificationType(da dies die einzigen Zeilen im Index sind), und das Sortieren der Daten vermeiden (da sie bereits nach ntID als führende Spalte im Index sortiert sind).

Es wird nach wie vor die überprüfen ResponseWindowauf jedem Zeilenwert. Im schlimmsten Fall wird der größte Teil oder der gesamte Index gelesen, wenn keine Zeilen vorhanden sind, die die Datumsanforderung für die Abfrage erfüllen (oder wenn die erste Übereinstimmung eine sehr hohe ntID aufweist). Dies macht die Wirksamkeit dieses Ansatzes abhängig von der Datenverteilung begrenzt.

Josh Darnell
quelle