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.