2013-06-03 9 views
7

Attualmente sto iniziando a lavorare su un progetto in cui dovrò scrivere codice (pl/sql) per esportare file XML di grandi dimensioni, basati su più tabelle in un database.Generazione di file xml di grandi dimensioni da oracle: best practice

I file di esportazione potrebbero diventare abbastanza grandi e potrebbero contenere fino a 700.000 clienti (con i loro indirizzi, ordini, numeri di telefono, ecc.).

Mi chiedevo se qualcuno avesse qualche consiglio sull'approccio migliore per questo. Ovviamente potrei semplicemente scrivere selezioni con perdita di XMLELEMENTS in esse, ma ciò significherebbe che l'intero file verrebbe generato in memoria.

È disponibile anche uno schema XML (XSD) a cui i file devono conformarsi. Mi chiedevo anche se ci fosse un modo per "mappare" la tabella allo schema XML.

Qualsiasi consiglio è apprezzato.

+0

più adatto per dba.stackexchange.com –

+5

@BurhanKhalid Non sono d'accordo: si tratta di un'attività di sviluppo, non di amministrazione del database. –

+0

È relativo alle migliori pratiche per selezionare - Non vedo come ciò non sia rilevante per dba.se * –

risposta

5

XML ha alcune ... carenze in questo settore. I file XML di grandi dimensioni, come si nota, possono generare RAM e annullare come se non ci fosse un domani.

Non credo onestamente che esista qualcosa chiamato "best practice", tutto dipende dal proprio database, server e query. Tuttavia, ecco cosa è appena fatto da un collega (non posso rivendicare credito) per scrivere enormi quantità (4,5 GB) di XML su disco da un numero elevato (20?) Di tabelle di grandi dimensioni (10-400 m righe) con estremamente complesso sub-query.

  • effettivamente scrivere fuori tutte quelle XMLElements

  • Se il SELECT è affatto complesso creare una tabella prima.

  • Seleziona dalla tabella, prendendo un elemento ragionevole, si spera basato sul tuo ID. Per esempio se si ha la seguente struttura avrebbe senso di dividerlo in <record>

    <someXML> 
        <record ID="1"> 
         <blah> 
          <moreBlah/> 
         </blah> 
        </record> 
        <record ID="2"> 
         <blah> 
          <moreBlah/> 
         </blah> 
        </record> 
    </someXML> 
    
  • Selezionare ogni record come un CLOB dal database. Finirai con una serie di CLOB che comporranno il tuo output XML.

  • Scrivi il tag di apertura prima poi singolarmente, o in pezzi, scrivere ogni CLOB disco

  • Assicurarsi che si scrive sul disco locale. Se non è evitabile, scrivi in ​​una condivisione di rete dove c'è un cavo grosso che punta verso di esso. Puoi sempre spostare il file in un secondo momento e questo sarà più efficiente rispetto alla scrittura in rete (o in una città/paese) in blocchi.

  • Parallelizza! Questo non è sempre possibile, ma se puoi farlo, fallo.

  • Fare attenzione alla parallelizzazione. Non vuoi scrivere XML malformato.

Sto difendendo efficacemente l'approccio di tbone, salvandolo invece in blocchi. Qualunque cosa tu faccia evita di mettere l'intera cosa in memoria.

2

Provare prima con DBMS_XMLGEN. Ci sono altri approcci così, vedere questo documento Oracle XML DB

DECLARE 
    v_ctx DBMS_XMLGEN.ctxhandle; 
    v_file UTL_FILE.file_type; 
    v_xml CLOB; 
    v_more BOOLEAN := TRUE; 
BEGIN 
    -- Create XML context. 
    v_ctx := DBMS_XMLGEN.newcontext('SELECT table_name, tablespace_name FROM user_tables WHERE rownum < 6'); 

    -- Set parameters to alter default Rowset and Row tag names and default case. 
    DBMS_XMLGEN.setrowsettag(v_ctx, 'USER_TABLES'); 
    DBMS_XMLGEN.setrowtag(v_ctx, 'TABLE'); 
    --DBMS_XMLGEN.settagcase(v_ctx, DBMS_XMLGen.LOWER_CASE); 

    -- Add an IE specfic XSL stylesheet reference so browser can transform the file. 
    --DBMS_XMLGEN.setstylesheetheader(v_ctx, 'C:\Development\XML\IEStyle.xsl', 'text/xsl'); 

    -- Create the XML document. 
    v_xml := DBMS_XMLGEN.getxml(v_ctx); 
    DBMS_XMLGEN.closecontext(v_ctx); 

    -- Output XML document to file. 
    v_file := UTL_FILE.fopen('C:\Development\XML\', 'test1.xml', 'w'); 
    WHILE v_more LOOP 
    UTL_FILE.put(v_file, SUBSTR(v_xml, 1, 32767)); 
    IF LENGTH(v_xml) > 32767 THEN 
     v_xml := SUBSTR(v_xml, 32768); 
    ELSE 
     v_more := FALSE; 
    END IF; 
    END LOOP; 
    UTL_FILE.fclose(v_file); 

    -- test insert into table 
    /* 
    insert into t_clob (clob_col) values (v_xml); 
    commit; 
    */ 
EXCEPTION 
    WHEN OTHERS THEN 
    DBMS_OUTPUT.put_line(Substr(SQLERRM,1,255)); 
    UTL_FILE.fclose(v_file); 
END; 

Nota che ho preso in prestito la maggior parte di questo eccellente dal oracle-base sito

+0

Ciao, per favore aiutatemi con http://stackoverflow.com/questions/25279365/utl-file-write-error-when-calling-utl-file-put-in-a-loop? – Jaskey

0

Un altro trucco sta scrivendo i risultati in più file XML, ovvero diciamo 10.000 righe per file come Table_01_Rows_00001_99999.xml. Quindi unire i file XML in un secondo momento, se necessario.

Problemi correlati