Question

J'ai une situation très similaire à celle décrit ici:

J'ai une situation SaaS où j'utilise plus de 1000 schémas dans une seule base de données (chaque schéma contient les mêmes tables, juste différentes données par locataire). J'ai utilisé des schémas afin que les serveurs d'applications partagés puissent partager une connexion avec la base de données unique pour tous les schémas. Les choses fonctionnent bien.

Et, alors que l'application elle-même semble fonctionner correctement, certaines requêtes impliquant des catalogues système sont très lentes. Aussi, psqlLa complétion automatique est totalement inutile et \dt Est très lent.

En particulier, je dois calculer la taille sur le disque de chaque schéma en utilisant quelque chose comme ceci:

SELECT sum(pg_total_relation_size(c.oid)) AS size
FROM   pg_namespace n
JOIN   pg_class     c ON c.relnamespace = n.oid
WHERE  n.nspname = 'abbiecarmer'
AND    c.relkind = 'r';

ce qui est assez lent. En regardant le plan de requête, je vois

Aggregate  (cost=136903.16..136903.17 rows=1 width=4) (actual time=1024.420..1024.420 rows=1 loops=1)             
  ->  Hash Join  (cost=8.28..136902.86 rows=59 width=4) (actual time=143.247..1016.749 rows=60 loops=1)           
        Hash Cond: (c.relnamespace = n.oid)                                                                       
        ->  Seq Scan on pg_class c  (cost=0.00..133645.24 rows=866333 width=8) (actual time=0.045..943.029 rows=879788 loops=1)                                                                                                    │
              Filter: (relkind = 'r'::"char")                                                                     
              Rows Removed by Filter: 2610112                                                                     
        ->  Hash  (cost=8.27..8.27 rows=1 width=4) (actual time=0.032..0.032 rows=1 loops=1)                      
              Buckets: 1024  Batches: 1  Memory Usage: 1kB                                                        
              ->  Index Scan using pg_namespace_nspname_index on pg_namespace n  (cost=0.00..8.27 rows=1 width=4)(actual time=0.029..0.030 rows=1 loops=1)                                                                        │
                    Index Cond: (nspname = 'abbiecarmer'::name)                                                   
Total runtime: 1024.476 ms                                                                                        

Ce qui, si je le comprends bien, indique que 90% du temps de requête est passé séquentiellement à scanner séquentiel pg_class relation.

J'ai arrêté Postmaster, exécuté le backend en mode utilisateur unique et ajouté les index suivants:

create index pg_class_relnamespace_index on pg_class(relnamespace);
REINDEX INDEX pg_class_relnamespace_index;

create index pg_class_reltablespace_index on pg_class(reltablespace);
REINDEX INDEX pg_class_reltablespace_index;

(J'ai aussi des milliers d'espaces de table aussi). Maintenant, la requête est ~ 100 fois plus rapide et le plan semble beaucoup plus agréable:

Aggregate  (cost=846.91..846.92 rows=1 width=4) (actual time=10.609..10.610 rows=1 loops=1)                       
  ->  Nested Loop  (cost=0.00..846.61 rows=60 width=4) (actual time=0.069..0.320 rows=60 loops=1)                 
        ->  Index Scan using pg_namespace_nspname_index on pg_namespace n  (cost=0.00..8.27 rows=1 width=4) (actual time=0.023..0.024 rows=1 loops=1)                                                                              │
              Index Cond: (nspname = 'abbiecarmer'::name)                                                        
        ->  Index Scan using pg_class_relnamespace_index on pg_class c  (cost=0.00..837.59 rows=75 width=8) (actual time=0.043..0.271 rows=60 loops=1)                                                                             │
              Index Cond: (relnamespace = n.oid)                                                                 
              Filter: (relkind = 'r'::"char")                                                                    
              Rows Removed by Filter: 102                                                                        
Total runtime: 10.696 ms                                                                                         

Cependant, dans le fil ci-dessus, Tom Lane, qui est l'un des contributeurs de base de Postgres, dit:

Il y a beaucoup de gotchas ici, notamment que la session dans laquelle vous créez l'index ne saura pas qu'elle est là (donc dans ce cas, un Reindex sur PG_CLASS serait probablement conseillé par la suite). Je pense toujours que vous seriez fou de l'essayer sur une base de données de production, mais ...

Je suis également inquiet par le fait que la modification des catalogues système semblait complètement désactivée dans Postgres 9.0 et 9.1 (j'utilise 9.2) - je suppose que cela a été fait pour une raison?

Donc, la question est: Quels sont les gotchas pour ajouter un index à un catalogue système dans Postgres et serai-je fou si je fais (éventuellement) cela sur un système de production?

Pas de solution correcte

Licencié sous: CC-BY-SA avec attribution
Non affilié à dba.stackexchange
scroll top