Vous n'êtes pas identifié(e).
Pages : 1
Bonjour,
Une question: si je crée une table :
CREATE TABLE test.table1
(
c1 double precision,
c2 bigint,
c3 double precision
)WITH ( OIDS=FALSE );
ALTER TABLE test.table1 OWNER TO postgres;
Et que j'insere 18 400 000 de lignes en mettant tout à null, ma table fait : 989MB.
Je pensais que si les valeurs étaient nulles on ne perdait pas de place...
Plus étrange, si j'enleve les colonnes c2 et c3, la taille passe à 495MB, soit la moitié, alors que j'ai retiré deux colonnes sur trois.
Enfin, j'ai tenté des calculs, si il y avait des infos dans ces colonnes au lieu de null:
18 400 000 * ( 8 bits + 8 bits + 8 bits, soit 24 bits ) = 421Mo de datas
Au lieu des 421Mo j'ai 989Mo et en plus c'est tout null...
Quelqu'un saurait m'expliquer svp?
Merci!
Olivier B.
Hors ligne
Bien sûr.
Ce que vos calculs ne prennent pas en compte: (les chiffres sont de mémoire, mais ça vous donnera un ordre de grandeur)
* La taille fixe de l'entête d'un bloc: 28 octets (tous les 8ko, c'est à peu près négligeable)
* 4 octets dans l'entête du bloc par enregistrement (le pointeur vers l'enregistrement, avec son offset dans le bloc)
* La taille fixe de l'entête d'un enregistrement: 23 octets (les informations de visibilité, de chaînage des versions, un certain nombre de flags,
Après, si vous avez des null dans un enregistrement, vous avez juste après l'entête un bitmap qui contient la liste des champs null (donc si <8 champs, un octet)
Par dessus, pour l'espace perdu, vous avez les contraintes d'alignement de chaque donnée (on peut trouver l'informationt dans tyalign dans pg_type).
Si vous voulez un peu plus fouiller:
https://www.postgresql.org/docs/9.5/sta … ayout.html
Les données prennent beaucoup plus de place dans une base de données.
Dernière modification par Marc Cousin (11/08/2016 18:12:25)
Marc.
Hors ligne
Merci pour la réponse, c'est intéressant mais complexe pour les non initiés...
En fait ma réflexion portait sur une table que j'ai contenant 18 millions d'enregistrements (4,1G de table et 3.9G d'index).
Il y a une cinquantaine de colonnes dont une trentaine de type int, text ou timestamp la plupart du temps à null (95% des lignes ont ces colonnes à null).
Si je comprends bien, je gagnerai de l'espace à créer une table annexe pointant par id la première table et sur laquelle je mettrai la trentaine de colonnes ?
Hors ligne
Bonjour,
Déjà une table avec une cinquantaine de colonnes il y a très probablement un problème de modélisation.
Cordialement.
Cordialement,
Sébastien.
Hors ligne
Déjà une table avec une cinquantaine de colonnes il y a très probablement un problème de modélisation.
Merci pour votre commentaire, mais en toute franchise je ne pense pas qu'il soit pertinent.
Il vous faudrait un minimum de connaissance de la fonction de cette table pour formuler un avis...
Je vous remercie quand même de vouloir etre utile.
-------------
Pour en revenir au problème initial:
Une chose m'étonne concernant la taille de la table :
Je crée une table avec 10 millions d'enregistrements: sa taille est T1
Je lui ajoute 10 colonnes de type bigint, sa taille reste T1, j'aurais pensé que ça gonfle pourtant.
Enfin, je fait un update de ces 10 colonnes en mettant tout à null et là la taille explose ...
Quand on ajoute des colonnes, la valeur de ces cellules créées n'est donc pas null, qu'est-ce alors?
Hors ligne
Je lui ajoute 10 colonnes de type bigint, sa taille reste T1, j'aurais pensé que ça gonfle pourtant.
Non, comme les valeurs sont NULL pour chaque nouvelle colonne ajoutée, la taille n'augmente pas. Comme le disait Marc ci-dessus, le bitmap des colonnes NULL est déjà présent.
Enfin, je fait un update de ces 10 colonnes en mettant tout à null et là la taille explose ...
Je parie que vous avez mis à jour toutes les lignes de la table, et que vous avez vu la table doubler de taille ? PostgreSQL ne modifie pas une ligne déjà présente. Il la duplique et modifie le duplicat. C'est sa façon de gérer MVCC.
Et donc ça n'a rien à voir avec le fait que vous avez ajouté des colonnes. Il aurait agi de la même façon sans les nouvelles colonnes :
postgres=# create table titi(id integer);
CREATE TABLE
postgres=# insert into titi select generate_series(1, 1000000);
INSERT 0 1000000
postgres=# select pg_size_pretty(pg_table_size('titi'));
pg_size_pretty
----------------
35 MB
(1 row)
postgres=# update titi set id=id+1;
UPDATE 1000000
postgres=# select pg_size_pretty(pg_table_size('titi'));
pg_size_pretty
----------------
69 MB
(1 row)
Guillaume.
Hors ligne
Bonjour Guillaume,
Je comprends mieux, c'est bien ce qui s'est passé.
Au final mes colonnes à null ne prennent donc qu'une place insignifiante alors si je comprends bien.
Merci pour votre aide!
Cordialement
Hors ligne
Pages : 1