Индекс SQL Server - Есть ли улучшения для LIKE запросов? - PullRequest
23 голосов
/ 29 апреля 2009

У нас есть запрос, который выполняется из довольно большой таблицы, к которой, к сожалению, нужно использовать LIKE "% ABC%" для пары полей varchar, чтобы пользователь мог искать по частичным именам и т. Д. SQL Server 2005

Поможет ли добавление индекса в эти поля varchar с точки зрения производительности отдельных запросов при использовании LIKE или оно в основном игнорирует индексы и в этих случаях выполняет полное сканирование?

Есть ли другие возможные способы повышения производительности при использовании LIKE?

Ответы [ 5 ]

21 голосов
/ 29 апреля 2009

Только если вы добавляете полнотекстовый поиск в эти столбцы и используете возможности полнотекстового запроса SQL Server.

Иначе нет, индекс не поможет.

12 голосов
/ 30 апреля 2009

Потенциально можно увидеть улучшение производительности, добавив индекс (ы), это во многом зависит от особенностей:)

Сколько общего размера строки составляют ваши предикатные столбцы? Сколько строк вы ожидаете совпадать? Нужно ли возвращать все строки, которые соответствуют предикату, или только верхнюю 1 или верхнюю n строк?

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

Вот пример, где общий размер строки намного превышает размер столбца для поиска:

create table t1 (v1 varchar(100), b1 varbinary(8000))
go
--add 10k rows of filler
insert t1 values ('abc123def', cast(replicate('a', 8000) as varbinary(8000)))
go 10000
--add 1 row to find
insert t1 values ('abc456def', cast(replicate('a', 8000) as varbinary(8000)))
go

set statistics io on 
go
select * from t1 where v1 like '%456%'
--shows 10001 logical reads

--create index that only contains the column(s) to search across
create index t1i1 on t1(v1)
go
select * from t1 where v1 like '%456%'
--or can force to 
--shows 37 logical reads

Если вы посмотрите на фактический план выполнения, вы увидите, что механизм сканировал индекс и выполнил поиск закладок в соответствующей строке. Или вы можете напрямую сказать оптимизатору использовать индекс, если он не решил использовать этот план самостоятельно: выберите * из t1 с помощью (индекс (t1i1)), где v1, как «% 456%»

Если у вас есть группа столбцов для поиска только в нескольких очень избирательных, вы можете создать несколько индексов и использовать подход сокращения. Например. сначала определите набор идентификаторов (или каким бы ни был ваш PK) из вашего высокоселективного индекса, а затем выполните поиск по менее избирательным столбцам с помощью фильтра по этому небольшому набору PK.

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

Таким образом, возможные оптимизации во многом зависят от специфики определения вашей таблицы и селективности ваших данных.

НТН! -Adrian

8 голосов
/ 30 апреля 2009

Единственный другой способ (кроме использования полнотекстового индексирования), который вы могли бы повысить производительность, - это использовать "LIKE ABC%" - не добавляйте подстановочные знаки на обоих концах поискового запроса - в этом случае индекс может работать.

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

Марк

2 голосов
/ 29 апреля 2009

Как и «% ABC%», всегда выполняется полное сканирование таблицы. Обойти это невозможно.

У вас есть пара альтернативных подходов. Во-первых, полнотекстовый поиск, он действительно предназначен для такого рода проблем, поэтому я бы сначала посмотрел на него.

В качестве альтернативы в некоторых случаях может быть целесообразно денормализовать данные и предварительно обработать целевые поля в соответствующие токены, а затем добавить эти возможные условия поиска в отдельную таблицу поиска для многих. Например, если мои данные всегда состояли из поля, содержащего шаблон «AAA / BBB / CCC», и мои пользователи искали на BBB, то я бы токенизировал это при вставке / обновлении (и удалении при удалении). Это также может быть одним из тех случаев, когда использование триггеров, а не кода приложения, будет намного предпочтительным.

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

0 голосов
/ 30 апреля 2009

создать статистику по этому столбцу. sql srever 2005 оптимизировал поиск в строке, так что вы можете извлечь из этого пользу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...