Je travaille sur un projet qui analyse les données des fichiers de mesure dans une base de données Posgres 9.3.5.
Au cœur se trouve une table (partitionnée par mois) qui contient une ligne pour chaque point de mesure:
CREATE TABLE "tblReadings2013-10-01"
(
-- Inherited from table "tblReadings_master": "sessionID" integer NOT NULL,
-- Inherited from table "tblReadings_master": "fieldSerialID" integer NOT NULL,
-- Inherited from table "tblReadings_master": "timeStamp" timestamp without time zone NOT NULL,
-- Inherited from table "tblReadings_master": value double precision NOT NULL,
CONSTRAINT "tblReadings2013-10-01_readingPK" PRIMARY KEY ("sessionID", "fieldSerialID", "timeStamp"),
CONSTRAINT "tblReadings2013-10-01_fieldSerialFK" FOREIGN KEY ("fieldSerialID")
REFERENCES "tblFields" ("fieldSerial") MATCH SIMPLE
ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT "tblReadings2013-10-01_sessionFK" FOREIGN KEY ("sessionID")
REFERENCES "tblSessions" ("sessionID") MATCH SIMPLE
ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT "tblReadings2013-10-01_timeStamp_check" CHECK ("timeStamp" >= '2013-10-01 00:00:00'::timestamp without time zone AND "timeStamp" < '2013-11-01 00:00:00'::timestamp without time zone)
)
Nous sommes en train de remplir le tableau avec des données qui ont déjà été collectées. Chaque fichier représente une transaction d'environ 48 000 points et il y a plusieurs milliers de fichiers. Ils sont importés à l'aide d'une INSERT INTO "tblReadings_master" VALUES (?,?,?,?);
Initialement, les fichiers importent à un taux de 1000+ insertions/sec mais après un certain temps (un montant incohérent mais jamais plus de 30 minutes environ) ce taux chute à 10-40 insertions/sec et le processus Postgres Rails un CPU. La seule façon de récupérer les taux d'origine est d'effectuer un vide complet et d'analyser. Cela va finalement stocker environ 1 000 000 000 de lignes par table mensuelle, donc le vide prend un certain temps.
EDIT: Voici un exemple où il a fonctionné pendant un certain temps sur des fichiers plus petits, puis après le démarrage de fichiers plus gros, il a échoué. Les fichiers plus volumineux semblent plus erratiques, mais je pense que c'est parce que la transaction n'est validée qu'à la fin d'un fichier, environ 40 secondes.
Il y aura un frontal Web sélectionnant certains éléments mais aucune mise à jour ou suppression et cela se voit sans aucune autre connexion active.
Mes questions sont:
Il y a quelques choses qui pourraient être à l'origine de ce problème, mais je ne peux pas être sûr que l'une d'entre elles soit le vrai problème. Le dépannage consiste à activer la journalisation supplémentaire dans la base de données, puis à voir si les parties lentes correspondent aux messages qui s'y trouvent. Assurez-vous de mettre un horodatage dans le paramètre log_line_prefix pour avoir des journaux utiles à consulter. Voir mon introduction au réglage pour commencer ici: https://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server
Postgres effectue toutes ses écritures dans le cache du système d'exploitation, puis se dirige vers le disque. Vous pouvez regarder cela en activant log_checkpoints et en lisant les messages. Lorsque les choses ralentissent, il se peut simplement que tous les caches soient maintenant pleins et que toutes les écritures soient bloquées en attendant la partie la plus lente des E/S. Vous pouvez améliorer cela en modifiant les paramètres du point de contrôle Postgres.
Il y a un problème interne avec la base de données que les gens rencontrent parfois, où des insertions lourdes se bloquent en attendant un verrou dans la base de données. Activez log_lock_waits pour voir si vous atteignez celui-ci.
Parfois, la vitesse à laquelle vous pouvez effectuer des insertions en rafale est supérieure à celle que vous pouvez maintenir une fois que le processus de vide automatique du système entre en jeu. Activez log_autovacuum pour voir si les problèmes sont simultanés avec le moment où ils se produisent.
Nous savons qu'une grande quantité de mémoire dans le cache privé shared_buffers de la base de données ne fonctionne pas aussi bien sur Windows que sur d'autres systèmes d'exploitation. Il n'y a pas autant de visibilité sur ce qui ne va pas quand cela se produit. Je n'essaierais pas d'héberger quelque chose qui fait plus de 1000 insertions par seconde dans une base de données Windows PostgreSQL. Ce n'est tout simplement pas une bonne plate-forme pour des écritures vraiment lourdes.
Je ne suis pas un expert Postgres donc cela pourrait être faux! Votre clé primaire a 3 colonnes, sessionID comme premier champ. Le fichier contient-il une répartition décente des horodatages? vous pourriez envisager de créer ce premier champ dans la clé primaire ou d'utiliser une clé de substitution, car actuellement c'est assez large.
D'après votre script, je ne pense pas que vous ayez un cluster. Différent de SQL Server mais je pense que vous devez spécifier avec l'ordre physique de la table dans Postgres avec la commande 'Cluster'. Le lien en parle:
https://stackoverflow.com/questions/4796548/about-clustered-index-in-postgres