Мой первый инстинкт - ограничить набор результатов
SELECT *
FROM Kctc.FieldChanges
WHERE Kctc.FieldChanges.RecordId = Kctc.CaseTasks.CaseTaskId AND
Kctc.FieldChanges.TableName = 'CaseTasks' AND
Kctc.FieldChanges.DateOfChange BETWEEN
ISNULL(@ChangedAfter, '2000/01/01') AND
ISNULL(@ChangedBefore, '2050/01/01'
изменено на
SELECT TOP 1 Kctc.FieldChanges.RecordId
FROM Kctc.FieldChanges
WHERE Kctc.FieldChanges.RecordId = Kctc.CaseTasks.CaseTaskId AND
Kctc.FieldChanges.TableName = 'CaseTasks' AND
Kctc.FieldChanges.DateOfChange BETWEEN
ISNULL(@ChangedAfter, '2000/01/01') AND
ISNULL(@ChangedBefore, '2050/01/01'
затем посмотрите на индекс в полях в предложении where
РЕДАКТИРОВАТЬ: Относительно ТОП-1 - вероятно, не дает такой большой выгоды, но не должно причинять вреда, и может помочь избежать сканирования таблицы. Использование одного поля вместо * должно возвращать только этот столбец (я предполагаю, что это НЕ столбец значения NULL)
Дополнительные соображения: объявляйте и устанавливайте локальное значение вместо вещи ISNULL, которая обрабатывается несколько раз:
DECLARE @checkmyafter datetime; -- assumption on my part here on the type
SET @checkmyafter = ISNULL(@ChangedAfter, '2000/01/01');
сделать то же самое с ранее, затем использовать
...
SELECT TOP 1 Kctc.FieldChanges.RecordId
FROM Kctc.FieldChanges
WHERE Kctc.FieldChanges.RecordId = Kctc.CaseTasks.CaseTaskId AND
Kctc.FieldChanges.TableName = 'CaseTasks' AND
Kctc.FieldChanges.DateOfChange BETWEEN
@checkmybefore AND @checkmyafter
...
ОДНА БОЛЬШЕ: Проверьте последовательность WHERE xxx AND - используйте кандидат MOST LIKELY, чтобы изолировать FIRST в последовательности, в зависимости от того, какое условие есть, чтобы он мог выйти быстрее. Если это RecordId, то найдите, если TableName лучше, сначала используйте его. Если у одного столбца также есть индекс, считайте, что все остальные равны.