Gestione di messaggi XML di grandi dimensioni

Quando un flusso di bit di input è analizzato e viene creata una struttura ad albero logica, la rappresentazione ad albero di un messaggio XML è in genere più grande e in qualche caso molto più grande, del flusso di bit corrispondente. I motivi di questa variazione sono:
  • L'aggiunta dei puntatori che collegano insieme gli oggetti
  • La conversione dei dati carattere in Unicode; questa operazione può raddoppiare la dimensione
  • L'inclusione di nomi campo che potevano essere impliciti nel flusso di bit
  • La presenza dei dati di controllo associati all'operazione del broker

La manipolazione di una struttura ad albero del messaggio di grandi dimensioni può richiedere molta memoria. Se si progetta un flusso di messaggi che gestisce messaggi di grandi dimensioni formati da strutture che si ripetono, è possibile codificare delle istruzioni ESQL utili a ridurre il carico di memoria sul broker. Tali istruzioni supportano l'accesso al messaggio sia casuale che sequenziale, ma presuppongono che non sia necessario accedere all'intero messaggio in una sola volta.

Queste istruzioni ESQL fanno in modo che il broker esegua un'analisi limitata del messaggio e conservi solo quella parte della struttura ad albero del messaggio che riflette un singolo record nella memoria alla volta. Se l'elaborazione richiede di conservare le informazioni da un record all'altro (ad esempio, per calcolare un prezzo totale da una struttura ripetuta di elementi in un ordine), è possibile dichiarare, inizializzare e conservare le variabili ESQL o salvare i valori in un'altra sezione della struttura ad albero del messaggio, ad esempio LocalEnvironment.

Questa tecnica riduce la memoria utilizzata dal broker a quella necessaria per conservare i flussi di bit di input e di output completi, più la memoria necessaria per le strutture ad albero di un solo record e consente di risparmiare memoria quando si rileva nel messaggio anche un piccolo numero di ripetizioni. Il broker utilizza l'analisi parziale e la capacità di analizzare parti specifiche della struttura ad albero del messaggio da e verso la parte corrispondente del flusso di bit.

Per utilizzare queste tecniche nel nodo Compute, applicare le seguenti tecniche generali:
  • Copiare il contenuto del messaggio di input come flusso di bit in una cartella speciale nel messaggio di output. In questo modo si crea una copia modificabile del messaggio di input che non è analizzata e che quindi utilizza una quantità di memoria minima.
  • Evitare qualsiasi esame del messaggio di input. In questo si elimina la necessità di analizzare il messaggio.
  • Utilizzare un loop e una variabile di riferimento per elaborare il messaggio un record alla volta. Per ogni record:
    • Utilizzare trasformazioni normali per creare una struttura ad albero secondaria di output corrispondente in una seconda cartella speciale.
    • Utilizzare la funzione ASBITSTREAM per creare un flusso di bit per la struttura ad albero secondaria di output memorizzata in un elemento BitStream ubicato nella posizione nell'albero che corrisponde alla posizione richiesta nel flusso di bit finale.
    • Utilizzare l'istruzione DELETE per eliminare le strutture ad albero del messaggio del record di input e di output correnti una volta completata la manipolazione.
    • Una volta completata l'elaborazione di tutti i record, scollegare le cartelle speciali in modo che non appaiano nel flusso di bit di output.
E' possibile variare queste tecniche per adattarle all'elaborazione richiesta per i messaggi. Il seguente ESQL fornisce un esempio di un'implementazione ed è una riscrittura dell'esempio di ESQL in Conversione di un messaggio XML complesso. Esso utilizza una singola istruzione SET con funzioni SELECT nidificate per trasformare un messaggio che contiene strutture nidificate e ripetute.
-- Copiare l'intestazione MQMD
  SET OutputRoot.MQMD = InputRoot.MQMD;

  -- Creare una cartella speciale nel messaggio di output per contenere la
  -- struttura ad albero di input
  -- Nota : SourceMessageTree è l'elemento root di un programma di analisi XML
  CREATE LASTCHILD OF OutputRoot.XML.Data DOMAIN 'XML' NAME 'SourceMessageTree';

  -- Copiare il messaggio di input in una cartella speciale nel messaggio di output
  -- Nota : questa è una copia da root a root che quindi non crea strutture ad albero
  SET OutputRoot.XML.Data.SourceMessageTree = InputRoot.XML;

  -- Creare una cartella speciale nel messaggio di output per contenere la struttura
  -- ad albero di output
  CREATE FIELD OutputRoot.XML.Data.TargetMessageTree;

  -- Prepararsi ad eseguire il loop degli articoli acquistati
  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;

  -- Creare un blocco in modo che sia facile interrompere l'elaborazione
  ProcessInvoice: BEGIN
    -- Se non esistono fatture nel messaggio di input, non vi sono operazioni da compiere
    IF NOT LASTMOVE(sourceCursor) THEN
      LEAVE ProcessInvoice;
    END IF;

    -- Eseguire il loop delle fatture nella struttura ad albero di origine
    InvoiceLoop : LOOP
      -- Controllare la fattura corrente e creare un'istruzione corrispondente
      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'
        );

      -- Trasformare l'istruzione corrente in un flusso di bit
      DECLARE StatementBitStream BLOB
        CAST(ASBITSTREAM(targetCursor.Statement OPTIONS FolderBitStream) AS BLOB);
                
      -- Se SELECT ha prodotto un risultato (cioè, non è stata filtrata dalla clausola
      -- WHERE), elaborare l'istruzione
      IF StatementBitStream IS NOT NULL THEN
        -- creare un campo per contenere il flusso di bit nella struttura ad albero dei risultati
        CREATE LASTCHILD OF resultCursor
          Type  XML.BitStream
          NAME  'StatementBitStream'
          VALUE StatementBitStream;

        -- Aggiungere l'ammontare dell'istruzione corrente all'importo totale
        -- Notare che il cast è necessario a causa del comportamento dell'elemento di sintassi XML
        SET grandTotal = grandTotal + CAST(targetCursor.Statement.Amount AS FLOAT);
      END IF;

      -- Eliminare l'albero dell'istruzione reale lasciando solo la versione del flusso di bit
      DELETE FIELD targetCursor.Statement;

      -- Passare alla fattura successiva, rimuovendo la fattura precedente e tutti
      -- gli elementi di testo che potrebbero essere distribuiti nelle fatture
      REPEAT
        MOVE sourceCursor NEXTSIBLING;
        DELETE PREVIOUSSIBLING OF sourceCursor;
      UNTIL (FIELDNAME(sourceCursor) = 'Invoice') OR (LASTMOVE(sourceCursor) = FALSE)
      END REPEAT;

      -- Se non ci sono altre fatture da elaborare, interrompere il loop
      IF NOT LASTMOVE(sourceCursor) THEN
        LEAVE InvoiceLoop;
      END IF;

    END LOOP InvoiceLoop;
  END ProcessInvoice;

  -- Rimuovere l'origine temporanea e le cartelle di destinazione
  DELETE FIELD OutputRoot.XML.Data.SourceMessageTree;
  DELETE FIELD OutputRoot.XML.Data.TargetMessageTree;

  -- Infine aggiungere l'importo totale
  SET resultCursor.GrandTotal = grandTotal;
Questa istruzione produce il seguente messaggio di output:
<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>
Concetti correlati
Panoramica dei flussi di messaggi
Panoramica di ESQL
Attività correlate
Progettazione di un flusso di messaggi
Definizione del contenuto del flusso di messaggi
Gestione dei file ESQL
Conversione di un messaggio XML complesso
Riferimenti correlati
Nodo Compute
Istruzione DELETE
Funzione ASBITSTREAM
Messaggio di esempio
Informazioni particolari | Marchi | Download | Libreria | Supporto | Commenti
Copyright IBM Corporation 1999, 2006 Ultimo aggiornamento: ago 17, 2006
ac16740_