Вопрос

Таблица продукта имеет 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. Давайте первым обзором предложенных решений, поскольку они также могут быть использованы в некоторых случаях:

  1. Опция (HASH JOIN) - не хорошо, так как вы можете получить ошибку «Процессор запросов не мог создать план запроса из-за подсказок, определенных в этом запросе. Повторяйте запрос, не указав какие-либо подсказки и без использования Set PershPlan».

  2. Выберите топ-1 * из (Original_select) Заказать ... - не хорошо, когда вам нужно использовать пагиновые результаты от вас оригинал_select

  3. 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, который занимал пару минут (из-за огромного количества фактических казней против фактического) спустился, чтобы занять секунду.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top