У меня есть следующий запрос SQL:
SELECT
Event.ID,
Event.IATA,
Device.Name,
EventType.Description,
Event.Data1,
Event.Data2
Event.PLCTimeStamp,
Event.EventTypeID
FROM
Event
INNER JOIN EventType ON EventType.ID = Event.EventTypeID
INNER JOIN Device ON Device.ID = Event.DeviceID
WHERE
Event.EventTypeID IN (3, 30, 40, 41, 42, 46, 49, 50)
AND Event.PLCTimeStamp BETWEEN '2011-01-28' AND '2011-01-29'
AND Event.IATA LIKE '%0005836217%'
ORDER BY Event.ID;
У меня также есть индекс в Event
таблице для столбца TimeStamp
. Насколько я понимаю, этот индекс не используется из-за IN()
заявления. Итак, мой вопрос: есть ли способ сделать индекс для этого конкретного IN()
оператора, чтобы ускорить этот запрос?
Я также попытался добавить его Event.EventTypeID IN (2, 5, 7, 8, 9, 14)
в качестве фильтра для индекса TimeStamp
, но, глядя на план выполнения, он, похоже, не использует этот индекс. Любые предложения или понимание этого будет принята с благодарностью.
Ниже приведен графический план:
А вот и ссылка на файл .sqlplan .
Ответы:
Приведены таблицы следующего общего вида:
Следующий индекс полезен:
Для запроса:
Фильтр удовлетворяет
AND
требованию предложения, первый ключ индекса позволяет искать[TimeStamp]
фильтруемый столбец,EventTypeIDs
включаяDeviceID
столбец, который покрывает индекс (потому чтоDeviceID
требуется для соединения сDevice
таблицей).Второй ключ индекса -
EventTypeID
не является строго обязательным (это также может бытьINCLUDEd
столбец); Я включил его в ключ по причинам, указанным здесь . В общем, я советую людям по крайней мереINCLUDE
столбцы из предложения фильтрованного индексаWHERE
.Исходя из обновленного запроса и плана выполнения в вопросе, я согласен с тем, что более общий индекс, предложенный SSMS, вероятно, является лучшим выбором, если только список отфильтрованных не
EventTypeIDs
является статическим, как Аарон также упоминает в своем ответе:Предлагаемый индекс (объявите его уникальным, если это уместно):
Информация о количестве элементов из плана выполнения (недокументированный синтаксис, не используется в производственных системах):
Обновленный запрос (повторение
IN
списка дляEventType
таблицы помогает оптимизатору в данном конкретном случае):Предполагаемый план выполнения:
План, который вы получите, скорее всего, будет другим, потому что я использую предполагаемую статистику. Основная задача - предоставить оптимизатору как можно больше информации и обеспечить эффективный метод доступа (индекс) для
[Event]
таблицы с 4 миллионами строк .источник
Большую часть затрат составляет сканирование кластерного индекса, и если эта таблица не очень широка или вам не нужны все эти столбцы в выводе, я считаю, что SQL Server - это оптимальный путь в текущем сценарии, и больше ничего не изменилось. , Он использует сканирование диапазона (помеченное как поиск CI), чтобы сузить диапазон строк, в которых он заинтересован, но из-за выходных данных он все еще будет нуждаться в поиске или сканировании CI даже с отфильтрованным индексом, который вы создали, что предназначен для этого диапазона, и даже в этом случае сканирование CI, вероятно, все еще является самым дешевым (или, по крайней мере, SQL Server оценивает его как таковое).
План выполнения действительно говорит вам, что этот индекс будет полезен:
Хотя в зависимости от перекоса данных может быть лучше, например:
Но я бы проверил и то, и другое, чтобы убедиться, что лучше, если и то, и другое - разница между любым из этих индексов и тем, что у вас есть сейчас, может быть только предельной (слишком много переменных для нас, чтобы знать), и вы должны принять во внимание, что дополнительное Индекс требует дополнительного обслуживания, и это может заметно повлиять на ваши операции DML (вставка / обновление / удаление). Вы можете также рассмотреть возможность включения критериев фильтра в этот индекс, как это предлагается @SQLKiwi , но только если это набор значений EventTypeID, которые вы часто ищете. Если этот набор изменяется со временем, то отфильтрованный индекс будет полезен только для этого конкретного запроса.
При таком низком количестве строк мне интересно, насколько плохой может быть производительность в настоящее время? Этот запрос возвращает 3 строки (но нет никаких указаний на то, сколько строк он отклонил). Сколько строк в таблице?
источник
Я просто обнаружил, что SQL Server 2008 R2 фактически предлагал индексировать при запуске плана выполнения. Этот предложенный индекс ускоряет выполнение запроса примерно на 90%.
Предложенный индекс был следующим:
источник