¿Cómo puedo saber si se ha terminado SQL índice de texto completo de la población?
-
02-10-2019 - |
Pregunta
Nos dirigimos pruebas unitarias para nuestra aplicación ASP.NET que se ejecutan en una base de datos de prueba de SQL Server. Es decir, el método ClassInitialize crea una nueva base de datos con datos de prueba, y la ClassCleanup elimina la base de datos. Hacemos esto mediante la ejecución de secuencias de comandos .bat de código.
Las clases bajo prueba se les da una cadena de conexión que se conecta a la base de datos de prueba de 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 ser totalmente lleno con los datos de prueba a fin de que nuestras pruebas se ejecuten como se esperaba.
Por lo que yo puedo decir, el índice de texto completo siempre se rellena en el fondo. Me gustaría ser capaz de, ya sea:
- Crea el índice de texto completo, totalmente poblada, con una sincrónica (Transact-SQL?) Declaración, o
- Para saber cuando la población de texto completo está terminado, hay una opción de devolución de llamada, o puedo pedir 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
Solución
Se puede consultar el estado usando FULLTEXTCATALOGPROPERTY (ver aquí: http: // TechNet .microsoft.com / es-es / 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
Es posible que también les gusta usar SQL para controlar lo que emite comandos SQL Server Management Studio cuando aparezca el diálogo de propiedades para el catálogo. El cuadro de diálogo incluye una indicatin de estado de la población y toda la información que se muestra es consultado usando T-SQL.
Otros consejos
Me gustaría ofrecer una versión más fácil de leer la respuesta de Renshaw @ Daniel:
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 crea basándose en la respuesta de GarethOwen. Se acepta una lista separada por comas de las tablas como parámetros y espera hasta que los índices de texto completo sobre todos ellos han sido actualizados. Lo hace esta comprobación cada décima de segundo para prevenir latigazos, el disco y el tiempo de espera después de 10 segundos por si las cosas están funcionando lentamente / roto. Es útil si tus búsquedas FT son a través de 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
Gracias Daniel, su respuesta me puso en el camino correcto.
En realidad, 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, me espera un par de segundos y volver a preguntar, hasta que esté inactivo. Es importante esperar una pequeña cantidad de tiempo entre comprobaciones para asegurar la población texto completo no se ralentiza comprobando continuamente el estado de la población.
El MSDN la documentación establece que la función OBJECTPROPERTYEX
(a nivel de tabla) se recomienda más que la declaración FULLTEXTCATALOGPROPERTY
con la propiedad 'PopulateStatus'. Se afirma lo siguiente:
Las siguientes propiedades se quitará en una versión futura de SQL Server: logsize y PopulateStatus. Evitar el uso de estas propiedades en nuevos trabajos de desarrollo y tenga previsto modificar las aplicaciones que actualmente usan cualquiera de ellos.
Para esperar un catálogo de texto completo a la población llegada 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 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