Что на самом деле означает слово «SARGable»?

23

Пользователи SQL Server используют термин «sargable» . Мне интересно, существует ли объективное, независимое от реализации определение вне времени для "sargable".

Например, WHERE foo LIKE '%bar%'многие говорят, что это не sargable , но некоторые РСУБД могут использовать индексы для таких запросов . Что же значит «не саргализируемый» ?

Другие ссылки

Эван Кэрролл
источник
5
Вы можете указать, что ваш вопрос не о SQL Server, а о термине « sargable ». Ваш вопрос касался только SQL Server, поскольку он не может обрабатывать предикаты поиска "% wordhere%", в то время как, по-видимому, другие СУБД.
Джон aka hot2use

Ответы:

31

Термин «sargable» был впервые введен P. Griffiths Selinger et al. в своей статье 1979 года «Выбор пути доступа в системе управления реляционными базами данных», опубликованной ACM . Для тех, кто не является членом ACM, есть копия этого документа по адресу http://cs.stanford.edu/people/chrismre/cs345/rl/selinger.pdf.

Термин определен в этом параграфе:

При сканировании как по индексу, так и по сегменту 1 может необязательно приниматься набор предикатов, называемых поисковыми аргументами (или SARGS), которые применяются к кортежу перед его возвратом вызывающей стороне RSI 2 . Если кортеж удовлетворяет предикатам, он возвращается; в противном случае сканирование продолжается до тех пор, пока не будет найден кортеж, который удовлетворяет SARGS, или не исчерпан сегмент или указанный диапазон значений индекса. Это снижает стоимость за счет устранения накладных расходов на выполнение вызовов RSI для кортежей, которые могут быть эффективно отклонены в RSS. Не все предикаты имеют форму, которая может стать SARGS. Sargable предикат является одним из формы (или который может быть введен в форму) «столбец оператор сравнения значения». SARGS выражаются как логическое выражение таких предикатов в дизъюнктивной нормальной форме.

Другими словами, предикат sargable является таким, который может быть разрешен механизмом хранения (методом доступа) путем непосредственного наблюдения за таблицей или индексной записью. И наоборот, предикат без аргументов требует более высокого уровня работы СУБД. Например, результат WHERE lastname = 'Doe'может быть определен механизмом хранения, просто просматривая содержимое поля lastnameкаждой записи. С другой стороны, WHERE UPPER(lastname) = 'DOE'требует выполнения функции механизмом SQL, что означает, что механизм хранения должен будет вернуть все строки, которые он читает (при условии, что они соответствуют возможным другим, sargable предикатам), обратно в механизм SQL для оценки, что приведет к дополнительным затратам ЦП. ,

Из исходного определения видно, что sargable предикаты могут применяться не только к просмотрам индекса, но и к просмотрам таблиц (сегментов в терминологии System R), если выполняются условия «значение оператора сравнения столбцов», и поэтому они могут быть оценивается механизмом хранения. Это действительно так с Db2, потомком System R во многих отношениях :

Предикаты sargable индекса не используются для ограничения поиска, но оцениваются по индексу, если он выбран, поскольку столбцы, включенные в предикат, являются частью ключа индекса. Эти предикаты также оцениваются менеджером индекса.

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

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

Предикаты Sargable и Non-Sargable иногда описываются как предикаты «стадии 1» и «стадии 2» соответственно (это также происходит из терминологии Db2 ). Предикаты этапа 1 могут оцениваться на самом низком уровне обработки запросов при чтении записей таблицы или индекса. Строки, соответствующие условиям этапа 1, если таковые имеются, отправляются на следующий уровень, этап 2 оценки.


1 - Сегмент в System R - это физическое хранилище кортежей таблицы; сканирование сегментов в некоторой степени эквивалентно сканированию таблиц в других СУБД.

2 - Интерфейс RSI - RSS 3, интерфейс запросов, ориентированный на кортежи. Интерфейсной функцией, относящейся к этому обсуждению, является NEXT, которая возвращает предикаты запроса на соответствие следующей строки.

3 - RSS, или Research Storage System, подсистема хранения System R.

mustaccio
источник
«непосредственно наблюдая за таблицей или индексной записью», что это значит? Я имею в виду, конечно = UPPER(), вызов функции, но memcmpсам по себе. Было бы относительно легко написать a, memcmpкоторый принимает ASCII и игнорирует регистр (просто посмотрите на второй клев). Делает ли это это приемлемым? Также см. Пример @ Ypercube, dba.stackexchange.com/questions/162263/…
Эван Кэрролл,
4
@EvanCarroll Это означает просмотр таблицы или индексной записи напрямую, без обращения к функциям базы данных, реализованным вне механизма хранения (например, в обработчике запросов / механизме выполнения / службе выражений). В примере ypercube запрос предварительно обрабатывается планировщиком / оптимизатором так, что поиск без SARGable выражается в терминах SARGable.
Пол Уайт восстановил Монику
Что означает «смотреть на таблицу или индексную запись напрямую» ? Я не уверен, как это объясняет «непосредственное наблюдение за таблицей или индексной записью» . Является ли x=0SARGable? Как насчет -0 = +0, ' ' = ''или пространственное равенство? Что может быть примером чего-то, что было SARGable, наверняка? Когда вы говорите «не прибегая к функциям базы данных, реализованным вне механизма хранения», вы включаете в пример Ypercube, DATE()который включен в механизм хранения. Почему это не SARGable само по себе?
Эван Кэрролл,
2
@EvanCarroll Потратьте некоторое время, чтобы прочитать ссылочную статью, и, возможно, снова прочитайте этот ответ после этого. Если у вас все еще есть вопросы по теме, вы можете их задать. Попутно обратите внимание, что DATE()это не настоящая (SQL Server) функция, а (я предположил) сокращение г-на Куба для преобразования типов. Мы также можем обсудить это в чате, если хотите.
Пол Уайт восстановил Монику
18

Для меня SARGable означает, что SQL Server может выполнять поиск по индексу, используя ваши предикаты поиска.

Нельзя просто сказать, что СУБД может «воспользоваться» индексом, потому что с предикатом без аргументов SQL Server может в конечном итоге сканировать некластеризованный индекс.

Брент Озар
источник
Я хотел бы распространить это и на удаление разделов
Дэвид דודו Марковиц
9

По словам Pro SQL Server Internals Дмитрия Короткевича :

Предикат поиска ARGment ABLE - это предикат, в котором SQL SERVER может использовать операцию поиска по индексу, если индекс существует.

Предикат SARGable - это предикат, в котором сервер SQL может изолировать одно значение или диапазон значений ключа индекса для обработки.

SARGable предикат включает в себя следующие операторы: =, >, >=, <, <=, IN, BETWEEN, и LIKE( в случае совпадения префикса )

Номера SARGable операторы включают в себя: NOT, NOT IN, <>, и LIKE( не совпадающим префиксом ), а также использование функций или расчетов по таблице, и преобразования типов , где тип данных не соответствует индексу созданного.

Пример :

WHERE name like 'SARGable%'
WHERE name like '%non-SARGable%'

Демо :

DROP TABLE dbo.Testing;
GO

CREATE TABLE Testing (
    WeirdDatatype   int NOT NULL,
    SomethingElse   char(200)
);

CREATE NONCLUSTERED INDEX IDX_ALWAYS_SARGable
    ON dbo.Testing( SomethingElse);

CREATE NONCLUSTERED INDEX IDX_NOT_ALWAYS_SARGable
    ON dbo.Testing(SomethingElse);

INSERT INTO dbo.Testing
        ( WeirdDatatype, SomethingElse )
SELECT TOP 1000 m.message_id, CONVERT(char(200), m.text)
FROM sys.messages AS m;

Теперь мы бежим:

SELECT *
FROM dbo.Testing AS t
WHERE  t.WeirdDatatype = 1001;
SELECT *
FROM dbo.Testing AS t
WHERE t.SomethingElse LIKE 'Line%'
SELECT *
FROM dbo.Testing AS t
WHERE t.SomethingElse LIKE '%Line%'
     AND t.WeirdDatatype = 1001;

Результаты:

[1]

Давайте посмотрим на свойства запроса SARGable (поиск по индексу)

введите описание изображения здесь

Оптимизатор запросов может определить ограничение в индексе начала и конца. У него есть аргумент поиска для запроса.

Теперь запрос без SARGable:

введите описание изображения здесь

Вы можете видеть, что начало предиката «% non ..%» не позволяет оптимизатору запросов определять начало и конец или диапазон в индексе. Теперь он должен искать всю таблицу (сканирование).

Вик Работа
источник
Итак, еще раз, если позже создается индекс, который поддерживает, WHERE name like '%non-SARGable%'делает ли это условие пригодным для использования? И, если да, разве мы не говорим о конкретном недостатке реализации? То есть, разве мы не должны говорить, что «не могут быть использованы с SQL Server 2016»
Эван Кэрролл
1
Хотя в версиях SQL Server все возможно. Принимая во внимание переломный момент индекса с подстановочным знаком в начале предиката, оптимизатору запросов будет очень сложно определить диапазон значений в индексе для поиска. Таким образом, использование сканирования и предиката затем называется предикатом без SARGable.
Вик
2
Конечно, это зависит от реализации. WHERE DATE(datetime_column) = '2001-01-01'например, «sargable» (будет выполнять поиск по индексу) в более новых версиях SQL Server (я думаю, 2008+), но не в более старых.
ypercubeᵀᴹ