Compresión de campos XML Nota técnica 2008.1.017 Junio de 2009 Ronda Guglielmo Marconi, 9 Parque Tecnológico 46980 Paterna | Valencia | Spain T |+34| 96 338 99 66 ventas@preference.es www.prefsuite.com Please Recycle PrefSuite Document PrefSuite www.prefsuite.com En PrefSuite 2008.1 y 2008.2, se ha modificado la forma de guardar los XMLs descriptivos tanto en el apartado de documentos de ventas como en producción. Así mismo, también se han modificado la forma de guardar los XMLs de serialización en los documentos de ventas. Los XMLs descriptivos y de serialización de los documentos de ventas se guardan en la tabla ContenidoPAFBLOB. El usuario puede elegir la forma de guardar estos XMLs mediante una variable global que se debe introducir en la tabla VariablesGlobales. El nombre de esta variable es PrefItems.ZipXmls. Cuando esta variable existe y tiene valor igual a ‘1’, los XMLs se guardarán comprimidos en la tabla ContenidoPAFBLOB. El XML descriptivo de cada línea se almacena en el campo XMLDescriptive y el de serialización en el campo Buffer. Si la variable no existe o tiene un valor distinto, los XMLs se guardarán sin comprimir en los campos XML y XMLSerialization respectivamente. Para ver si existe esta variable, habrá que ejecutar el siguiente script en el Management Studio de SQL: SELECT * FROM VariablesGlobales WHERE Nombre='PrefItems.ZipXmls' Este indicará si existe el registro en la tabla o no. Por tanto: a) Si existe, y en el campo “Valor” aplica “0”, habrá que modificar dicho campo a “1”. Para cambiar el valor de esta variable a “1”, la instrucción a ejecutar será: UPDATE VariablesGlobales SET Valor=1 WHERE Nombre='PrefItems.ZipXmls' b) En caso de que no exista la variable en la tabla “VariablesGlobales”, habrá que insertarla y aplicarle el valor deseado. Esta acción se aplica ejecutando la siguiente sentencia SQL: INSERT INTO VariablesGlobales (Empresa, Nombre, Valor) VALUES (1,'PrefItems.ZipXmls', 1) PrefSuite es compatible con líneas guardadas en ambos formatos. Todos los accesos de lectura/escritura del kernel a estos XMLs han sido revisados para soportar ambos formatos. Por tanto, no es necesario realizar ningún proceso de conversión de datos para utilizar una forma de guardado u otra, y se puede cambiar tantas veces como se desee sin incurrir por ello en ningún coste. Los accesos que se realizan desde fuera del kernel (DLLs de usuario) deben ser modificados para ser compatibles con ambos formatos. La forma correcta de acceder al XML de una línea de un documento de ventas es usando la función SQL llamada dbo.Sales_GetItemDescriptiveXml. Para el XML de serialización es necesario usar la función dbo.Sales_GetItemSerializationXml. Ambas aceptan como parámetros el número, versión y orden de la línea de la cual se desea obtener el XML. Estas funciones leen el XML del campo adecuado y lo descomprimen si es necesario. Hay que señalar que en el caso de que deban descomprimir el XML, lo hacen en el propio servidor SQL, por lo que tienen que ser llamadas con cuidado a fin de evitar una excesiva carga de la CPU en el servidor. Los XMLs descriptivos de producción, se guardan siempre comprimidos. La variable global no les afecta. Se guardan en la tabla PrefItems.ItemDescriptiveXmls, en el campo XmlBlob. EL DBManager se encarga de realizar la compresión de los datos antiguos. Compresión de campos XML | Technical Note 2008.1.017 | 2 PrefSuite www.prefsuite.com Los accesos al XML de producción deben realizarse utilizando la función SQL dbo.Production_GetItemDescriptiveXml, que acepta como parámetros el número de lote, y el número, versión y orden del documento de ventas. Una vez activada la compresión en una base de datos, se puede usar el script que se indica a continuación para comprimir poco a poco la tabla ContenidoPAFBlob. Antes de ejecutar el script hay que configurarle las variables @startDate y @endDate con el rango de fechas de los documentos a comprimir. El proceso puede ser muy lento, así que se recomienda no usar grandes rangos de documentos porque se podría bloquear el servidor SQL. Se puede ir haciendo poco a poco. Se recomienda hacerlo fuera del horario de oficina. Imprescindible disponer de un backup completo de la base de datos antes de ejecutar el script. El hecho de comprimir los datos no va a reducir el tamaño de una base de datos en disco, pero sí que va a dejar espacio libre dentro del espacio reservado para la base de datos. Sólo tras compactar la base de datos se liberaría el espacio no utilizado. Pero es bueno que las bases de datos tengan espacio de más reservado; así que no se recomienda compactar salvo que sea necesario o que el espacio reservado sea muy superior al utilizado. El script es el siguiente: ALTER TABLE ContenidoPAFBlob DISABLE TRIGGER ALL GO SET NOCOUNT ON; -- Configure range of documents to convert DECLARE @start_date AS datetime = '2009-01-01 00:00:00' DECLARE @end_date AS datetime = '2009-03-31 00:00:00' -DECLARE DECLARE DECLARE DECLARE DECLARE DECLARE DECLARE DECLARE @number AS int @version AS int @order AS int @date AS datetime @counter AS int = 1 @total AS int @space_before AS nvarchar(max) @space_after AS nvarchar(max) DECLARE @space_used table(name nvarchar(max), rows int, reserved nvarchar(max), data nvarchar(max), index_sisze nvarchar(max), unused nvarchar(max)) INSERT INTO @space_used exec sp_spaceused ContenidoPAFBlob SELECT @space_before=data FROM @space_used DELETE FROM @space_used SELECT @total=COUNT(*) FROM ContenidoPAF CP INNER JOIN PAF P ON P.Numero = CP.Numero AND P.Version = CP.Version WHERE P.FechaSolicitud >= @start_date AND P.FechaSolicitud < @end_date PRINT CONVERT(nvarchar(max),GETDATE(),108) + N' - Start processing ' + CONVERT(nvarchar(max),@total) + N' items.' DECLARE ContenidoPAFCursor CURSOR FAST_FORWARD FOR Compresión de campos XML | Technical Note 2008.1.017 | 3 PrefSuite www.prefsuite.com SELECT CP.Numero, CP.Version, CP.Orden, P.FechaSolicitud FROM ContenidoPAF CP INNER JOIN PAF P ON P.Numero = CP.Numero AND P.Version = CP.Version WHERE P.FechaSolicitud >= @start_date AND P.FechaSolicitud < @end_date ORDER BY P.FechaSolicitud ASC OPEN ContenidoPAFCursor FETCH NEXT FROM ContenidoPAFCursor INTO @number, @version, @order, @date WHILE ( @@FETCH_STATUS = 0 AND @@ERROR = 0 ) BEGIN SET @counter = @counter+1 UPDATE CPB SET CPB.XmlDescriptive = zlib.ZipXml (CPB.xml), CPB.xml = NULL FROM ContenidoPAFBLOB CPB WHERE CPB.Xml IS NOT NULL AND CPB.Numero=@number AND CPB.Version=@version AND CPB.Orden=@order UPDATE CPB SET CPB.Buffer = zlib.ZipXml (CPB.XMLSerialization), CPB.XMLSerialization = NULL FROM ContenidoPAFBLOB CPB WHERE CPB.XMLSerialization IS NOT NULL AND CPB.Numero=@number AND CPB.Version=@version AND CPB.Orden=@order UPDATE CPB SET CPB.XMLPricesBlob = zlib.ZipXml (CPB.XmlPrices), CPB.XmlPrices = NULL FROM ContenidoPAFBLOB CPB WHERE CPB.XmlPrices IS NOT NULL AND CPB.Numero=@number AND CPB.Version=@version AND CPB.Orden=@order IF @counter % 100 = 0 BEGIN PRINT CONVERT(nvarchar(max),GETDATE(),108) + N' - Processed ' + CONVERT(nvarchar(max),@counter) + N' items until ' + CONVERT(nvarchar(max),@date, 103) END FETCH NEXT FROM ContenidoPAFCursor INTO @number, @version, @order, @date END CLOSE ContenidoPAFCursor DEALLOCATE ContenidoPAFCursor INSERT INTO @space_used exec sp_spaceused ContenidoPAFBlob SELECT @space_after=data FROM @space_used PRINT CONVERT(nvarchar(max),GETDATE(),108) + N' - Terminated processing ' + CONVERT(nvarchar(max),@counter) + N' items.' PRINT CONVERT(nvarchar(max),GETDATE(),108) + N' - Data in table was ' + @space_before + N' and now is ' + @space_after + N'.' GO ALTER TABLE ContenidoPAFBlob ENABLE TRIGGER ALL GO Compresión de campos XML | Technical Note 2008.1.017 | 4