Как узнать, когда заполнение полнотекстового индекса SQL завершено? - PullRequest
53 голосов
/ 28 апреля 2010

Мы пишем модульные тесты для нашего приложения ASP.NET, которые работают с тестовой базой данных SQL Server. То есть метод ClassInitialize создает новую базу данных с тестовыми данными, а ClassCleanup удаляет базу данных. Мы делаем это, запуская скрипты .bat из кода.

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

Наша проблема в том, что база данных содержит полнотекстовый индекс, который должен быть полностью заполнен тестовыми данными, чтобы наши тесты работали, как ожидалось.

Насколько я могу судить, полнотекстовый индекс всегда заполняется в фоновом режиме. Я хотел бы иметь возможность:

  1. Создать полнотекстовый индекс, полностью заполненный, с помощью синхронного (transact-SQL?) Оператора, или
  2. Узнайте, когда заполнение полнотекста закончено, есть ли опция обратного вызова, или я могу спросить несколько раз?

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

Ответы [ 5 ]

60 голосов
/ 08 мая 2012

Я хотел бы предложить более удобную для чтения версию ответа Даниэля Реншоу:

DECLARE @CatalogName VARCHAR(MAX)
SET     @CatalogName = 'FTS_Demo_Catalog'

SELECT
    DATEADD(ss, FULLTEXTCATALOGPROPERTY(@CatalogName,'PopulateCompletionAge'), '1/1/1990') AS LastPopulated
    ,(SELECT CASE FULLTEXTCATALOGPROPERTY(@CatalogName,'PopulateStatus')
        WHEN 0 THEN 'Idle'
        WHEN 1 THEN 'Full Population In Progress'
        WHEN 2 THEN 'Paused'
        WHEN 3 THEN 'Throttled'
        WHEN 4 THEN 'Recovering'
        WHEN 5 THEN 'Shutdown'
        WHEN 6 THEN 'Incremental Population In Progress'
        WHEN 7 THEN 'Building Index'
        WHEN 8 THEN 'Disk Full.  Paused'
        WHEN 9 THEN 'Change Tracking' END) AS PopulateStatus
FROM sys.fulltext_catalogs AS cat

Результаты:

LastPopulated           PopulateStatus
----------------------- ----------------------------------
2012-05-08 14:51:37.000 Idle

(1 row(s) affected)
42 голосов
/ 28 апреля 2010

Вы можете запросить статус, используя FULLTEXTCATALOGPROPERTY (см. Здесь: http://technet.microsoft.com/en-us/library/ms190370.aspx).

Например:

SELECT
    FULLTEXTCATALOGPROPERTY(cat.name,'ItemCount') AS [ItemCount],
    FULLTEXTCATALOGPROPERTY(cat.name,'MergeStatus') AS [MergeStatus],
    FULLTEXTCATALOGPROPERTY(cat.name,'PopulateCompletionAge') AS [PopulateCompletionAge],
    FULLTEXTCATALOGPROPERTY(cat.name,'PopulateStatus') AS [PopulateStatus],
    FULLTEXTCATALOGPROPERTY(cat.name,'ImportStatus') AS [ImportStatus]
FROM sys.fulltext_catalogs AS cat

Возможно, вы также захотите использовать SQL Profiler для отслеживания того, какие команды выдает SQL Server Management Studio при открытии диалогового окна свойств для каталога. В диалоговом окне указывается состояние населения, и вся отображаемая информация запрашивается с помощью T-SQL.

10 голосов
/ 31 октября 2011

Это хранимая процедура, которую мы создали на основе ответа GarethOwen. Он принимает список таблиц через запятую в качестве параметров и ожидает обновления полнотекстовых индексов для всех из них. Он выполняет эту проверку каждую десятую секунды, чтобы предотвратить перегрузку диска и время ожидания через 10 секунд на случай, если что-то работает медленно / не работает. Полезно, если ваши поиски по FT имеют несколько индексов.

Вызывается следующим образом:

EXECUTE [dbo].[WaitForFullTextIndexing] 'MY_TABLE,ALTERNATE_NAMES,TAG_GROUP_VALUES,TAG_GROUPS,FIELD_OPTION';

Источник:

CREATE PROCEDURE WaitForFullTextIndexing
    @TablesStr varchar(max)
AS
BEGIN
    DECLARE @Tables AS TABLE( [word] [varchar](8000) NULL)

    INSERT INTO @Tables (word) SELECT items from dbo.Split(@TablesStr, ',');

    DECLARE @NumberOfTables int;
    SELECT @NumberOfTables = COUNT(*) from @Tables;

    DECLARE @readyCount int;
    SET @readyCount = 0;

    DECLARE @waitLoops int;
    SET @waitLoops = 0;

    DECLARE @result bit;

    WHILE @readyCount <> @NumberOfTables AND @waitLoops < 100
    BEGIN

        select @readyCount = COUNT(*)
        from @Tables tabs
        where OBJECTPROPERTY(object_id(tabs.word), 'TableFulltextPopulateStatus') = 0;

        IF @readyCount <> @NumberOfTables
        BEGIN
            -- prevent thrashing
            WAITFOR DELAY '00:00:00.1';
        END

        set @waitLoops = @waitLoops + 1;

    END

END
GO

dbo.split - функция табличных значений, которая должна быть у всех к настоящему времени, которая разбивает строку на разделителе во временную таблицу:

CREATE FUNCTION [dbo].[Split](@String varchar(8000), @Delimiter char(1))        
returns @temptable TABLE (items varchar(8000))        
as        
begin        
    declare @idx int        
    declare @slice varchar(8000)        

    select @idx = 1        
        if len(@String)<1 or @String is null  return        

    while @idx!= 0        
    begin        
        set @idx = charindex(@Delimiter,@String)        
        if @idx!=0        
            set @slice = left(@String,@idx - 1)        
        else        
            set @slice = @String        

        if(len(@slice)>0)   
            insert into @temptable(Items) values(@slice)        

        set @String = right(@String,len(@String) - @idx)        
        if len(@String) = 0 break        
    end    
return        
end 

GO
8 голосов
/ 28 апреля 2010

Спасибо, Даниэль, благодаря твоему ответу я оказался на правильном пути.

Я фактически использую следующую инструкцию T-SQL, чтобы спросить, является ли заполненный статус полнотекстового индекса незанятым:

SELECT OBJECTPROPERTY(object_id('v_doc_desc_de'), 'TableFulltextPopulateStatus')

'v_doc_desc_de' - это имя представления базы данных, которое мы индексируем.

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

Документация MSDN гласит, что функция OBJECTPROPERTYEX (на уровне таблицы) рекомендуется вместо оператора FULLTEXTCATALOGPROPERTY со свойством PopulateStatus. В нем говорится следующее:

Следующие свойства будут удалены в следующем выпуске SQL Server: LogSize и PopulateStatus. Избегайте использования этих свойств в новых разработках и планируйте модифицировать приложения, которые в настоящее время используют любое из них.

4 голосов
/ 26 февраля 2016

Чтобы дождаться, пока полнотекстовый каталог завершит заполнение всех его таблиц и представлений без указания их имен, вы можете использовать следующую хранимую процедуру. Это сочетание ответа JohnB на этот вопрос и ответа cezarm на связанный вопрос :

CREATE PROCEDURE WaitForFullTextIndexing
@CatalogName VARCHAR(MAX)
AS
BEGIN
    DECLARE @status int;
    SET @status = 1;
    DECLARE @waitLoops int;
    SET @waitLoops = 0;

    WHILE @status > 0 AND @waitLoops < 100
    BEGIN       
        SELECT @status = FULLTEXTCATALOGPROPERTY(@CatalogName,'PopulateStatus')
        FROM sys.fulltext_catalogs AS cat;

        IF @status > 0
        BEGIN
            -- prevent thrashing
            WAITFOR DELAY '00:00:00.1';
        END
        SET @waitLoops = @waitLoops + 1;
    END
END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...