PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

dans postgresql, les partitions ou les bases de données multiples sont-elles plus efficaces ?

Je vous recommande de rechercher des informations sur les listes de diffusion PostgreSQL sur la conception multi-tenant. Il y a eu beaucoup de discussions là-bas, et la réponse se résume à "ça dépend". Il existe des compromis à tous les égards entre l'isolation garantie, les performances et la maintenabilité.

Une approche courante consiste à utiliser une seule base de données, mais un schéma (espace de noms) par client avec la même structure de table dans chaque schéma, plus un schéma partagé ou commun pour les données qui sont les mêmes pour tous. Un schéma PostgreSQL est comme une "base de données" MySQL en ce sens que vous pouvez interroger différents schémas mais qu'ils sont isolés par défaut. Avec les données client dans un schéma séparé, vous pouvez utiliser le search_path paramètre, généralement via ALTER USER customername SET search_path = 'customerschema, sharedschema' pour s'assurer que chaque client voit ses données et uniquement ses données.

Pour une protection supplémentaire, vous devez REVOKE ALL FROM SCHEMA customerschema FROM public puis GRANT ALL ON SCHEMA customerschema TO thecustomer ils sont donc les seuls à y avoir accès, faisant de même pour chacune de leurs tables. Votre pool de connexion peut alors se connecter avec un compte utilisateur fixe qui n'a non GRANT ed accès à n'importe quel schéma client mais a le droit de SET ROLE devenir n'importe quel client. (Faites cela en leur donnant l'adhésion à chaque rôle client avec NOINHERIT défini afin que les droits doivent être explicitement revendiqués via SET ROLE ). La connexion doit immédiatement SET ROLE au client pour lequel il opère actuellement. Cela vous permettra d'éviter les frais généraux liés à l'établissement de nouvelles connexions pour chaque client tout en maintenant une protection solide contre les erreurs de programmation conduisant à l'accès aux données du mauvais client. Tant que le pool fait un DISCARD ALL et/ou un RESET ROLE avant de distribuer les connexions au client suivant, cela vous donnera une isolation très forte sans la frustration des connexions individuelles par utilisateur.

Si votre environnement d'application Web ne dispose pas d'un pool de connexions décent intégré (par exemple, vous utilisez PHP avec des connexions persistantes), alors vous vraiment besoin de mettre un un bon pool de connexion en place entre Pg et le serveur Web de toute façon, car trop de connexions au backend nuiront à vos performances. PgBouncer et PgPool-II sont les meilleures options, et peuvent facilement s'occuper de faire le DISCARD ALL et RESET ROLE pour vous lors du transfert de connexion.

Le principal inconvénient de cette approche est la surcharge liée au maintien de ce nombre de tables, car votre ensemble de base de tables non partagées est cloné pour chaque client. Cela s'additionnera à mesure que le nombre de clients augmentera, au point que le nombre de tables à examiner pendant les exécutions d'autovacuum commence à devenir coûteux et où toute opération qui évolue en fonction du nombre total de tables dans la base de données ralentit. C'est plus un problème si vous envisagez d'avoir plusieurs milliers ou dizaines de milliers de clients dans la même base de données, mais je fortement vous recommandons de faire des tests de mise à l'échelle avec cette conception en utilisant des données factices avant de vous y engager.

L'approche idéale est susceptible d'être des tables uniques avec une sécurité automatique au niveau des lignes contrôlant la visibilité des tuples, mais malheureusement, c'est quelque chose que PostgreSQL n'a pas encore. Il semble que ce soit en route grâce au travail de SEPostgreSQL ajoutant une infrastructure et des API appropriées, mais ce n'est pas dans la 9.1.