如何知道SQL全文索引人口何时完成?

我们正在为针对testingSQL Server数据库运行的ASP.NET应用程序编写unit testing。 也就是说,ClassInitialize方法用testing数据创build一个新的数据库,ClassCleanup删除数据库。 我们通过从代码运行.bat脚本来做到这一点。

被testing的类被赋予一个连接到unit testing数据库而不是生产数据库的连接string。

我们的问题是,数据库包含一个全文索引,为了使我们的testing按预期运行,需要完整地填充testing数据。

据我所知,全文索引总是填充在背景中。 我希望能够:

  1. 使用同步(transact-SQL?)语句或者创build完全填充的全文索引
  2. 找出全文的完成时间,是否有callback选项,或者我可以反复询问?

我目前的解决办法是强制延迟最后的类初始化方法 – 5秒似乎工作 – 因为我找不到任何文档。

您可以使用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事件探查器来监视当您打开目录的属性对话框时SQL Server Management Studio发出的命令。 该对话框包含一个人口状态标记,所有显示的信息都使用T-SQL进行查询。

我想提供一个易于阅读的@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 FROM sys.fulltext_catalogs AS cat 

结果:

 LastPopulated PopulateStatus ----------------------- ---------------------------------- 2012-05-08 14:51:37.000 Idle (1 row(s) affected) 

这是我们根据GarethOwen的答案创build的存储过程。 它接受以逗号分隔的表格列表作为参数,并等待全部文本索引全部更新。 这样做每十分之一秒检查一次,以防止颠簸磁盘,10秒后超时,以防万一运行缓慢/中断。 如果您的FTsearch跨越多个索引,那么这很有用

以下面的方式调用:

 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是一个表值函数,现在每个人都必须拥有一个表值函数,它将分隔符上的一个string分割成一个临时表:

 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 

谢谢丹尼尔,你的回答让我走上了正轨。

我实际上使用下面的T-SQL语句来询问全文索引的人口状态是否是空闲的:

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

'v_doc_desc_de'是我们索引的数据库视图的名称。

如果人口状况不是空闲的,我等几秒钟再问,直到空闲。 在检查之间等待一小段时间是很重要的,通过不断检查人口状况来确保全文人口不会减慢。

MSDN文档指出,在属性“PopulateStatus”的FULLTEXTCATALOGPROPERTY语句上推荐OBJECTPROPERTYEX函数(在表级别)。 它声明如下:

在以后的SQL Server版本中将删除以下属性:LogSize和PopulateStatus。 避免在新的开发工作中使用这些属性,并计划修改当前使用其中任何一个的应用程序。

要等待全文目录完成所有表和视图的填充而不必指定其名称,则可以使用以下存储过程。 这是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 
    Interesting Posts