PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Rappresentazione di dati sparsi in PostgreSQL

Presumo che tu stia pensando a matrici sparse dal contesto matematico:http://en.wikipedia. org/wiki/matrice_sparsa (Le tecniche di archiviazione descritte sono per l'archiviazione in memoria (operazione aritmetica veloce), non per l'archiviazione persistente (utilizzo ridotto del disco).

Poiché di solito si opera su queste matrici sul lato client piuttosto che sul lato server, SQL-ARRAY[] è la scelta migliore!

La domanda è come sfruttare la scarsità della matrice? Qui i risultati di alcune indagini.

Configurazione:

  • Postgres 8.4
  • Matrici con 400*400 elementi in doppia precisione (8 byte) --> 1.28MiB di dimensione grezza per matrice
  • 33% di elementi diversi da zero --> 427 kiB di dimensione effettiva per matrice
  • media utilizzando ~1000 diverse matrici popolate casualmente

Metodi di gara:

  • Fai affidamento sull'automatico lato server compressione di colonne con SET STORAGE MAIN o EXTENDED.
  • Memorizza solo gli elementi diversi da zero più una bitmap (bit varying(xx) ) che descrive dove posizionare gli elementi diversi da zero nella matrice. (Una doppia precisione è 64 volte maggiore di un bit. In teoria (ignorando i costi generali) questo metodo dovrebbe essere un miglioramento se <=98% sono diversi da zero;-).) La compressione lato server è attivata.
  • Sostituisci gli zeri nella matrice con NULL . (Gli RDBMS sono molto efficaci nella memorizzazione di NULL.) La compressione lato server è attivata.

(L'indicizzazione di elementi diversi da zero utilizzando un 2nd index-ARRAY[] non è molto promettente e quindi non testata.)

Risultati:

  • Compressione automatica
    • nessuno sforzo di implementazione aggiuntivo
    • nessuna riduzione del traffico di rete
    • overhead di compressione minimo
    • archiviazione persistente =39% della dimensione non elaborata
  • Bitmap
    • sforzo di implementazione accettabile
    • traffico di rete leggermente diminuito; dipendente dalla scarsità
    • archiviazione persistente =33,9% della dimensione non elaborata
  • Sostituisci gli zeri con NULL
    • alcuni sforzi di implementazione (l'API deve sapere dove e come impostare i NULL nell'ARRAY[] durante la creazione della query INSERT)
    • nessuna modifica nel traffico di rete
    • archiviazione persistente =35% della dimensione grezza

Conclusione:iniziare con il parametro di archiviazione EXTENDED/MAIN. Se hai del tempo libero, esamina i tuoi dati e usa la mia configurazione di prova con il tuo livello di sparsità. Ma l'effetto potrebbe essere inferiore a quello che ti aspetti.

Suggerisco di utilizzare sempre la serializzazione della matrice (es. Riga-ordine maggiore) più due colonne intere per le dimensioni della matrice NxM. Poiché la maggior parte delle API utilizza SQL testuale, stai risparmiando molto traffico di rete e memoria client per "ARRAY[ARRAY[..], ARRAY[..], ARRAY[..], ARRAY[..], ..]" annidato !!!

Tebas

CREATE TABLE _testschema.matrix_dense
(
  matdata double precision[]
);
ALTER TABLE _testschema.matrix_dense ALTER COLUMN matdata SET STORAGE EXTERN;


CREATE TABLE _testschema.matrix_sparse_autocompressed
(
  matdata double precision[]
);

CREATE TABLE _testschema.matrix_sparse_bitmap
(
  matdata double precision[]
  bitmap bit varying(8000000)
);

Inserisci le stesse matrici in tutte le tabelle. I dati concreti dipendono dalla determinata tabella. Non modificare i dati lato server a causa di pagine inutilizzate ma allocate. Oppure fai un VACUUM.

SELECT 
pg_total_relation_size('_testschema.matrix_dense') AS dense, 
pg_total_relation_size('_testschema.matrix_sparse_autocompressed') AS autocompressed, 
pg_total_relation_size('_testschema.matrix_sparse_bitmap') AS bitmap;