REINDEX est-il dangereux?

17

J'ai essayé COUNT(*)une table avec 150 000 lignes qui a une clé primaire. Cela prend environ 5 minutes, j'ai donc compris qu'il s'agissait d'un problème d'indexation.

Citant le manuel PostgreSQL :

REINDEX est similaire à une suppression et recréation de l'index en ce que le contenu de l'index est reconstruit à partir de zéro. Cependant, les considérations de verrouillage sont assez différentes. REINDEX verrouille les écritures mais pas les lectures de la table parent de l'index. Il prend également un verrou exclusif sur l'index spécifique en cours de traitement, qui bloquera les lectures qui tentent d'utiliser cet index (...) Le CREATE INDEX suivant verrouille les écritures mais pas les lectures; comme l'index n'est pas là, aucune lecture ne tentera de l'utiliser, ce qui signifie qu'il n'y aura pas de blocage mais les lectures pourraient être forcées dans des analyses séquentielles coûteuses.

D'après votre propre expérience, pouvez-vous dire:

  • est REINDEXINGdangereux? Peut-il nuire à la cohérence des données?
  • Cela peut-il prendre beaucoup de temps?
  • Est-ce une solution probable à mon scénario?

Mise à jour:

La solution qui a fonctionné pour nous était de recréer le même index avec un nom différent, puis de supprimer l'ancien index.

La création de l'index est très rapide, et nous avons réduit la taille de l'index de 650 Mo à 8 Mo. L'utilisation d'un COUNT(*)avec betweenne prend que 3 secondes.

Adam Matan
la source

Réponses:

15

La réindexation n'est pas dangereuse et ne peut pas nuire à la cohérence des données. Cependant, si vous avez des écritures à temps critique, vous risquez de perdre des données si la table est verrouillée et que le DML est abandonné.

La réindexation ne devrait pas prendre beaucoup de temps, mais impliquera généralement la lecture de la table entière, le tri des champs d'index et l'écriture d'un nouvel index. Étant donné le temps, COUNT(*)cela prendra probablement cinq minutes ou plus.

Il est peu probable que ce soit un problème d'indexation. COUNT(*)devrait utiliser une analyse de table auquel cas aucun index n'est lu. Je suppose que vous avez un problème d'E / S quelconque.

Essayez d'utiliser COUNT(1)ou COUNT(pk_field)qui peut utiliser l'index.

Si vous utilisez une plate-forme Unix ou Linux, vous souhaiterez peut-être surveiller l'activité du disque avec sar. Vous pouvez également avoir un disque défaillant qui peut réduire considérablement les taux d'E / S.

Les tables contenant de gros objets peuvent également augmenter considérablement les entrées-sorties pour construire les enregistrements pour COUNT (*).

BillThor
la source
2
Selon wiki.postgresql.org, COUNT(*)est le meilleur choix:If you are using count(*), the database is free to use any column to count, which means it can pick the smallest covering index to scan (note that this is why count(*) is much better than count(some_field), as long as you don't care if null values of some_field are counted). Since indexes often fit entirely in memory, this means count(*) is often very fast.
orange80
1

Je ne suis pas sûr de la meilleure réponse pour vous. Cependant, ce fil semble offrir de bonnes suggestions: n http://postgresql.1045698.n5.nabble.com/count-performance-issue-td2067873.html

Une note est que vous pouvez implémenter un TRIGGER pour maintenir le nombre de lignes dans une table séparée (si COUNT (*) est appelé fréquemment par vos applications).

Quelques-unes des réponses suggèrent que cela est symptomatique d'une base de données qui n'a pas été aspirée assez récemment (suggérant que l'autovacuum est désactivé sur votre serveur ou pour cette base de données en particulier)?

Une autre suggestion ressemble à ceci:

ANALYZE tablename;
SELECT reltuple FROM pg_class WHERE relname = 'tablename';

Et quelqu'un identifié comme A. Kretschmer note:

Non. L'implémentation d'index actuelle ne contient aucune information sur la visibilité des lignes dans la transaction en cours. Vous devez analyser l'ensemble de la table de données pour savoir si la ligne actuelle est visible dans la transaction en cours.

... soutenant mon commentaire sur les autorisations au niveau des lignes étant un problème de performances.

Ma recherche a également révélé WikiVS: MySQL vs PostgreSQL: COUNT (*) .

Vous pouvez parcourir les autres résultats que j'ai trouvés en utilisant Google: performances de comptage postgresql (*)

Jim Dennis
la source