2013-04-17 8 views
2

Я хочу использовать полнотекстовый поиск для автозаполнения, что означает, что мне нужно, чтобы он работал быстро! До двух секунд макс.Как оптимизировать полнотекстовый поиск SQL Server

Результаты поиска взяты из разных таблиц, поэтому я создал представление, которое объединяет их вместе. Функция SQL, которую я использую, является FREETEXTTABLE().

Запрос выполняется очень медленно, иногда до 40 секунд.

Для оптимизации времени выполнения запроса, я убедился, что базовая таблица имеет кластерный индекс столбца, что это целочисленный тип данных (а не GUID)

У меня есть два вопроса: Во-первых, любые дополнительные идеи о том, как чтобы ускорить полнотекстовый поиск? (не включая модернизацию аппаратного обеспечения ...) Во-вторых, каждый раз, когда я восстанавливаю полный текстовый каталог, поисковый запрос работает очень быстро (менее одной секунды), но только для первого запуска. Во второй раз, когда я запускаю запрос, требуется еще несколько секунд, и оттуда все вниз. Любая идея, почему это происходит?

+0

Можете ли вы опубликовать код для вашего вида? – Keith

+0

Разделены ли полные текстовые индексы? Возможно, это поможет: [Обслуживание SQL Server: Проспекты с индексом] (http://itsalljustelectrons.blogspot.com/2016/03/SQL-Server-Maintenance-Overlooked-Index.html) – DMason

ответ

1

Here's a good resource, чтобы проверить. Однако, если вы действительно хотите повысить производительность, вам придется подумать об обновлении вашего оборудования. (Я видел значительное увеличение производительности за счет перемещения моих данных и текстовых индексных файлов для разделения дисков с оптимизацией по чтению и перемещения журналов и tempdb для разделения дисков с оптимизированной записью - всего 4 дополнительных диска плюс еще 1 для ОС и SQL двоичные файлы сервера)

Некоторые другие не аппаратные решения, которые я рекомендую:.

  1. настроить встроенный стоп список слов, чтобы определить больше стоп-слова, тем самым уменьшая размер вашего полнотекстового индекса.
  2. Изменение структуры файла tempdb. См. here и here.
  3. Если ваше представление выполняет более одного вызова функции FREETEXTTABLE, рассмотрите возможность изменения структуры данных, чтобы только просмотр должен был сделать 1 вызов.

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

2

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

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

Так что проверка скорости запроса имеет смысл только после восстановление индексов закончено.

Следующий выбор может оказаться полезным для проверки размера (а также фрагментации) индексов.Когда размер перестает расти, завершается восстановление индексов;)

-- Compute fragmentation information for all full-text indexes on the database 
SELECT c.fulltext_catalog_id, c.name AS fulltext_catalog_name, i.change_tracking_state, 
    i.object_id, OBJECT_SCHEMA_NAME(i.object_id) + '.' + OBJECT_NAME(i.object_id) AS object_name, 
    f.num_fragments, f.fulltext_mb, f.largest_fragment_mb, 
    100.0 * (f.fulltext_mb - f.largest_fragment_mb)/NULLIF(f.fulltext_mb, 0) AS fulltext_fragmentation_in_percent 
FROM sys.fulltext_catalogs c 
JOIN sys.fulltext_indexes i 
    ON i.fulltext_catalog_id = c.fulltext_catalog_id 
JOIN (
    -- Compute fragment data for each table with a full-text index 
    SELECT table_id, 
     COUNT(*) AS num_fragments, 
     CONVERT(DECIMAL(9,2), SUM(data_size/(1024.*1024.))) AS fulltext_mb, 
     CONVERT(DECIMAL(9,2), MAX(data_size/(1024.*1024.))) AS largest_fragment_mb 
    FROM sys.fulltext_index_fragments 
    GROUP BY table_id 
) f 
    ON f.table_id = i.object_id