Pourquoi chute de performances des requêtes PostgresQL au fil du temps, mais restauré lorsque l'indice de reconstruction

StackOverflow https://stackoverflow.com/questions/2392982

Question

Selon cette dans le manuel, indexes don't need to be maintained. Cependant, nous courons avec une table de PostgresQL qui a un taux continu de updates, deletes et inserts que dans le temps (quelques jours) voit une dégradation de requête importante. Si nous supprimer et recréer l'index, les performances des requêtes est rétablie.

Nous utilisons hors des paramètres de la boîte.
Le tableau dans notre test est actuellement vide et ses débuts pousse à un demi-million de lignes. Il a une rangée assez grande (beaucoup de champs de texte).

Nous searching based of an index, not the primary key (j'ai confirmé l'indice est utilisé, au moins dans des conditions normales)

La table est utilisée comme un stockage persistant pour un seul processus. L'utilisation PostgresQL sous Windows avec un client Java.

Je suis prêt à renoncer à insert and update performance pour maintenir les performances des requêtes.

Nous envisageons rearchitecting l'application afin que les données sont réparties sur différentes tables dynamiques d'une manière qui nous permet de déposer et reconstruire les index périodiquement sans impact sur l'application. Cependant, comme toujours, il y a un manque de temps pour obtenir ce travail et je soupçonne que nous manque quelque chose dans notre base de configuration ou de l'utilisation.

Nous avons examiné forcing vacuuming et rebuild to run at certain times, mais je soupçonne que le locking period for such an action would cause our query to block. Cela peut être une option, mais il y a un peu en temps réel (fenêtres de 3-5 secondes) conséquences qui nécessitent d'autres changements dans notre code.

Informations complémentaires: Le tableau et l'indice

CREATE TABLE icl_contacts
(
  id bigint NOT NULL,
  campaignfqname character varying(255) NOT NULL,
  currentstate character(16) NOT NULL,
  xmlscheduledtime character(23) NOT NULL,
...
25 or so other fields.  Most of them fixed or varying character fiel  
...
  CONSTRAINT icl_contacts_pkey PRIMARY KEY (id)
)
WITH (OIDS=FALSE);
ALTER TABLE icl_contacts OWNER TO postgres;

CREATE INDEX icl_contacts_idx
  ON icl_contacts
  USING btree
  (xmlscheduledtime, currentstate, campaignfqname);

Analyser:

Limit  (cost=0.00..3792.10 rows=750 width=32) (actual time=48.922..59.601 rows=750 loops=1)
  ->  Index Scan using icl_contacts_idx on icl_contacts  (cost=0.00..934580.47 rows=184841 width=32) (actual time=48.909..55.961 rows=750 loops=1)
        Index Cond: ((xmlscheduledtime < '2010-05-20T13:00:00.000'::bpchar) AND (currentstate = 'SCHEDULED'::bpchar) AND ((campaignfqname)::text = '.main.ee45692a-6113-43cb-9257-7b6bf65f0c3e'::text))

Et, oui, je suis conscient qu'il ya une variété de choses we could do to normalize and improve the design of this table. Certaines de ces options peuvent être disponibles pour nous.

Je me concentre sur cette question est de comprendre how PostgresQL is managing the index and query over time (understand why, not just fix). Si elle devait faire plus ou sensiblement refondus, il y aurait beaucoup de changements.

Était-ce utile?

La solution

vide automatique devrait faire l'affaire, à condition que vous l'avez configuré pour votre performance souhaitée.

Notes: VACUUM FULL: cette reconstruira les statistiques de table et de récupérer des charges d'espace disque. Il verrouille la table.

VIDE: ce reconstruira les statistiques de table et de récupérer l'espace disque. Il peut être exécuté en parallèle avec le système de production, mais génère beaucoup d'IO qui peuvent avoir un impact sur les performances.

ANALYSER: ce reconstruira les statistiques de planificateur de requêtes. Ceci est déclenché par VACUUM, mais peut être exécuté sur lui-même.

Plus notes détaillées trouvées ici

Autres conseils

En ce qui concerne la performance, en utilisant des chaînes pour le stockage de temps et d'information est un état tout à fait goulot d'étranglement. Tout d'abord, les index sur des textes sont extrêmement inefficaces, en comparant deux fois le même jour a besoin d'au moins 11 comparaison (dans le format que vous avez utilisé), mais en utilisant le type de temps, il peut être réduit à une simple comparaison. Cela influe également la taille de l'index, et un grand indice est difficile à rechercher plus, et le db ne gardera pas en mémoire. Les mêmes considérations sont applicables à la colonne d'état. Si elle représente un petit ensemble d'états, vous devez utiliser des nombres entiers mis en correspondance aux Etats, cela réduira les nœuds de l'indice - et la taille de l'index en conséquence. En outre, cet indice sera inutile même en utilisant theese types intégrés si vous ne spécifiez pas le temps réel dans votre requête.

Cela sent comme indice météorisation pour moi. I'l vous référer à cette page

http://www.postgresql.org/docs/8.3/ statique / reindex.html-routine

qui dit au fond:

  

En outre, pour les index B-tree un   indice fraîchement construit est quelque peu   plus rapide d'accès que celui qui a   été mis à jour plusieurs fois, parce que   logiquement pages adjacentes sont généralement   également adjacent physiquement dans une nouvelle   index généré. (Cette considération ne   pas applicable actuellement à la non-B-tree   index). Il pourrait être utile de   juste pour ré-indexation périodiquement améliorer   la vitesse d'accès.

Ce qui ne semble entrer en conflit avec la page que vous avez mentionné en disant que les index « ne nécessitent pas d'entretien ou d'accord ».

Avez-vous essayé « créer un index en même temps »?

est le '2010-05-20T13: 00: 00.000'? Valeur xmlscheduledtime est comparée à une partie de SQL, ou fourni comme paramètre

Lors de la planification comment exécuter la requête, en disant qu'un champ doit être inférieur à un paramètre fourni avec une valeur encore inconnue ne donne pas beaucoup de PostgreSQL pour continuer. Il ne sait pas si ça va correspondre presque toutes les lignes ou presque aucune des lignes.

Lecture sur comment le planificateur utilise les statistiques aide énormément en essayant de comprendre pourquoi votre base de données utilise les plans, il est.

Vous pouvez obtenir une meilleure sélection de la performance en changeant l'ordre des champs dans cet index complexe, ou la création d'un nouvel indice, avec les champs commandés (campaignfqname, currentState, xmlscheduledtime) depuis lors, l'index vous mènera directement à la campagne nom de fq et l'état actuel que vous êtes intéressé, et l'analyse d'index sur la plage de xmlscheduledtime seront toutes les lignes que vous êtes après.

C'est un cas d'école. Vous devez autovacuum de configuration pour être beaucoup plus agressif.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top