2011-05-25 2 views
2

J'ai dans les tables PostgreSQL, chacune avec des millions d'enregistrements et plus d'une centaine de champs.
L'un d'entre eux est un champ de date, que nous filtrons par ceci dans nos requêtes. La création d'un index pour ce champ de date a amélioré la performance des requêtes qui lisent une petite plage de dates, mais dans une grande gamme de dates la performance a diminué ...Améliorer les performances des requêtes dans Postgresql avec un index

Je dois prioriser l'un sur l'autre? Les performances dans les petites gammes peuvent être améliorées sans diminuer les requêtes de grande portée?

Répondre

0

Je vais essayer plusieurs choses:

  • augmentation cache DB Paramètres de
  • ajouter l'index sur ce champ de date
  • nouvelle conception/modifier l'application pour travailler avec des gammes plus petites (althogh cette suggestion peut paraître évident, il est généralement d'abord être jeté)
0

La création d'un index pour ce champ est amélioré les performanc e des requêtes qui ont lu une petite plage de dates, mais dans la grande plage de dates ... la baisse des performances

Essayez clustering votre table en utilisant cet indice. La diminution des performances peut être due à l'ouverture de toute la table sur de grandes plages. Et si c'est le cas, la mise en cluster de la table le long de cet index conduirait à moins de recherche de disque.

0

Deux suggestions:

1) enquêtent sur l'utilisation de table inheritance pour les données de séries chronologiques. Par exemple, créez une table enfant par mois, puis INDEX la date sur chaque table. PostgreSQL est assez intelligent pour exécuter uniquement index_scan sur les tables enfant qui contiennent les données réelles dans la plage de dates. Une fois la table enfant "scellée" car il s'agit d'un nouveau mois, exécutez CLUSTER sur la table pour trier les données par date.

2) Regardez la création d'un groupe de INDEX qui utilisent les clauses WHERE. Suggestion # 1 sera le gagnant à long terme, mais prendra un certain travail à mettre en place (mais évoluera pour toujours), mais la suggestion n ° 2 peut être une solution temporaire rapide si vous avez une plage de dates limitée que vous se soucient de la numérisation. N'oubliez pas que vous ne pouvez utiliser que les fonctions IMMUTABLE dans la clause WHERE de votre INDEX.

CREATE INDEX tbl_date_2011_05_idx ON tbl(date) WHERE date >= '2011-05-01' AND date <= '2011-06-01'; 
+0

Merci, mais il y a un problème, je parle d'un champ de date pour simplifier ma question, mais vraiment j'utilise deux champs de date pour filtrer dans différentes requêtes, une dans certaines requêtes, jamais dans les deux en même temps. Le problème que j'écris est présent dans les deux. Encore une chose, ces deux champs de date sont similaires, je veux dire que la différence est petite (secondes ou milisecondes). Avez-vous des urls d'héritage de table pour les données de séries chronologiques? –

+0

Dans le scénario 1, comment faire les insertions ou les mises à jour sur la table enfant correcte? – AngerClown

+0

* (minutes ou secondes) –

3

Impossible de répondre aux requêtes dans PostgreSQL en utilisant simplement les informations d'un index. Que la ligne soit visible ou non, du point de vue de la requête en cours d'exécution, elle est stockée dans la ligne principale elle-même. Ainsi, lorsque vous ajoutez un index à quelque chose, et d'exécuter une requête qui utilise, il y a deux étapes:

  • Naviguer l'index pour déterminer quels blocs de données sont utilisés
  • récupérer ces blocs et retourner les lignes correspondre à la requête

Il est donc possible que répondre à une requête avec un index puisse prendre plus de temps que d'aller directement aux blocs de données et d'aller chercher les lignes.Le cas le plus fréquent où cela se produit est si vous êtes en train de saisir une grande partie des données. Généralement, si plus de 20% de la table est utilisée, il est considéré comme rapide de l'accéder de manière séquentielle. Parfois, le planificateur pense que moins de 20% seront accessibles, donc l'indice est préféré, mais ce n'est pas vrai; C'est une façon d'ajouter un index peut ralentir une requête. C'est peut-être la situation que vous voyez, basée sur votre description - si les grandes plages touchent plus de la table que les estimations de l'optimiseur, l'utilisation d'un index peut être un ralentissement net. Pour comprendre cela, la base de données recueille des statistiques sur chaque colonne de chaque table, afin de déterminer si une condition WHERE particulière est suffisamment sélective pour utiliser un index. L'idée est que vous devez avoir sauvé autant de blocs en ne lisant pas toute la table que l'ajout de l'index E/S en plus de cela est toujours une victoire nette.

Ce calcul peut mal tourner, de sorte que vous finissez par faire plus d'E/S que si vous aviez simplement lu la table directement, dans quelques cas. La cause de la plupart d'entre eux apparaît si vous exécutez la requête en utilisant EXPLAIN ANALYZE. Si les valeurs "attendues" et les nombres "réels" sont très différentes, cela peut suggérer que l'optimiseur avait de mauvaises statistiques sur la table. Une autre possibilité est que l'optimiseur a simplement fait une erreur sur la sélectivité de la requête - il pensait que cela ne retournerait qu'un petit nombre de lignes, mais il restituerait la plus grande partie de la table. Ici encore, de meilleures statistiques sont la façon normale de commencer à travailler là-dessus. Si vous utilisez PostgreSQL 8.3 ou une version antérieure, la quantité de statistiques collectées est très faible par défaut.

Certaines charges de travail finissent par ajuster le paramètre ajustable random_page_cost, qui contrôle l'endroit où se produit cet échange entre index et table scan. C'est seulement quelque chose à considérer après que l'information de statistiques soit vérifiée cependant. Voir Tuning Your PostgreSQL Server pour une intro à plusieurs choses que vous pouvez ajuster ici.

Questions connexes