sql server - ¿Cómo puedo saber cuándo ha terminado la población de índice de texto completo de SQL?
sql-server unit-testing (5)
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
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:
- Crear el índice de texto completo, completo, con una declaración sincrónica (Transact-SQL?), O
- Averigüe cuándo finalizó la población de texto completo, ¿hay alguna 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 clases: 5 segundos parecen funcionar, porque no puedo encontrar nada en la documentación.
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.
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)
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
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.