Что делает предложение SQL обоснованным?

По определению (по крайней мере, из того, что я видел) sargable означает, что запрос способен заставить механизм запроса оптимизировать план выполнения, который использует запрос. Я попытался найти ответы, но, похоже, на этот вопрос не так много. Итак, вопрос в том, что делает или не делает SQL-запрос приемлемым? Любая документация была бы весьма признательна.

Для справки: SARGable

Ответ 1

Наиболее распространенная вещь, которая сделает запрос неприемлемым, заключается в том, чтобы включить поле внутри функции в предложении where:

SELECT ... FROM ...
WHERE Year(myDate) = 2008

Оптимизатор SQL не может использовать индекс для myDate, даже если он существует. Это буквально придется оценивать эту функцию для каждой строки таблицы. Гораздо лучше использовать:

WHERE myDate >= '01-01-2008' AND myDate < '01-01-2009'

Некоторые другие примеры:

Bad: Select ... WHERE isNull(FullName,'Ed Jones') = 'Ed Jones'
Fixed: Select ... WHERE ((FullName = 'Ed Jones') OR (FullName IS NULL))

Bad: Select ... WHERE SUBSTRING(DealerName,4) = 'Ford'
Fixed: Select ... WHERE DealerName Like 'Ford%'

Bad: Select ... WHERE DateDiff(mm,OrderDate,GetDate()) >= 30
Fixed: Select ... WHERE OrderDate < DateAdd(mm,-30,GetDate()) 

Ответ 2

Не делай этого:

WHERE Field LIKE '%blah%'

Это вызывает сканирование таблицы/индекса, поскольку значение LIKE начинается с символа подстановки.

Не делай этого:

WHERE FUNCTION(Field) = 'BLAH'

Это вызывает сканирование таблицы/индекса.

Сервер базы данных должен будет сравнить FUNCTION() с каждой строкой таблицы, а затем сравнить ее с BLAH.

Если возможно, сделайте это в обратном порядке:

WHERE Field = INVERSE_FUNCTION('BLAH')

Это запустит INVERSE_FUNCTION() для параметра один раз и все равно позволит использовать индекс.

Ответ 3

В этом ответе я предполагаю, что база данных имеет достаточные индексы покрытия. Существует достаточно вопросов о этот раздел.

В большинстве случаев надежность запроса определяется точкой опроса соответствующих индексов. Точка опрокидывания определяет разницу между поиском и сканированием индекса при соединении одной таблицы или набора результатов с другим. Один поиск, конечно, намного быстрее, чем сканирование всей таблицы, но когда вам нужно искать много строк, сканирование может иметь больше смысла.

Таким образом, среди прочего, оператор SQL более ориентирован, когда оптимизатор ожидает, что число результирующих строк одной таблицы будет меньше точки опроса возможного индекса в следующей таблице.

Вы можете найти подробное сообщение и пример здесь.

Ответ 4

Для того чтобы операция считалась способной к переносу, недостаточно просто использовать существующий индекс. В приведенном выше примере добавление вызова функции к индексированному столбцу в предложении where, скорее всего, будет иметь преимущество в отношении определенного индекса. Он "сканирует" aka извлекает все значения из этого столбца (индекс), а затем удаляет те, которые не соответствуют предоставленному фильтру. Он по-прежнему недостаточно эффективен для таблиц с большим количеством строк. То, что на самом деле определяет надежность, - это способность запроса пересекать индекс b-дерева с использованием метода двоичного поиска, который полагается на устранение половины набора для массива отсортированных элементов. В SQL он будет отображаться в плане выполнения как "поиск индекса".