PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Représenter des données fragmentées dans PostgreSQL

Je suppose que vous pensez à des matrices creuses dans un contexte mathématique :http://en.wikipedia. org/wiki/Sparse_matrix (Les techniques de stockage décrites ici sont destinées au stockage en mémoire (opération arithmétique rapide), et non au stockage persistant (faible utilisation du disque).)

Comme on opère généralement sur ces matrices côté client plutôt que côté serveur, un SQL-ARRAY[] est le meilleur choix !

La question est de savoir comment profiter de la rareté de la matrice ? Voici les résultats de certaines enquêtes.

Configuration :

  • Postgres 8.4
  • Matrices avec 400 x 400 éléments en double précision (8 octets) --> 1,28 Mio de taille brute par matrice
  • 33 % d'éléments non nuls --> 427 Kio de taille effective par matrice
  • moyenné à l'aide d'environ 1 000 matrices aléatoires différentes

Méthodes concurrentes :

  • Faites confiance au automatique compression côté serveur de colonnes avec SET STORAGE MAIN ou EXTENDED.
  • Ne stocker que les éléments non nuls plus un bitmap (bit varying(xx) ) décrivant où localiser les éléments non nuls dans la matrice. (Une double précision est 64 fois plus grande qu'un bit. En théorie (en ignorant les frais généraux), cette méthode devrait être une amélioration si <=98 % sont différents de zéro ;-).) La compression côté serveur est activée.
  • Remplacer les zéros dans la matrice avec NULL . (Les SGBDR sont très efficaces pour stocker les valeurs NULL.) La compression côté serveur est activée.

(L'indexation d'éléments non nuls à l'aide d'un 2nd index-ARRAY[] n'est pas très prometteuse et n'a donc pas été testée.)

Résultats :

  • Compression automatique
    • aucun effort de mise en œuvre supplémentaire
    • pas de réduction du trafic réseau
    • charge de compression minimale
    • stockage persistant =39 % de la taille brute
  • Bitmap
    • effort de mise en œuvre acceptable
    • le trafic réseau a légèrement diminué ; dépend de la rareté
    • stockage persistant =33,9 % de la taille brute
  • Remplacer les zéros par des NULL
    • un certain effort de mise en œuvre (l'API doit savoir où et comment définir les valeurs NULL dans ARRAY[] lors de la construction de la requête INSERT)
    • aucun changement dans le trafic réseau
    • stockage persistant =35 % de la taille brute

Conclusion :Commencez par le paramètre de stockage EXTENDED/MAIN. Si vous avez du temps libre, étudiez vos données et utilisez ma configuration de test avec votre niveau de parcimonie. Mais l'effet peut être plus faible que prévu.

Je suggère de toujours utiliser la sérialisation de la matrice (par exemple, l'ordre Row-major) plus deux colonnes entières pour les dimensions de la matrice NxM. Étant donné que la plupart des API utilisent du SQL textuel, vous économisez beaucoup de trafic réseau et de mémoire client pour les "ARRAY[ARRAY[..], ARRAY[..], ARRAY[..], ARRAY[..], ..]" imbriqués. !!!

Thébas

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)
);

Insérez les mêmes matrices dans tous les tableaux. Les données concrètes dépendent de certaines tables. Ne modifiez pas les données côté serveur en raison de pages inutilisées mais allouées. Ou faites un VIDE.

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;