Подтвердить что ты не робот

Как узнать, когда заполняется индексный индекс SQL Full Text?

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

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

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

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

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

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

4b9b3361

Ответ 1

Вы можете запросить статус с помощью 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.

Ответ 2

Я хотел бы предложить более удобную для чтения версию ответа @Daniel Renshaw:

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

Результаты:

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

(1 row(s) affected)

Ответ 3

Это хранимая процедура, которую мы создали на основе ответа 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

Ответ 4

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

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

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

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

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

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

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

Ответ 5

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