Как узнать, когда заполняется индексный индекс SQL Full Text?
Мы пишем модульные тесты для нашего приложения ASP.NET, которые работают с тестовой базой данных SQL Server.
То есть метод ClassInitialize создает новую базу данных с тестовыми данными, а ClassCleanup удаляет базу данных. Мы делаем это, запустив сценарии .bat из кода.
В тестируемых классах указывается строка подключения, которая соединяется с базой данных unit test, а не с производственной базой данных.
Наша проблема заключается в том, что база данных содержит полный текстовый индекс, который должен быть полностью заполнен тестовыми данными, чтобы наши тесты выполнялись как ожидалось.
Насколько я могу судить, полнотекстовый индекс всегда заполняется в фоновом режиме. Я хотел бы иметь возможность:
- Создайте полный текстовый индекс, полностью заполненный, с помощью синхронного (transact-SQL?) оператора или
- Узнайте, когда закончена полнотекстовая популяция, есть ли опция обратного вызова или я могу задать несколько раз?
Мое текущее решение состоит в том, чтобы задержать в конце метод инициализации класса - кажется, что 5 секунд - потому что я не могу найти что-либо в документации.
Ответы
Ответ 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