Почему мое представление медленно отображается, когда я проиндексировал столбцы?
В SQL Server я поместил кластеризованный индекс в представление, чтобы устранить неэффективность объединения с помощью операторов LIKE:
CREATE VIEW KeywordCount WITH SCHEMABINDING
AS
SELECT
K.ID AS KeywordID
,COUNT_BIG(*) AS KeywordCount
FROM dbo.Grants G
INNER JOIN dbo.GrantStatuses GS2 ON GS2.ID = G.StatusID AND GS2.Status NOT IN ('Pre-Submission', 'Awaiting Signatory Approval', 'Modifying', 'Closed')
INNER JOIN dbo.Keywords K
ON G.Keywords LIKE '%' + K.Word + '%' --It's one of the grant's keywords
OR G.Title LIKE '%' + K.Word + '%' --Word appears in the title
OR Replace(G.Title, '-', ' ') LIKE '%' + Replace(K.Word, '-', ' ') + '%' --Word with hyphens replaced appears in the title
OR G.Synopsis LIKE '%' + K.Word + '%' --Word appears in the Synopsis
OR Replace(G.Synopsis, '-', ' ') LIKE '%' + Replace(K.Word, '-', ' ')+ '%' --Word with hyphens replaced appears in the synopsis
GROUP BY K.ID
GO
CREATE UNIQUE CLUSTERED INDEX IX_KeywordCount
ON dbo.KeywordCount (KeywordID)
GO
Затем я добавил еще один индекс в столбец KeywordCount:
CREATE INDEX IX_KeywordCount_Count
ON dbo.KeywordCount (KeywordCount)
GO
Так почему следующий запрос занимает 7 минут? Разве индекс не должен дать мне намного лучшую производительность?
SELECT TOP 10 * FROM KeywordCount ORDER BY KeywordCount DESC
РЕДАКТИРОВАТЬ Спасибо всем, но я знаю, что LIKE заявления и REPLACE сделает эту точку зрения неэффективной. Вот почему я добавил кластерный индекс. Я думал, что размещение кластеризованного индекса в представлении материализует данные в таблицу, чтобы база данных не выполняла объединения. План запроса действительно говорит, что он выполняет объединения. Это почему?
3 ответа
Я нашел решение в этой статье: http://technet.microsoft.com/en-us/library/cc917715.aspx
SELECT TOP 10 * FROM KeywordCount WITH (NOEXPAND) ORDER BY KeywordCount DESC
По какой-то причине план запроса не использовал индекс, но я добавил подсказку WITH (NOEXPAND), и мой запрос был выполнен мгновенно - большое спасибо Quassnoi за то, что он указал, что нужно сделать.
Обратите внимание, что WITH (NOEXPAND) означает, что представление должно смотреть только на индексы, а не на данные таблицы. Это означает, что если индексы не обновлены, представление также не будет.
LIKE '%' + Replace(K.Word, '-', ' ') + '%'
(%
подстановочные знаки в начале поисковых терминов) НИКОГДА не смогут использовать любые индексы. Если вы используете такое утверждение, не удивляйтесь, что у вас будет полное сканирование таблицы все время.
Если вы действительно нуждаетесь в таком поиске, вам нужно либо справиться со скоростью, с которой вы работаете, либо исследовать полнотекстовый поиск.
Другой вариант - изменить ваши операторы LIKE на: LIKE K.Word + '%'
Если вы используете %
Подстановочный знак только в конце, SQL Server имеет шанс на самом деле использовать индекс на K.Word
и, таким образом, ускорить поиск.