Manejo de mensajes XML grandes

Cuando se analiza una corriente de bits de entrada y se crea un árbol lógico, la representación del árbol de un mensaje XML generalmente es más grande y en algunos casos mucho más grande que la corriente de bits correspondiente. Esto es debido a lo siguiente:
  • Se han añadido punteros que enlazan con todos los objetos a la vez
  • Se han convertido datos a Unicode, lo que puede doblar el tamaño
  • Se han incluido nombres de campo que pueden estar implícitos en la corriente de bits
  • Hay daots de control asociados a la operación del intermediario

Manipular un árbol de mensajes de gran tamaño puede requerir mucho almacenamiento. Si diseña un flujo de mensajes que maneje mensajes grandes compuestos por estructuras repetitivas, puede codificar sentencias ESQL que le ayudarán a disminuir la carga de almacenamiento en el intermediario. Estas sentencias dan soporte tanto al acceso secuencial como al acceso aleatorio al mensaje, pero presuponen que no necesita acceder a todo el mensaje a la vez.

Estas sentencias ESQL pueden hacer que el intermediario realice un análisis parcial del mensaje y guarde sólo esta parte del árbol de mensajes que refleja un solo registro en el almacenamiento cada vez. Si el proceso requiere que guarde la información de un registro a otro registro (por ejemplo, para calcular el precio total de una estructura de artículos de un pedido que se repite), puede declarar, inicializar y mantener las variables ESQL o puede guardar los valores en otra parte del árbol de mensajes, por ejemplo, el árbol LocalEnvironment.

Esta técnica disminuye la memoria que utiliza el intermediario a la que se necesita para guardar las corrientes de bits de entrada y salida completas más la que se necesita simplemente para los árboles de un registro y permite ahorrar memoria cuando se encuentran un número reducido de repeticiones en el mensaje. El intermediario utiliza el análisis parcial y la posibilidad de analizar las partes especificadas del árbol de mensajes a y desde la parte correspondiente de la corriente de bits.

Para utilizar estas técnicas en el nodo Compute, aplique estas técnicas generales:
  • Copie el cuerpo del mensaje de entrada como una corriente de bits en una carpeta especial del mensaje de salida. Esto crea una copia modificable del mensaje de entrada que no se analiza y que, por lo tanto, utiliza una cantidad de memoria mínima.
  • Evite inspeccionar el mensaje de entrada. De este modo, se evita tener que analizar el mensaje.
  • Utilice un bucle una variable de referencia para avanzar por el mensaje de registro en registro. Para cada registro:
    • Utilice las transformaciones normales para crear un subárbol de salida correspondiente en una segunda carpeta especial.
    • Utilice la función ASBITSTREAM para generar una corriente de bits para el subárbol de salida que se almacena en un elemento BitStream colocado en la posición del árbol que se corresponde con la posición necesaria de la corriente de bits final.
    • Utilice la sentencia DELETE para eliminar los árboles de mensajes del registro de entrada y del registro de salida cuando haya acabado de manipularlos.
    • Cuando haya acabado de procesar todos los registros, desasocie las carpetas especiales para que no aparezcan en la corriente de bits de salida.
Puede variar estas técnicas para adaptarlas al proceso que requieren sus mensajes. El ESQL siguiente proporciona un ejemplo de una implementación y es una reescritura del ejemplo ESQL de Transformación de un mensaje XML complejo. Utiliza una sola sentencia SET con funciones SELECT anidadas para transformar un mensaje contenido en las estructuras anidadas que se repiten.
-- Copiar la cabecera MQMD
  SET OutputRoot.MQMD = InputRoot.MQMD;

  -- Crear una carpeta especial en el mensaje de salida para contener el árbol de entrada
  -- Nota : SourceMessageTree es el elemento raíz de un analizador XML
  CREATE LASTCHILD OF OutputRoot.XML.Data DOMAIN 'XML' NAME 'SourceMessageTree';

  -- Copie el mensaje de entrada en una carpeta especial del mensaje de salida
  -- Nota : Esta es una copia de raíz a raíz que, por lo tanto, no creará árboles
  SET OutputRoot.XML.Data.SourceMessageTree = InputRoot.XML;

  -- Crear una carpeta especial en el mensaje de salida para contener el árbol de salida
  CREATE FIELD OutputRoot.XML.Data.TargetMessageTree;

  -- Preparar el bucle a través de los artículos adquiridos
  DECLARE sourceCursor REFERENCE TO OutputRoot.XML.Data.SourceMessageTree.Invoice;
  DECLARE targetCursor REFERENCE TO OutputRoot.XML.Data.TargetMessageTree;
  DECLARE resultCursor REFERENCE TO OutputRoot.XML.Data;
  DECLARE grandTotal   FLOAT     0.0e0;

  -- Crear un bloque de modo que se pueda abandonar el proceso fácilmente
  ProcessInvoice: BEGIN
    -- Si no hay facturas en el mensaje de entrada, no tiene nada que hacer
    IF NOT LASTMOVE(sourceCursor) THEN
      LEAVE ProcessInvoice;
    END IF;

    -- Efectuar un bucle por las facturas del árbol de origen
    InvoiceLoop : LOOP
      -- Inspeccionar la factura actual y crear una sentencia coincidente
      SET targetCursor.Statement =
        THE (
          SELECT
            'Monthly'                                    AS (XML.Attribute)Type,
            'Full'                                       AS (0x03000000)Style[1],
            I.Customer.FirstName                         AS Customer.Name,
            I.Customer.LastName                          AS Customer.Surname,
            I.Customer.Title                             AS Customer.Title,
            (SELECT
              FIELDVALUE(II.Title)              AS Title,
              CAST(II.UnitPrice AS FLOAT) * 1.6 AS Cost,
              II.Quantity                       AS Qty
            FROM I.Purchases.Item[] AS II
            WHERE II.UnitPrice > 0.0                     ) AS Purchases.Article[],
            (SELECT
              SUM( CAST(II.UnitPrice AS FLOAT) *
                   CAST(II.Quantity  AS FLOAT) *
                   1.6                          )
            FROM I.Purchases.Item[] AS II                      ) AS Amount,
            'Dollars'                                  AS Amount.(XML.Attribute)Currency
          FROM sourceCursor AS I
          WHERE I.Customer.LastName <> 'White'
        );

      -- Convertir la sentencia actual en una corriente de bits
      DECLARE StatementBitStream BLOB
        CAST(ASBITSTREAM(targetCursor.Statement OPTIONS FolderBitStream) AS BLOB);
                
      -- Si SELECT ha generado un resultado (es decir, no se ha filtrado mediante la cláusula WHERE)
      -- procesar la sentencia
      IF StatementBitStream IS NOT NULL THEN
        -- crear un campo para guardar la corriente de bits en el árbol de resultados
        CREATE LASTCHILD OF resultCursor
          Type  XML.BitStream
          NAME  'StatementBitStream'
          VALUE StatementBitStream;

        -- Añadir la cantidad actual de la sentencia al total
        -- Tenga en cuenta que casta es necesario debido al comportamiento del elemento de sintaxis XML
        SET grandTotal = grandTotal + CAST(targetCursor.Statement.Amount AS FLOAT);
      END IF;

      -- Suprimir el árbol de sentencia real dejando sólo la versión de corriente de bits
      DELETE FIELD targetCursor.Statement;

      -- Pasar a la factura siguiente suprimiendo la factura anterior y cualquier
      -- elemento de texto que se haya intercalado con las facturas
      REPEAT
        MOVE sourceCursor NEXTSIBLING;
        DELETE PREVIOUSSIBLING OF sourceCursor;
      UNTIL (FIELDNAME(sourceCursor) = 'Invoice') OR (LASTMOVE(sourceCursor) = FALSE)
      END REPEAT;

      -- Si no hay más facturas que procesar, abandonar el bucle
      IF NOT LASTMOVE(sourceCursor) THEN
        LEAVE InvoiceLoop;
      END IF;

    END LOOP InvoiceLoop;
  END ProcessInvoice;

  -- Suprimir las carpetas de origen y destino temporales
  DELETE FIELD OutputRoot.XML.Data.SourceMessageTree;
  DELETE FIELD OutputRoot.XML.Data.TargetMessageTree;

  -- Finalmente añadir el total
  SET resultCursor.GrandTotal = grandTotal;
Esto genera el mensaje de salida siguiente:
<Data>
 <Statement Type="Monthly" Style="Full">
  <Customer>
   <Name>Andrew</Name>
   <Surname>Smith</Surname>
   <Title>Mr</Title>
  </Customer>
  <Purchases>
   <Article>
    <Title>The XML Companion </Title>
    <Cost>4.472E+1</Cost>
    <Qty>2</Qty>
   </Article>
   <Article>
    <Title>A Complete Guide to DB2 Universal Database</Title>
    <Cost>6.872E+1</Cost>
    <Qty>1</Qty>
   </Article>
   <Article>
    <Title>JAVA 2 Developers Handbook</Title>
    <Cost>9.5984E+1</Cost>
    <Qty>1</Qty>
   </Article>
  </Purchases>
  <Amount Currency="Dollars">2.54144E+2</Amount>
 </Statement>
 <GrandTotal>2.54144E+2</GrandTotal>
</Data>

Conceptos relacionados
Flujos de mensajes
ESQL

Tareas relacionadas
Diseño de un flujo de mensajes
Definición del contenido del flujo de mensajes
Gestión de archivos ESQL
Transformación de un mensaje XML complejo

Referencia relacionada
Nodo Compute
Sentencia DELETE
Función ASBITSTREAM
Mensaje de ejemplo