Postmaster utilise des écritures CPU et disque excessives

9

en utilisant PostgreSQL 9.1.2

Je constate une utilisation excessive du processeur et de grandes quantités d'écritures sur le disque à partir des tâches de postmaster. Cela se produit même lorsque mon application ne fait presque rien (10s d'inserts par MINUTE). Il existe cependant un nombre raisonnable de connexions ouvertes.

J'ai essayé de déterminer ce qui, dans ma demande, est à l'origine de cela. Je suis assez nouveau avec postgresql, et je n'ai pas réussi jusqu'ici. J'ai activé certaines options de journalisation dans mon fichier de configuration et regardé les connexions dans la table pg_stat_activity, mais elles sont toutes inactives. Pourtant, chaque connexion consomme ~ 50% de CPU et écrit ~ 15M / s sur le disque (ne lisant rien).

J'utilise essentiellement le stock postgresql.conf avec très peu de réglages. J'apprécierais tout conseil ou pointage sur ce que je peux faire pour retrouver cela.

Voici un échantillon de ce que top / iotop me montre:

Cpu(s): 18.9%us, 14.4%sy,  0.0%ni, 53.4%id, 11.8%wa,  0.0%hi,  1.5%si,  0.0%st
Mem:  32865916k total,  7263720k used, 25602196k free,   575608k buffers
Swap: 16777208k total,        0k used, 16777208k free,  4464212k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                          
17057 postgres  20   0  236m  33m  13m R 45.0  0.1  73:48.78 postmaster                                                                                                                       
17188 postgres  20   0  219m  15m  11m R 42.3  0.0  61:45.57 postmaster                                                                                                                       
17963 postgres  20   0  219m  16m  11m R 42.3  0.1  27:15.01 postmaster                                                                                                                       
17084 postgres  20   0  219m  15m  11m S 41.7  0.0  63:13.64 postmaster                                                                                                                       
17964 postgres  20   0  219m  17m  12m R 41.7  0.1  27:23.28 postmaster                                                                                                                       
18688 postgres  20   0  219m  15m  11m R 41.3  0.0  63:46.81 postmaster                                                                                                                       
17088 postgres  20   0  226m  24m  12m R 41.0  0.1  64:39.63 postmaster                                                                                                                       
24767 postgres  20   0  219m  17m  12m R 41.0  0.1  24:39.24 postmaster                                                                                                                       
18660 postgres  20   0  219m  14m 9.9m S 40.7  0.0  60:51.52 postmaster                                                                                                                       
18664 postgres  20   0  218m  15m  11m S 40.7  0.0  61:39.61 postmaster                                                                                                                       
17962 postgres  20   0  222m  19m  11m S 40.3  0.1  11:48.79 postmaster                                                                                                                       
18671 postgres  20   0  219m  14m   9m S 39.4  0.0  60:53.21 postmaster                                                                                                                       
26168 postgres  20   0  219m  15m  10m S 38.4  0.0  59:04.55 postmaster  


Total DISK READ: 0.00 B/s | Total DISK WRITE: 195.97 M/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND                                                                                                                        
17962 be/4 postgres    0.00 B/s   14.83 M/s  0.00 %  0.25 % postgres: aggw aggw [local] idle
17084 be/4 postgres    0.00 B/s   15.53 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17963 be/4 postgres    0.00 B/s   15.00 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17188 be/4 postgres    0.00 B/s   14.80 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17964 be/4 postgres    0.00 B/s   15.50 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
18664 be/4 postgres    0.00 B/s   15.13 M/s  0.00 %  0.23 % postgres: aggw aggw [local] idle
17088 be/4 postgres    0.00 B/s   14.71 M/s  0.00 %  0.13 % postgres: aggw aggw [local] idle
18688 be/4 postgres    0.00 B/s   14.72 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
24767 be/4 postgres    0.00 B/s   14.93 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
18671 be/4 postgres    0.00 B/s   16.14 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
17057 be/4 postgres    0.00 B/s   13.58 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
26168 be/4 postgres    0.00 B/s   15.50 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
18660 be/4 postgres    0.00 B/s   15.85 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle

Mise à jour : une grande partie de l'écriture des fichiers semble concerner certains fichiers temporaires (?) Du répertoire $ PG_DATA / base /. Ma compréhension de la structure de fichiers ici est que chaque table est essentiellement stockée sous forme de fichier dont le nom est l'OID de la table. Cependant, il y a des tonnes de fichiers nommés tnn_nnnnnnn, et ce sont ces fichiers qui semblent être écrits (peut-être écrasés) en permanence. À quoi servent ces fichiers? Il y a environ 4700 fichiers et tous mesurent 8 Ko:

-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t12_1430975
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t16_1432736
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t28_1439066
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t24_1436243
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t24_1436210
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t19_1393372
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t28_1439051
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t8_1430334

Mise à jour : l'exécution de strace sur les processus postmaster montre essentiellement beaucoup de choses d'E / S sur les fichiers:

open("base/16388/t24_1435947_fsm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435947_vm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435947", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 8192
ftruncate(9, 0)                         = 0
lseek(9, 0, SEEK_END)                   = 0
open("base/16388/t24_1435941", O_RDWR)  = 18
lseek(18, 0, SEEK_END)                  = 0
write(9, "\0\0\0\0\0\0\0\0\1\0\0\0000\0\360\37\360\37\4 \0\0\0\0b1\5\0\2\0\0\0"..., 8192) = 8192
lseek(18, 0, SEEK_END)                  = 0
close(9)                                = 0
open("base/16388/t24_1435947", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 8192
close(18)                               = 0
close(9)                                = 0
open("base/16388/t24_1435944_fsm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435944_vm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435944", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 0
close(9)                                = 0

Mise à jour : ce problème semble donc être tout à voir avec les tables temporaires. Nous avons changé notre configuration de sorte que les tables temporaires sont des tables «normales», et toute l'activité du disque a disparu, et les performances sont de retour là où je m'y attendais. Maintenant, ce changement n'était qu'un test rapide et sale: si nous voulons vraiment changer pour utiliser des tables régulières, nous avons des problèmes avec la concurrence et le nettoyage. Les tables temporaires sont-elles vraiment si mauvaises, ou en abusons-nous?

Mise à jour : un peu plus de contexte. J'utilise un middleware de réplication basé sur des déclarations développé en interne . Il est assez mature et a été utilisé sur un certain nombre de projets depuis plusieurs années, mais en utilisant MySQL. Nous ne travaillons avec PostgreSQL que depuis un an ou deux. Nous utilisions essentiellement les tables temporaires dans le cadre du mécanisme de réplication. Chaque fois qu'une nouvelle connexion est établie, nous créons une table temporaire pour chaque table de la base de données. Avec 10-20 connexions (longue durée de vie) et ~ 50 tables, cela peut représenter un grand nombre de tables temporaires. Toutes les tables temporaires ont été créées avec:

CREATE TEMPORARY TABLE... ON COMMIT DELETE ROWS;

La sémantique des tables temporaires correspond très bien à notre schéma de réplication et simplifie une grande partie du code que nous avons dû utiliser pour MySQL, mais il semble que l'implémentation ne soit pas aussi juste. D'après les recherches que j'ai faites, je ne pense pas que les tables temporaires étaient vraiment destinées à la fonction pour laquelle nous les utilisions.

Je ne suis pas l'expert interne (pas même de près) sur ce sujet, juste un utilisateur de celui-ci, donc mon explication n'est peut-être pas exacte à 100%, mais je pense que c'est assez proche.

château de loup
la source
3
Votre compréhension est un peu dépassée, si vous regardez la documentation officielle , vous constaterez que "... pour les relations temporaires, le nom du fichier est de la forme tBBB_FFF, où BBB est l'ID de backend du backend qui a créé le fichier et FFF est le numéro de fichier. ... "
Milen A. Radev
Wow, c'est un sous-système d'E / S disque performant. Que dit Strace de ce que font réellement les travailleurs?
womble
@ MilenA.Radev, il semble donc que je puisse faire quelque chose de bizarre / excessif avec des tables temporaires. C'est intéressant. J'ai beaucoup de déclencheurs en place qui utilisent des tables temporaires. J'y regarderai de plus près.
wolfcastle
@womble, j'ai mis à jour la question avec la sortie de strace.
wolfcastle
Vous rencontrez réellement un problème de performances?
voretaq7

Réponses:

1

Votre configuration PostgreSQL est loin. C'était suspect de votre post initial,

 Cpu(s): 18.9%us, 14.4%sy,  0.0%ni, 53.4%id, 11.8%wa,  0.0%hi,  1.5%si,  0.0%st
 Mem:  32865916k total,  7263720k used, 25602196k free,   575608k buffers
 Swap: 16777208k total,        0k used, 16777208k free,  4464212k cached

Sur 32 Go sur votre serveur, environ 25 Go sont gratuits, à l'exception d'environ 575 Mo de mémoire tampon.

Depuis votre fichier postgresql.conf,

 shared_buffers = 32MB                   # min 128kB                               
 #temp_buffers = 8MB                     # min 800kB
 #max_prepared_transactions = 0          # zero disables the feature
 ...
 #work_mem = 1MB                         # min 64kB
 #maintenance_work_mem = 16MB            # min 1MB
 #max_stack_depth = 2MB   

Je suppose que c'est une base de données dédiée. Si c'est le cas, modifiez-le aux paramètres suivants et rechargez / redémarrez,

 shared_buffers = 16GB                   # min 128kB                               
 temp_buffers = 128MB                     # min 800kB
 #max_prepared_transactions = 0          # zero disables the feature
 ...
 work_mem = 8MB                         # min 64kB
 maintenance_work_mem = 64MB            # min 1MB
 max_stack_depth = 4MB   

Faites-moi savoir en quoi cela modifie vos performances et pouvez les ajuster au besoin.

En ce qui concerne les tables non enregistrées, si vos tables temporaires contiennent des données temporaires éphémères et, comme vous l'avez mentionné, sont créées lors de la session, il est préférable d'utiliser des tables non enregistrées.

Vous pouvez tronquer vos tables après la session si cela est acceptable.

Plus d'informations ici - http://michael.otacoo.com/postgresql-2/unlogged-table-performance-in-postgresql-9-1/

Je ne sais pas pourquoi vous avez besoin de tables temporaires pour la réplication. Vous ne pouvez pas utiliser la réplication de streaming PostgreSQL?

Chida
la source
0

L'utilisation de tables temporaires et de connexions de longue date (probablement le regroupement de connexions est impliqué) peut être un fardeau si votre serveur n'y est pas préparé. Un paramètre PostgreSQL avec temp_bufferslequel vous pouvez essayer de jouer est celui qui contrôle la RAM allouée aux tables temporaires. Ces tampons temporaires sont alloués par connexion et la valeur par défaut (8 Mo) est probablement trop faible pour votre site.

Vous devrez peut-être également modifier un peu le comportement de votre application cliente, selon la façon dont vous utilisez vos tables temporaires. Il y a une question similaire avec une belle réponse sur Stack Overflow .

Tonin
la source
Je vais devoir demander à mon expert interne si nous avons essayé d'ajuster la valeur temp_buffers ou non (nous avons essayé beaucoup de choses différentes). La question que vous pointez ne s'applique pas vraiment car nous n'utilisons pas les tables temporaires de cette façon. J'ai mis à jour la question avec plus de détails.
wolfcastle
Merci pour la mise à jour de la question et pour le fichier postgresql.conf, c'est ce dont nous avons besoin pour essayer d'améliorer cette situation. Je suis d'accord avec la réponse de @Chida qui correspond à ce que j'ai suggéré par rapport à temp_buffers. Pouvez-vous également nous dire quelle est la taille de la base de données que vous essayez de répliquer? Combien de tables, taille moyenne par table et taille totale de la base de données?
Tonin
0

Pourriez-vous publier votre fichier postgresql.conf? Votre postgresql semble être considérablement sous-optimisé.

Pourriez-vous également poster:

  • Si vous utilisez des tables non enregistrées pour vos tables temporaires?

  • Combien de disques et dans quelle configuration RAID?

Chida
la source
J'ai mis le fichier postgresql.conf ici . Je pense que vous ne pouvez pas créer une table à la fois temporaire ET non enregistrée. Il y a 6 disques de 1 To dans un RAID 1 + 0 (stockage total de 3 To)
Wolfcastle