#sql #sql-server #optimization #query-optimization
#sql #sql-сервер #оптимизация #Оптимизация запросов
Вопрос:
Мы разрабатываем запрос, чтобы попытаться найти все сообщения в таблице, в которых последнее событие сообщения ошибочно. Сообщения могут быть повторно обработаны, и это может привести их в хорошее состояние, поэтому мы ищем самые последние, даже если они ошибочны. Мы не сильны в нашем SQL, и запрос, который мы в настоящее время выполняем, занимает гораздо больше времени, чем хотелось бы. Есть ли что-нибудь помимо добавления индексов или уменьшения размера таблицы, что могло бы ускорить выполнение этого запроса? Можно ли это сделать без объединения?
SELECT M.MessageID AS MessageID,
Source,
IntakeTimestamp,
MessageKey,
MessageSourceID,
CustomerID,
AgreementID,
LocationID,
EquipmentID,
OfficeID,
IncidentID,
M.HistoryID AS HistoryID,
Subject,
FromHeader,
ToHeader,
PackedHeaders
FROM [pipe].[Message] AS M
JOIN [pipe].[MessageState] AS MS ON MS.MessageID = M.MessageID
WHERE MessageStateID IN (
SELECT TOP 1 MessageStateID FROM [pipe].[MessageState] AS NMS
WHERE M.MessageID = NMS.MessageID
AND MS.EventStatusID = 6
ORDER BY MessageStateID DESC )
ORDER BY [MessageID] DESC
Я смог извлечь все сообщения в состоянии ошибки с помощью простого запроса, приведенного ниже, но при этом не проверялось только самое последнее состояние сообщения
SELECT * FROM [pipe].[Message]
WHERE MessageID IN (
SELECT *
FROM [pipe].[MessageState]
WHERE EventStatusID = 6
)
Комментарии:
1. чем старые строки отличаются от самой последней строки ? Отличаются ли только IntakeTimeStamp и MessageStateID или также другие столбцы?
2. Метка времени ввода — это время получения сообщения, а не время его обработки, поэтому оно также будет одинаковым. Единственное, что изменится, это MessageStateID и EventStatusID.
3. На это нельзя ответить без плана запроса. Пожалуйста, отредактируйте его — выполните в SSMS, получите панель запросов, поместите ее, т. е. на supratimas.com — не зная, КАК это выполняется, мы не можем видеть, что не так. Одна вещь, которую я вижу, это подзапрос — TOP 1 …. вы можете запустить его как WHERE EXISTS, а не WHERE IN, затем удалить Top 1 .
4. Ах, скорее ue brentozar.com/pastetheplan — это может дать вам ссылку, содержащую план.
5. Работаю над этим сейчас. Спасибо
Ответ №1:
Вы можете попробовать что-то вроде приведенного ниже, чтобы найти самую последнюю запись для каждого MessageID
, предполагая, что ваш MessageStateID
порядок подходит для ваших данных. Это работает путем присвоения каждой группе строк с одинаковым MessageID
значением номера строки, который сортируется в порядке убывания MessageStateID
значения. При этом любая запись со rn
значением 1
является самой последней записью для этого MessageID
:
WITH m AS
(
SELECT M.MessageID,
Source,
IntakeTimestamp,
MessageKey,
MessageSourceID,
CustomerID,
AgreementID,
LocationID,
EquipmentID,
OfficeID,
IncidentID,
M.HistoryID AS HistoryID,
Subject,
FromHeader,
ToHeader,
PackedHeaders,
MS.EventStatusID,
ROW_NUMBER() OVER (PARTITION BY M.MessageID ORDER BY M.MessageStateID DESC) AS rn
FROM [pipe].[Message] AS M
JOIN [pipe].[MessageState] AS MS
ON MS.MessageID = M.MessageID
)
SELECT m.*
FROM m
WHERE m.rn = 1
AND m.EventStatusID = 6
ORDER BY m.MessageID DESC
Я бы также рекомендовал вам правильно присвоить псевдонимы всем вашим столбцам, чтобы вы знали, из какой таблицы они поступают.