Calcul et d'économiser de l'espace dans PostgreSQL
J'ai une table dans pg comme suit:
CREATE TABLE t (
a BIGSERIAL NOT NULL, -- 8 b
b SMALLINT, -- 2 b
c SMALLINT, -- 2 b
d REAL, -- 4 b
e REAL, -- 4 b
f REAL, -- 4 b
g INTEGER, -- 4 b
h REAL, -- 4 b
i REAL, -- 4 b
j SMALLINT, -- 2 b
k INTEGER, -- 4 b
l INTEGER, -- 4 b
m REAL, -- 4 b
CONSTRAINT a_pkey PRIMARY KEY (a)
);
Ci-dessus ajoute jusqu'à 50 octets par ligne. Mon expérience est que j'ai besoin d'un autre 40% à 50% de la charge du système, sans même que l'utilisateur créé des index à la ci-dessus. Ainsi, environ 75 octets par ligne. Je vais avoir beaucoup, beaucoup de lignes dans la table, potentiellement, la hausse de 145 milliards de lignes, de sorte que le tableau va être repousser 13-14 téraoctets. Quels trucs, le cas échéant, pourrais-je l'utiliser pour compacter ce tableau? Mes idées possibles ci-dessous ...
Convertir le real
valeurs de integer
. Si ils peuvent stockées en tant que smallint
, c'est une économie de 2 octets par champ.
Convertir les colonnes b .. m dans un tableau. Je n'ai pas besoin de faire une recherche sur ces colonnes, mais j'ai besoin d'être en mesure de retourner une valeur de la colonne à la fois. Donc, si j'ai besoin de la colonne g, je pourrais faire quelque chose comme
SELECT a, arr[5] FROM t;
Aurais-je économiser de l'espace avec l'option matrice? Y aurait-il une pénalité sur la vitesse?
D'autres idées?
- Je pense que Erwin réponse est plus approprié de réponse ici pour la accepté de répondre.
Vous devez vous connecter pour publier un commentaire.
Je ne vois rien à gagner (et quelque chose à perdre) dans le stockage de plusieurs champs numériques dans un tableau.
La la taille de chaque type numérique est clairement documenté, vous devez tout simplement utiliser la plus petite taille de type compatible avec votre choix de la gamme, la résolution; et c'est tout ce que vous pouvez faire.
Je ne pense pas (mais je ne suis pas sûr) si il y a un alignement d'octets exigence pour les colonnes le long d'une ligne, dans ce cas, une réorganisation des colonnes pourrait modifier l'espace utilisé - mais je ne le pense pas.
BTW, il y a un correctif frais généraux par ligne, sur 23 octets.
There is a fixed-size header (occupying 23 bytes on most machines), followed by an optional null bitmap, an optional object ID field
. La différence est pertinente, la valeur NULL masque de bits pour les tables avec 8 colonnes, s'inscrit dans cette réserve octet de décisions NULL stockage de libérer de ces tables.De La Colonne"Tetris"
Fait, vous pouvez faire quelque chose, mais cela demande une compréhension plus profonde. Le mot-clé est alignement rembourrage. Chaque type de données a ses propres exigences alignement.
Vous pouvez réduire l'espace perdu de rembourrage entre les colonnes en les ordonnant favorablement. La suite (extrême) exemple serait de perdre beaucoup d'espace disque physique:
Pour enregistrer 24 octets par ligne, utiliser à la place:
SQL Violon.
En règle générale, si vous mettez de 8 octets colonnes d'abord, puis de 4 octets 2 octets 1 octet colonnes dernier, vous ne pouvez pas vous tromper.
boolean
,uuid
et quelques autres types de besoin de rien d'alignement de rembourrage.text
,varchar
et autres "varlena" (de longueur variable) types nominalement besoin de "int" alignement (4 octets sur la plupart des machines). Mais en fait, il n'y a pas d'alignement de rembourrage dans le format du disque (à la différence dans la RAM). J'ai vérifié dans de nombreux tests. Finalement, j'ai trouvé l'explication dans un remarque: dans le code source:Normalement, vous pouvez économiser quelques octets par ligne au meilleur jouer de la de la colonne"tetris". Rien de tout cela est nécessaire dans la plupart des cas. Mais avec des milliards de lignes, il peut signifier un couple de gigaoctets facilement.
Vous pouvez tester la colonne réel /taille de la ligne avec la fonction
pg_column_size()
.Certains types d'occuper plus d'espace dans la mémoire RAM que sur disque (comprimé ou "paniers" format). Vous pouvez obtenir plus de résultats pour les constantes (RAM) que pour les colonnes de la table lors de l'essai de la même valeur (ou de la ligne des valeurs de vs ligne du tableau) avec
pg_column_size()
.Enfin, certains types peuvent être comprimé ou "grillé" (stockées hors de la ligne), ou les deux.
Frais généraux par tuple (ligne)
4 octets par ligne pour l'élément pointeur - ne pas être sujet à des considérations ci-dessus.
Et au moins 24 octets (23 + padding) pour le n-uplet d'en-tête. Le manuel pour la Base de données de Mise en Page:
Pour le rembourrage entre en-tête et les données de l'utilisateur, vous avez besoin de savoir
MAXALIGN
sur votre serveur en général de 8 octets sur un système d'exploitation 64 bits (soit 4 octets sur un 32-bit OS). Si vous n'êtes pas sûr, consultezpg_controldata
.Exécuter la ligne suivante dans votre Postgres binaire dir pour obtenir une réponse définitive:
Le manuel de:
De sorte que vous obtenez habituellement le stockage optimale par les données d'emballage multiple de 8 octets.
Il n'y a rien à gagner dans la exemple que vous avez posté. Il est déjà emballé hermétiquement. 2 octets de remplissage après la dernière
int2
, 4 octets à la fin. Vous pouvez consolider le rembourrage à 6 octets à la fin, ce qui ne changerait rien.Frais généraux par les données de la page
Taille de page de données est en général de 8 KO. Certains frais généraux /ballonnement à ce niveau, trop: Restes pas assez grand pour s'adapter à un autre tuple, et plus important encore morts lignes ou un pourcentage réservé aux
taux de remplissage
paramètre.Il ya un couple de d'autres facteurs de taille sur le disque à prendre en compte:
Types de tableau?
Avec un tableau type comme si vous étiez à l'évaluation, vous ajoutez 24 octets de surcharge pour le type. De Plus, les éléments du tableau occupent de l'espace comme d'habitude. Rien à y gagner.
CREATE TABLE
est important à tous. Je ne pensais pas que c'était important. Pourquoi ne pas/ne peut pas postgres ce faire tetris optimisation pour vous? Pourquoi est-ordre de la colonne considérée comme suffisamment importante pour garder que définis?VIEW
peut servir à présenter une autre colonne ordre de simple de cas (écrit sont propagées automatiquement, aussi.)CREATE TABLE WITH column_reorder_ok
qui implique "je ne se soucient pas de la logique de l'ordre des colonnes, afin de le modifier comme vous le souhaitez pour l'optimisation de la table". Ou, avec votre terminologie,WITH column_tetris_ok
. 🙂CREATE TABLE
déclaration pour un minimum de stockage ...