2017-10-10 6 views
2

Chaque jour, je supprime des centaines de milliers d'enregistrements d'une grande table, puis je fais quelques calculs (avec de nouvelles données) et remplace chacun des enregistrements que j'ai précédemment supprimés. Je pensais faire régulièrement vacuum tbl ferait l'affaire. Je sais qu'il ne restitue pas l'espace disque au serveur, mais (à cause des docs de pg) j'ai pensé que parce que j'insérais autant d'enregistrements que je supprimais, je ne perdrais pas beaucoup d'espace disque. Cependant, après avoir déplacé la table vers un autre espace de nom (pour une raison non liée) la table est passée de 117GB à 44GB! Alors ...meilleure stratégie d'économie de disque pour les "insertions de remplacement"

Y at-il une meilleure stratégie que cela pour ma table ne météorisation:

delete from tbl where ...etc... -- hundreds of thousands of rows removed 
insert into tbl (...etc...) values (...etc...) -- hundreds of thousands of rows added back (fresh calcs) 

.. repeat the above about 10 times a day ... 

vacuum tbl 

https://www.postgresql.org/docs/9.6/static/sql-vacuum.html

PostgreSQL 9.6

Ce que je fait réellement pour réduire la taille de la table est en ma réponse ici: integer out of range and remaining disk space too small to convert id to bigint and other solutions

Édition 1: Les inconvénients de vacuum full sont trop restrictives pour moi. Je traite des documents 24 heures sur 24, 7 jours sur 7, donc je ne peux pas avoir de verrous comme ça et mon espace disque disponible est assez limité à tout moment. Essayer d'aller à ce sujet d'une meilleure manière.

+0

Il n'y a rien d'absolu "le meilleur" pour quoi que ce soit. Quelque chose peut être mieux que quelque chose d'autre par certains critères particuliers. 'VACUUM FULL' pourrait vous aider à compacter les données pour le coût du CPU/IO et des verrous. – zerkms

+0

@zerkms - voir mon édition 1. merci! – mountainclimber

Répondre

2

Ce que vous cherchez est "l'équilibre de l'espace mort" comme j'aime l'appeler. Si vous avez 1M lignes et que vous voulez supprimer et remplacer 100k lignes, vous pouvez le faire de différentes manières. Supposons que vous supprimiez 100k et que vous insériez 100k tout de suite. Le db n'aura pas le temps d'aspirer ces vieilles rangées mortes, alors maintenant votre table de rangée de 1M a 100k rangs morts dedans. Au cours des prochaines 24 heures, l'aspirateur se déclenchera et les marquera mort, et la prochaine fois que vous supprimerez/insérerez, vous créerez 100 000 lignes mortes de plus, puis réutiliserez (la plupart des) 100 000 lignes mortes précédentes. Votre table de lignes 1M a maintenant de nouveau ~ 100k lignes mortes, qui seront réutilisées la prochaine fois et ainsi de suite.

Vous voulez atteindre un point où votre/inserts (suppressions ou mises à jour) et le vide créent/récupération morts à un tuples même taux.

+0

À part un aspirateur plein, passer l'aspirateur après l'effacement et avant l'insertion pourrait aider ... merci encore! – mountainclimber

+1

Oui l'aspiration manuelle peut être TRÈS efficace. Mais soyez averti que par défaut l'aspiration manuelle n'a pas de "froid". C'est à dire. il n'attend pas que le système fonctionne, il va tout simplement à plein régime avec un retard de vide de 0. Vous pouvez définir vacuum_cost_delay soit de façon permanente via la base de données ou postgresql.conf alter etc, ou pour cette session avec l'ensemble vacuum_cost_delay = 5ms etc. Il être plus lent avec un retard sur les coûts, mais ne battra pas le sous-système IO assez fort pour que d'autres processus puissent continuer à fonctionner. –

+0

Je vais faire ça! Je n'ai pas réalisé qu'il y avait plus d'un coup le faire manuellement/dans un programme. Merci encore! – mountainclimber