Oracle
 sql >> Database >  >> RDS >> Oracle

INSERT di 10 milioni di query in 10 minuti in Oracle?

So che altri l'hanno menzionato e non vuoi sentirlo ma usa SQL * Loader o tabelle esterne. Il mio tempo di caricamento medio per tabelle approssimativamente della stessa larghezza è di 12,57 secondi per poco più di 10 m di file. Queste utilità sono state progettate in modo esplicito per caricare rapidamente i dati nel database e sono piuttosto brave in questo. Ciò potrebbe comportare alcune penalità di tempo aggiuntive a seconda del formato del file di input, ma ci sono alcune opzioni e raramente ho dovuto modificare i file prima del caricamento.

Se non sei disposto a farlo, non devi ancora aggiornare il tuo hardware; è necessario rimuovere ogni possibile ostacolo al caricamento rapido. Per enumerarli, rimuovi:

  1. L'indice
  2. Il grilletto
  3. La sequenza
  4. La partizione

Con tutto ciò stai obbligando il database a svolgere più lavoro e poiché lo stai facendo in modo transazionale, non stai utilizzando il database al massimo delle sue potenzialità.

Carica i dati in una tabella separata, ad esempio ABC_LOAD . Dopo che i dati sono stati completamente caricati, esegui un singolo istruzione INSERT in ABC.

insert into abc
select abc_seq.nextval, a.*
  from abc_load a

Quando lo fai (e anche se non lo fai) assicurati che la dimensione della cache della sequenza sia corretta; per citare:

Quando un'applicazione accede a una sequenza nella cache della sequenza, questi numeri di sequenza vengono letti rapidamente. Tuttavia, se un'applicazione accede a una sequenza che non è nella cache, la sequenza deve essere letta dal disco alla cache prima di utilizzare i numeri di sequenza.

Se le tue applicazioni utilizzano molte sequenze contemporaneamente, la cache delle sequenze potrebbe non essere abbastanza grande da contenere tutte le sequenze. In questo caso, l'accesso ai numeri di sequenza potrebbe spesso richiedere letture del disco. Per un rapido accesso a tutte le sequenze, assicurati che la cache disponga di voci sufficienti per contenere tutte le sequenze utilizzate contemporaneamente dalle tue applicazioni.

Ciò significa che se si dispone di 10 thread che scrivono contemporaneamente 500 record ciascuno utilizzando questa sequenza, è necessaria una dimensione della cache di 5.000. Il documento ALTER SEQUENCE indica come cambiarlo:

alter sequence abc_seq cache 5000

Se segui il mio suggerimento, aumenterei la dimensione della cache a circa 10,5 m.

Cerca di usare il suggerimento APPEND (vedi anche Oracle Base); questo indica a Oracle di utilizzare un inserimento del percorso diretto, che aggiunge i dati direttamente alla fine della tabella anziché cercare lo spazio per inserirli. Non sarai in grado di usarlo se la tua tabella ha indici ma potresti usarlo in ABC_LOAD

insert /*+ append */ into ABC (SSM_ID, invocation_id , calc_id, ... )
select 'c','b',NULL, 'test', 123 , 'N', 'asdf' from dual
union all select 'a','b',NULL, 'test', 123 , 'N', 'asdf' from dual
union all select 'b','b',NULL, 'test', 123 , 'N', 'asdf' from dual
union all select 'c','g',NULL, 'test', 123 , 'N', 'asdf' from dual

Se usi il suggerimento APPEND; Aggiungerei TRUNCATE ABC_LOAD dopo aver inserito in ABC altrimenti questa tabella aumenterà indefinitamente. Questo dovrebbe essere sicuro perché a quel punto avrai finito di usare la tabella.

Non menzioni quale versione o edizione o Oracle stai utilizzando. Ci sono una serie di piccoli trucchi extra che puoi usare:

  • Oracolo 12c

    Questa versione supporta le colonne di identità; potresti eliminare completamente la sequenza.

    CREATE TABLE ABC(
       seq_no         NUMBER GENERATED AS IDENTITY (increment by 5000)
    
  • Oracle 11g r2

    Se mantieni il grilletto; puoi assegnare direttamente il valore della sequenza.

    :new.seq_no := ABC_seq.nextval;
    
  • Edizione Oracle Enterprise

    Se stai utilizzando Oracle Enterprise puoi velocizzare INSERT da ABC_LOAD utilizzando il suggerimento PARALLEL:

    insert /*+ parallel */ into abc
    select abc_seq.nextval, a.*
      from abc_load a
    

    Ciò può causare i propri problemi (troppi processi paralleli ecc.), quindi prova. potrebbe aiuto per gli inserimenti batch più piccoli, ma è meno probabile che perderai tempo a calcolare quale thread dovrebbe elaborare cosa.

tl;dr

Utilizzare le utilità fornite con il database.

Se non puoi usarli, elimina tutto ciò che potrebbe rallentare l'inserimento e fallo in blocco, perché è in questo che il database è bravo.