¿Cómo puedo saber cuándo ha terminado la población de índice de texto completo de SQL?

Estamos escribiendo pruebas unitarias para nuestra aplicación ASP.NET que se ejecuta en una base de datos SQL Server de prueba. Es decir, el método ClassInitialize crea una nueva base de datos con datos de prueba y ClassCleanup elimina la base de datos. Hacemos esto ejecutando scripts .bat desde el código.

Las clases sometidas a prueba reciben una cadena de conexión que se conecta a la base de datos de prueba de la unidad en lugar de una base de datos de producción.

Nuestro problema es que la base de datos contiene un índice de texto completo, que debe completarse completamente con los datos de prueba para que nuestras pruebas se ejecuten como se espera.

Por lo que puedo decir, el índice de texto completo siempre se rellena en segundo plano. Me gustaría poder:

  1. Crear el índice de texto completo, completo, con una statement sincrónica (Transact-SQL?), O
  2. Averigüe cuándo finalizó la población de texto completo, ¿hay alguna opción de callback o puedo preguntar repetidamente?

Mi solución actual es forzar un retraso al final del método de inicialización de clases: 5 segundos parecen funcionar, porque no puedo encontrar nada en la documentación.

Puede consultar el estado utilizando FULLTEXTCATALOGPROPERTY (consulte aquí: http://technet.microsoft.com/en-us/library/ms190370.aspx ).

Por ejemplo:

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 

También puede utilizar el Analizador de SQL para supervisar qué comandos emite SQL Server Management Studio cuando abre el cuadro de diálogo de propiedades para el catálogo. El diálogo incluye una indicación del estado de la población y toda la información que se muestra se consulta utilizando T-SQL.

Me gustaría ofrecer una versión más fácil de leer de la respuesta de @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 

Resultados:

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

Este es un procedimiento almacenado que creamos basado en la respuesta de GarethOwen. Acepta una lista de tablas separadas por comas como parámetros y espera hasta que se actualicen los índices de texto completo en todos ellos. Hace esta comprobación cada décima de segundo para evitar agitar el disco y se agota después de 10 segundos, por si acaso las cosas se ejecutan lentamente / interrumpidas. Útil si sus búsquedas FT están en múltiples índices.

Llamado de la siguiente manera:

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

La fuente:

 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 es una función de valor de tabla que todo el mundo debe tener ahora y que divide una cadena en un separador en una tabla temporal:

 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 

Gracias Daniel, tu respuesta me puso en el camino correcto.

De hecho, uso la siguiente instrucción T-SQL para preguntar si el estado de la población del índice de texto completo está inactivo:

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

‘v_doc_desc_de’ es el nombre de la vista de base de datos que indexamos.

Si el estado de la población no está inactivo, espero un par de segundos y vuelvo a preguntar, hasta que esté inactivo. Es importante esperar una pequeña cantidad de tiempo entre las comprobaciones para garantizar que no se ralentice la población de texto completo comprobando continuamente el estado de la población.

La documentación de MSDN indica que se OBJECTPROPERTYEX función OBJECTPROPERTYEX (a nivel de tabla) sobre la instrucción FULLTEXTCATALOGPROPERTY con la propiedad ‘PopulateStatus’. Declara lo siguiente:

Las siguientes propiedades se eliminarán en una versión futura de SQL Server: LogSize y PopulateStatus. Evite usar estas propiedades en el nuevo trabajo de desarrollo y planee modificar las aplicaciones que actualmente usan alguno de ellos.

Para esperar a que un catálogo de texto completo termine la población de todas sus tablas y vistas sin tener que especificar sus nombres, puede usar el siguiente procedimiento almacenado. Esta es una combinación de la respuesta de JohnB a esta pregunta y la respuesta de cezarm a una pregunta relacionada :

 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 
Intereting Posts