Scenario

  1. Ambiente oracle single instance
  2. Database oracle versione 12.1.0.2
  3. Cluster GRID oracle versione 19.7.0.0
  4. Sistema Operativo Oracle Linux 7.8
  5. Storage VNX 5100 con connessione in fibra
  6. Directory di lavoro: /home/oracle/perf_test
  7. Direcory logs: /home/oracle/perf_test/log
  8. Database connection: MYDB

Obiettivo

Ridurre le attese su una tabella in fase di inserimento massivo nell’ipotesi che questo venga effettuato da un numero elevato di processi paralleli generando una contention a livello di accesso alla tabella stessa e agli oggetti ad essa correlati.

Sommario test eseguiti

Numero di processi che effettuano le insert: 400

Numero di righe inserite per ogni processo: 10.000

Totale righe inserite per ogni ciclo: 4.000.000

Risultato dei test con tuning progressivo:

N° TestSecondiStruttura tabellaStruttura indici
126SempliceSemplice
225Partizionamento hashSemplice
310Partizionamento hashPartizionamento hash
48Partizionamento hashPartizionamento hash indici reverse
59Partizionamento range sottopartizioni hashPartizionamento hash indici reverse
Risultati Test

Preparazione ambiente di lavoro:

Creiamo utenza, tabella e tablespaces necessari all’esecuzione del test

Tablespaces per tabella e indici:

Utenza e grant relativi

Tabella per il test:

Sequence:

Viene creata una sequence da usare per la chiave primaria:

Script accesso DB per il test massivo (block_test.sh):

Lo script genera un processo che inserisce un numero di righe pari a NUM_ROWS.

Script Principale per il test massivo (main_block_test.sh):

Lo script lancia un certo numero di processi paralleli che si occuperanno di effettuare le insert nel database.

TEST 1:

Eseguiamo il test senza nessuna ottimizzazione:

  1. Tabella:
    1. Struttura: Semplice
    1. Partizioni: Nessuna
  2. Indici:
    1. Struttura: Semplice
    1. Partizioni: Nessuna

Risultati test:

come si vede da OEM c’è un enorme contesa di accesso alla tabella e un elevato numero di sessioni attive contempopranee (picchi di oltre 250):

Picture1-Insert-Massive-Performance-Tuning

Infatti analizzando gli eventi di attesa durante l’esecuzione osserviamo attese importanti:

TEST 2:

Un’ottima strategia per ridurre la contesa nell’accesso ai blocchi è utilizzare il partizionamento hash in modo da distribuire i dati su più file e ridurre la contesa del blocco:

  1. Tabella:
    1. Struttura: Partizionata
    1. Partizioni: Partizioni hash su tablespace differenti
  2. Indici:
    1. Struttura: Semplice
    1. Partizioni: Nessuna

ATTENZIONE!!!

Molto importante ricordarsi che il partizionamento hash richiede un numero di partizioni pari a 2n per massimizzare le prestazioni!

Creiamo quindi la tabella con partizionamento hash sul campo chiave.

Risultati test:

Purtroppo come si vede la distribuzione di carico non ha migliorato le tempistiche e questo a causa del fatto che il partizionamento non è stato applicato anche sugli indici.

TEST 3:

Effettuiamo la distribuzione su diversi tablespace anche sugli indici:

  1. Tabella:
    1. Struttura: Partizionata
    1. Partizioni: Partizioni hash su tablespace differenti
  2. Indici:
    1. Struttura: Partizionata
    1. Partizioni: Partizioni hash su tablespace differenti

Struttura tabella:

Risultati test:

come si vede da OEM c’è una notevole riduzione dela contesa di accesso ai dati e una riduzione delle sessioni attive contemporanee con un picco di 110 circa:

Picture2-Insert-Massive-Performance-Tuning

Come si osserva anche analizzando gli eventi di attesa:

TEST 4:

Effettuiamo la distribuzione su diversi tablespace anche sugli indici ma aggiungendo l’opzione reverse:

  1. Tabella:
    1. Struttura: Partizionata
    1. Partizioni: Partizioni hash su tablespace differenti
  2. Indici:
    1. Struttura: Partizionata, reverse index
    1. Partizioni: Partizioni hash su tablespace differenti

Struttura tabella:

Risultati test:

come si vede da OEM c’è una riduzione della contesa di accesso ai dati e il picco di sessioni contemporanee scende a circa 70 e tempi di attesa inferiori:

Come si osserva anche analizzando gli eventi di attesa:

TEST 5:

Effettuiamo adesso un test che ha come obiettivo la possibilità di pianificare future archiviazioni in base alla data ma continuando a sfruttare le potenzialità del partizionamento hash:

Scenario:

  1. Tabella:
    1. Struttura: Partizionata
    1. Partizioni: Partizioni per data e sottopartzioni hash su tablespace differenti
  2. Indici:
    1. Struttura: Partizionata, reverse index
    1. Partizioni: Partizioni hash su tablespace differenti

Modifiche strutturali:

Risultati test:

Come si può osservare rispetto il test precedente abbiamo un ulteriore anche se lieve miglioramento delle prestazioni e inoltre si ha il vantaggio di poter spostare le partizioni per data in base alle necessità di eventuale storicizzazione.

Così come anche analizzando i tempi di attesa si osserva il miglioramento:

Conclusioni

L’utilizzo delle sottopartizioni hash e degli indici reverse distribuiti su tablespaces differenti e quindi su file fisici differenti aiuta notevolmente a ridurre la contesa delle risorse e a velocizzare l’inserimento massivo di processi paralleli all’interno di una stessa tabella.