2010-06-23 5 views
8

J'ai une assez grande table (enregistrements 20M) qui a un index de 3 colonnes et une colonne de tableau. La colonne de tableau est mise à jour quotidiennement (en ajoutant de nouvelles valeurs) pour toutes les lignes. Il y a aussi des inserts, mais pas autant que des mises à jour.PostgreSQL lente sur une grande table avec des tableaux et beaucoup de mises à jour

Les données du tableau représente des mesures quotidiennes correspondant aux trois touches, quelque chose comme ceci: [[date_id_1, my_value_for_date_1], [date_id_2, my_value_for_date_2]]. Il est utilisé pour dessiner un graphique de ces valeurs quotidiennes. Dire que je veux visualiser la valeur de la clé (a, b, c) au fil du temps, je fais SELECT values FROM t WHERE a = my_a AND b = my_b AND c = my_c. Ensuite, j'utilise le tableau values pour dessiner le graphique.

Performance des mises à jour (qui se produisent dans un volume une fois par jour) a considérablement empiré au fil du temps.

Utilisation de PostgreSQL 8.3.8.

Pouvez-vous me donner des conseils de l'endroit où chercher une solution? Il peut s'agir de modifier certains paramètres dans postgres ou même de passer à une autre base de données (je suppose qu'une base de données non relationnelle serait mieux adaptée à cette table particulière, mais je n'en ai pas beaucoup d'expérience).

+1

http://archives.postgresql.org/pgsql-performance/ –

+1

@Milen Merci pour l'indice. Je suis un grand fan de StackOverflow et je le préfère à des listes de diffusion spécialisées ou à des forums.Bien que je suis d'accord que ceux-ci ont encore leur place, et je voudrais certainement y aller si je ne pouvais pas trouver de l'aide sur SO. – ibz

+0

Voir aussi https://stackoverflow.com/questions/3361291/slow-simple-update-query-on-postgresql-database-with-3-million-rows – rogerdpack

Répondre

16

Je voudrais jeter un oeil à la FILLFACTOR pour la table. Par défaut, il est réglé à 100, vous pouvez l'abaisser à 70 (pour commencer). Après cela, vous devez faire un VACUUM FULL pour reconstruire la table.

ALTER TABLE tablename SET (FILLFACTOR = 70); 
VACUUM FULL tablename; 
REINDEX TABLE tablename; 

Cela donne ACTUALISATION une chance de placer la copie mise à jour d'une ligne sur la même page que l'original, qui est plus efficace que de le placer sur une autre page. Ou si votre base de données est déjà quelque peu fragmentée par rapport à de nombreuses mises à jour précédentes, elle pourrait déjà être suffisamment éparse. Maintenant, votre base de données a également l'option de faire HOT updates, en supposant que la colonne que vous mettez à jour n'est pas un impliqué dans un index.

+0

Comme je le vois, HOT est un moyen d'éviter la mise à jour de l'index lors d'une mise à jour. Droite? Si oui, pourquoi ma performance diminuerait * au fil du temps *? Mes index étaient mis à jour de la même manière qu'il y a 4 mois, mais ma performance a considérablement diminué depuis. – ibz

+3

Une diminution des performances peut se produire car les nouvelles versions d'un enregistrement (à cause de la mise à jour) seront placées sur une page différente. Lorsque vous avez beaucoup de documents, vous aurez aussi beaucoup de pages. Mettre une nouvelle version loin de la version originale aura un impact sur les plans de requête. Utilisez EXPLAIN pour voir ce qui se passe. Considérez également CLUSTER pour stocker vos enregistrements dans le même ordre que les index stockent leurs informations. Vous devez jouer avec le facteur de remplissage, les enregistrements mis à jour doivent rester proches des originaux. –

+0

Je vois. Donc, chaque fois que je fais une requête, elle doit aussi passer par les rangées mortes avant d'arriver à celle que je veux? C'est ce que vous voulez dire (simplifié à l'extrême)? Cela signifie que le fillfactor devrait en effet aider. Les mises à jour HOT sont-elles liées au fillfactor? Comment activer les mises à jour HOT une fois que je changefactor? – ibz

2

Vous ne savez pas si les tableaux sont la solution. Pourquoi ne pas les stocker dans une table séparée (une valeur plus les clés par ligne) alors la mise à jour en vrac sera une activité d'insertion pure.

1

Eh bien, un index à 3 colonnes n'a rien à craindre. Cela ne le rend pas nécessairement beaucoup plus lent. Mais cette colonne de tableau pourrait bien être le problème. Vous dites que vous ajoutez des valeurs à cette colonne-tableau quotidiennement. En ajoutant, voulez-vous dire ajouter des valeurs à tous les 20 mln. enregistrements dans le tableau? Ou juste quelques records?

La situation est pas tout à fait clair pour moi, mais je suggérerais à examiner les moyens de se débarrasser de cette colonne de tableau. Ce qui en fait une table séparée par exemple. Mais, cela dépend de votre situation et pourrait ne pas être une option. C'est peut-être juste moi, mais je me sens toujours "sale" ayant une telle colonne dans une de mes tables. Et la plupart du temps il y a une meilleure solution pour le problème que vous essayez de résoudre avec cette colonne de tableau. Cela étant dit, il y a certainement des situations dans lesquelles une telle colonne est valide, mais pour l'instant, je ne peux penser à aucune. Certainement pas dans une table avec un 20 mln. nombre d'enregistrements.

+2

J'ajoute des éléments à certains des tableaux, pas tous 20 mln. J'avais l'habitude d'avoir une table différente, mais cela le rend énorme et la performance est bien pire. Décidé de dénormaliser et stocker des données dans ces tableaux, ce qui a fait une énorme amélioration pour les sélections et n'a pas empiré les mises à jour au début (mais semble qu'ils s'aggravent au fil du temps). – ibz

+0

Pourriez-vous peut-être expliquer plus sur la nature des données qui sont dans la table, et dans le tableau, et la relation entre eux? Il pourrait encore y avoir une meilleure solution. :) – pyrocumulus

+0

Ajouté plus de détails. Voir le deuxième paragraphe. Je ne suis pas sûr que cela compte vraiment. – ibz

2

Le problème est dans les mises à jour. Changer le schéma de tableau en fonction de plusieurs lignes par jour, et le problème de performance va disparaître.

Vous pouvez ajouter des cumuls à des tableaux, plus tard, avec une sorte de cronjob, mais il faut éviter les mises à jour.

+0

"rollups to arrays" serait vraiment lent si je devais construire les tableaux à partir de zéro (passer chaque jour, pour chaque combinaison de a, b, c). – ibz

Questions connexes