2010-04-28 17 views
47

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.¿Cómo puedo saber cuándo ha terminado la población de índice de texto completo de SQL?

Las clases bajo 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 ser capaz de, ya sea:

  1. crear el índice de texto completo, completamente equipada, con una declaración síncrona (? Transact-SQL), o
  2. averiguar cuándo la población de texto completo está terminado, ¿hay una opción de devolución de llamada, o puedo preguntar repetidamente?

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

Respuesta

35

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 te utilizar SQL para supervisar lo comandos de gestión de cuestiones Studio de SQL Server cuando aparezca el 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.

+1

que he encontrado una página que indica que la propiedad 'PopulateStatus' es/dejará de estar disponible en una versión futura de SQL Servidor, pero no he podido encontrar una alternativa para verificar el estado de la población. ¿Tienes alguna idea? Consulte la primera nota: http://technet.microsoft.com/en-us/library/ms190370.aspx – Oskar

+0

@Oskar De acuerdo con la lista detallada de características en desuso, http://technet.microsoft.com/en-us/library /cc646010.aspx, no hay reemplazo! Joe Stefanelli en otra pregunta publicó un comentario sugiriendo una posible alternativa: http://stackoverflow.com/questions/3680453/sql-server-2005-fts-unexpected-results pero todo esto se ve muy complicado. Tal vez habrá una nueva vista del sistema para FTE con esta información en SQL Server 2012 ... –

+0

En realidad http://technet.microsoft.com/en-us/library/ms190370.aspx establece que debemos usar OBJECTPROPERTYEX sobre la mesa en su lugar. Sería mejor para el rendimiento, dar más detalles y mantenerse apoyado. http://technet.microsoft.com/en-us/library/ms188390.aspx Existe el equivalente a las propiedades mencionadas: TableFulltextPopulateStatus, TableFulltextItemCount, TableFulltextCatalogId, TableFullTextMergeStatus, y hay más (consulte el enlace) – Cohen

7

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

De hecho, me utilizar 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 base de datos que nos índice.

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.

El MSDN documentation indica que se recomienda la función OBJECTPROPERTYEX (a nivel de tabla) sobre la declaración FULLTEXTCATALOGPROPERTY con la propiedad 'PopulateStatus'. Establece 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.

+1

Citación para Gareth MSDN Statement http://msdn.microsoft.com/en-us/library/ms190370(v=sql.90).aspx: "Por lo general, es una mejor opción para comprobar la propiedad PopulateStatus correspondiente en el nivel de tabla, TableFullTextPopulateStatus en el Función del sistema OBJECTPROPERTYEX Esta y otras propiedades nuevas de texto completo en OBJECTPROPERTYEX proporcionan información más detallada sobre las tablas de indización de texto completo " –

10

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 por ahora, 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 
+1

+100 si pudiera proporcionarla. Beats haciendo un hilo de dormir. –

+0

@Valamas, combinado con Command.BeginRead :) – Cohen

+0

@Cohen: ¿Qué quieres decir? –

54

Me gustaría ofrecer una versión más fácil de leer de @Daniel Renshaw's Swer:

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) 
+1

Excelente respuesta –

+1

Combinar esta con la respuesta de Daniel Renshaw es una gran consulta para múltiples catálogos. – kampsj

+0

Ambas consultas son excelentes, esta es excelente si no necesita conocer detalles que es lo que yo quería. La respuesta aceptada agregó más a esta. – Cody

3

que esperar para un catálogo de texto completo para terminar población de todas sus tablas y vistas sin tener que especificar sus nombres, se puede utilizar el siguiente procedimiento almacenado. Esta es una combinación de la respuesta de JohnB a esta pregunta y la respuesta por cezarm a un related question:

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 
Cuestiones relacionadas