FreeText Query медленно - включает в себя верхний и заказ
-
02-10-2019 - |
Вопрос
Таблица продукта имеет 700К записи в нем. Запрос:
SELECT TOP 1 ID,
Name
FROM Product
WHERE contains(Name, '"White Dress"')
ORDER BY DateMadeNew desc
займет около 1 минуты для бега. На имя NateMadeNew и Freetext находится не кластерный индекс на имя DateMadeNew и FreeText.
Если я удаляю топ-1 или заказать, - это займет меньше, чем 1 секунду.
Вот ссылка на план выполнения.http://ssreencast.com/t/zdczmzg5n.
Похоже, FullTextMatch имеет более 400 тысяч казней. Почему это происходит? Как это может быть сделано быстрее?
Обновление 5/3/2010.
Похоже, кардинальность выходит из удара на нескольких словах Freetext поиска:
Оптимизаторы оценивают, что есть 28К записи, соответствующие «белым платье», в то время как на самом деле есть только 1.http://ssreencast.com/t/njm3zje4njat.
Если я заменил «белое платье» с «белым», предполагаемое число является «27, 951», а фактическое число «28, 487», что намного лучше.
Похоже, оптимизатор использует только первое слово в фразе, которые искали кардинальность.
Решение
Редактировать
От http://technet.microsoft.com/en-us/library/cc721269.ascx#_toc202506240.
Самое главное, что правильный тип соединения выбран для полнотекстового запроса. Оценка кардинальности на FullTextMatch STVF очень важно для правильного плана. Таким образом, первое, что нужно проверить, - это оценка кардинальности FullTextMatch. Это предполагаемое количество попаданий в индексе для полнотекстовой строки поиска. Например, в запросе на рисунке 3 это должно быть близко к количеству документов, содержащих термин «слово». В большинстве случаев это должно быть очень точным, но если оценка была на долгий путь, вы могли бы создавать плохие планы. Оценка для одиночных терминов обычно очень хорошая, но оценка нескольких терминов, таких как фразы или и запросы, более сложна, поскольку невозможно знать, что пересечение терминов в индексе будет основано на частоте терминов в индексе. Отказ Если оценка кардинальности хорошая, плохой план, вероятно, вызван моделью стоимости оптимизатора запросов. Единственный способ исправить проблему плана - использовать подсказку запроса, чтобы заставить определенный вид присоединения или оптимизации.
Так что он просто не может знать из информации, которую она хранит, могут ли 2 поисковых условиях, скорее всего, будут совершенно независимыми или общепринятыми вместе. Может быть, у вас должно быть 2 отдельных процедура по одному словам, которые вы позволили оптимизеру сделать свои вещи, и один для многоуровневых процедур, которые вы заставляете «достаточно хороший» план (Sys.dm_fts_index_keywords, может помочь, если вы не хотите Один размер подходит всем плану).
NB: Ваша единственная процедура Word, вероятно, понадобится с возможностью перекомпилирования, глядя на этот бит статьи.
В SQL Server 2008 полнотекстовый поиск у нас есть возможность изменять план, который генерируется на основе оценки сервисного качества используемого запроса. Если план запроса исправлен (как он находится в параметризованном запросе внутри сохраненной процедуры), этот шаг не проходит. Поэтому скомпилированный план всегда обслуживает этот запрос, даже если этот план не идеально подходит для заданного поиска.
Оригинальный ответ
Ваш новый план все еще выглядит довольно плохо. Похоже, оно возвращает только 1 строк из деталей полного текстового запроса, но сканирование всех 770159 строк в таблице продукта.
Как это работает?
CREATE TABLE #tempResults
(
ID int primary key,
Name varchar(200),
DateMadeNew datetime
)
INSERT INTO #tempResults
SELECT
ID, Name, DateMadeNew
FROM Product
WHERE contains(Name, '"White Dress"')
SELECT TOP 1
*
FROM #tempResults
ORDER BY DateMadeNew desc
Другие советы
Я не вижу связанный план исполнения, сетевая полиция блокирует это, так что это просто предположение ...
Если он работает быстро без TOP
и ORDER BY
, Попробуйте сделать это:
SELECT TOP 1
*
FROM (SELECT
ID, Name, DateMadeNew
FROM Product
WHERE contains(Name, '"White Dress"')
) dt
ORDER BY DateMadeNew desc
Похоже, FullTextMatch имеет более 400 тысяч казней. Почему это происходит?
Так как у вас есть индекс в сочетании с TOP 1
, Оптимизатор считает, что будет лучше пройти индекс, проверяя каждую запись для записи.
Как это может быть сделано быстрее?
Если обновление статистики не помогает, попробуйте добавить подсказку на ваш запрос:
SELECT TOP 1 *
FROM product pt
WHERE CONTAINS(name, '"test1"')
ORDER BY
datemadenew DESC
OPTION (HASH JOIN)
Это заставит двигатель использовать HASH JOIN
Алгоритм присоединиться к вашему столу и выходу запроса FullText.
FullText Query рассматривается как удаленный источник, возвращающий набор значений, индексированных KEY INDEX
предусмотрено в FULLTEXT INDEX
определение.
Обновлять:
Если ваш ORM
Использует параметризованные запросы, вы можете создать руководство плана.
- Используйте Profiler, чтобы перехватить запрос, который
ORM
отправляет договор - Генерировать правильный план в
SSMS
используя подсказки и сохранить его какXML
- Использовать
sp_create_plan_guide
сOPTION USE PLAN
Чтобы заставить оптимизатор всегда использовать этот план.
У меня была та же проблема раньше.
Производительность зависит от того, какой уникальный индекс вы выбираете для полной индексации текста. У моего стола две уникальные колонны - ID
и article_number
.
Запрос:
select top 50 id, article_number, name, ...
from ARTICLE
CONTAINS(*,'"BLACK*" AND "WHITE*"')
ORDER BY ARTICLE_NUMBER
Если полный текстовый индекс подключен к ID
Тогда это медленно в зависимости от поиска слов. Если полный текстовый индекс подключен к ARTICLE_NUMBER UNIQUE
Индекс тогда он всегда был быстр.
У меня лучше решение.
I. Давайте первым обзором предложенных решений, поскольку они также могут быть использованы в некоторых случаях:
Опция (HASH JOIN) - не хорошо, так как вы можете получить ошибку «Процессор запросов не мог создать план запроса из-за подсказок, определенных в этом запросе. Повторяйте запрос, не указав какие-либо подсказки и без использования Set PershPlan».
Выберите топ-1 * из (Original_select) Заказать ... - не хорошо, когда вам нужно использовать пагиновые результаты от вас оригинал_select
SP_CREATE_PLAN_GUIDE - не хорошо, как использовать Plan_Guide, вы должны сохранить план для определенного оператора SQL, это не будет работать для динамических операторов SQL (например, сгенерировано ORM)
II. Мое решение содержит из двух частей 1. Таблица Self Join Table, используемая для полного текстового поиска 2. Использование MS SQL HASH Join Incints MSDN присоединиться к подсказкам
Ваш SQL:
SELECT TOP 1 ID, Name FROM Product WHERE contains(Name, '"White Dress"')
ORDER BY DateMadeNew desc
Следует переписать как:
SELECT TOP 1 p.ID, p.Name FROM Product p INNER HASH JOIN Product fts ON fts.ID = p.ID
WHERE contains(fts.Name, '"White Dress"')
ORDER BY p.DateMadeNew desc
Если вы используете NHIBERNATE с / без замка Active Records, я ответил сообщение Как записать перехватчик, чтобы изменить ваш запрос, чтобы заменить внутреннее присоединение внутреннего хеша присоединиться
Пара мыслей на этом:
1) Вы обновили статистику на таблице продукта? Было бы полезно увидеть оценки и фактическое количество строк на операциях.
2) Какая версия SQL Server вы используете? У меня была подобная проблема с SQL Server 2008, который оказался не более чем не имеющим установленного пакета обновления 1. Установите SP1 и запрос FreeText, который занимал пару минут (из-за огромного количества фактических казней против фактического) спустился, чтобы занять секунду.