Dans quelle mesure PostgreSQL fonctionne-t-il avec un grand nombre de bases de données?


9

Nous avons une application Web dont l'architecture nécessite que tout utilisateur enregistré (une entreprise, en fait) soit isolé de l'autre, c'est-à-dire que je vais exécuter la même application Web avec les mêmes modèles de données, mais avec des ensembles de données différents pour chaque client.

Nous avons donc pensé à créer une base de données différente dans Postgres pour chaque client. Cette solution peut-elle évoluer, par exemple, vers des bases de données 10-20K? Comment bien?

Quelqu'un at-il une meilleure solution pour cela?

Merci d'avance.

Réponses:


10

À l'extrémité inférieure, cela se résume essentiellement à "pouvez-vous absolument dire que vous n'avez pas de données partagées?" Contrairement à mysql, la base de données est une limite absolue dans postgresql. Vous ne pouvez pas SELECT zip_code FROM common.city_zip WHERE city=...si vous allez avec des bases de données distinctes (du moins pas sans dblink).

Si vous avez des données partagées, le "schéma" de postgresql est similaire à ce que mysql appelle une "base de données" . Tu peux CREATE SCHEMA clienta; CREATE TABLE clienta.customer (...);. Vous créez un schéma pour chaque client, que l'utilisateur du client aurait leur schéma d' abord dans leur chemin de recherche, et les autorisations aurait été accordé afin que l'utilisateur du client A aurait accès aux clientaet les publicschémas (et leurs tables).

Votre problème va être qu'à l'extrémité supérieure de # de clients, chaque table est stockée sous forme de fichier, donc si vous allez avec une base de données par client, un schéma par client, ou utilisez quelque chose comme ${client}_customerpour vos noms de table, vous se heurtera probablement à des limites de filedescriptor avec des clients 10k même si vous n'aviez qu'une seule table par client (plus un filedescriptor par connexion). Bien sûr, vous pouvez ajuster le nombre maximal de descripteurs de fichiers du noyau à la volée à l'aide de sysctl, mais la limite par processus (ulimit) nécessitera de redémarrer postgresql si vous le définissez trop bas la première fois.

L'alternative est d'avoir "une grande table" avec une colonne client qui identifie le client auquel appartient cette ligne (idéalement, par nom d'utilisateur si vous avez un utilisateur par client, cela facilite les choses sous un LOT). En n'accordant aucun accès à cette table par les clients, vous pouvez créer des vues spécifiques au client (ou les utiliser session_userpour identifier le client actuel). Cependant, les mises à jour ne peuvent pas être effectuées directement via une vue. Vous auriez besoin d'avoir des fonctions définies pour insérer / mettre à jour / supprimer sur la table (un ensemble de fonctions par client ou bien en utilisant session_user) avec les fonctions utilisant SECURITY DEFINERpour exécuter en tant qu'utilisateur spécial avec la permission d'insérer / mettre à jour / supprimer sur les tables (note : session_userest utilisé parce que useretcurrent_user sont basés sur le contexte actuel, et dans une fonction DEFINIR DE SECURITE, ce serait toujours l'utilisateur qui a défini la fonction).

En termes de performances, au-delà du problème fd, je ne sais vraiment pas ce qui se passerait avec 10000 bases de données dans postgresql, par rapport à avoir une grande table avec 10000 données de clients. Une conception d'index appropriée doit empêcher la grande table d'être lente à interroger.

Je dirai que je suis allé avec des bases de données distinctes pour chaque client ici (nous ajoutons des serveurs pour garder le système utilisable, en déplaçant les bases de données client vers de nouveaux serveurs au besoin, nous n'atteindrons donc jamais 10 000 bases de données sur un seul serveur). J'ai dû restaurer les données des clients individuels à partir de sauvegardes pour le débogage ou en raison d'erreurs utilisateur sur une base régulière, quelque chose qui serait un cauchemar absolu sur la conception d'une "grande table". De plus, si vous avez l'intention de vendre la personnalisation de votre produit à vos clients, la conception d'une «grande table» pourrait vous empêcher de personnaliser le modèle de données.


Salut, DerfK. Je ne peux pas utiliser l'approche "une grande table" pour la raison que vous avez indiquée. Même si aujourd'hui, les modèles de données sont les mêmes pour chaque utilisateur, nous ne pouvons garantir qu'ils seront toujours les mêmes. De plus, je ne connaissais pas la limite absolue de la base de données dans PSQL (car nous avons des données partagées). Je pense que j'ai laissé les approches de nom de schéma et de table à gauche. D'après votre expérience, est-il difficile de gérer ce nombre de bases de données (même sur différents serveurs)?
Carlos

@Eduardo La plus grande difficulté que j'ai avec cela est de s'assurer que lorsque le modèle de données doit changer pour tout le monde, cela se fait. Un jour, nous adapterons quelque chose comme le système de Rails pour gérer les modifications du modèle de données, jusque-là, j'ai un script qui parcourt les clients et exécute la même commande sur chaque base de données. Comme nous ne faisons pas du tout de données partagées, tout le reste a été assez facile. Si vous utilisez une base de données avec plusieurs schémas, vous pouvez toujours vider un schéma client à la fois en utilisant pg_dump -n(assurez-vous de vider votre schéma commun aussi!) Pour répertorier le schéma: psql -Epuis\dn
DerfK

@Eduardo ne conçoit pas des fonctionnalités que vous n'avez pas le droit. Si tel était le cas, ma voiture serait un sous-marin et repousserait les ours et pourrait voler vers la lune. Il existe de nombreux modèles de conception de base de données solides qui vous permettront de commencer avec une grande table et d'ajouter des fonctionnalités supplémentaires si nécessaire. L'essentiel est de vous demander ce dont vous avez besoin aujourd'hui et ce que votre équipe opérationnelle pourra soutenir en fonction des projections de croissance.
Jeremiah Peschka

@DerfK, quelle est la pile Web que vous utilisez aujourd'hui?
Carlos

@Jeremiah, vous avez un bon point. Avez-vous de l'expérience avec les applications multi-locataires?
Carlos

3

Sans plus de détails sur votre application, il est difficile de dire que vous obtiendrez une sécurité supplémentaire de cette configuration. Si chaque client se connecte à l'application Web et qu'il existe un utilisateur partagé de l'application Web à la base de données, vous n'avez pas isolé vos données d'une manière différente de l'utilisation d'une seule base de données monolithique. L'accès à vos données via des procédures stockées correctement paramétrées vous fournira le niveau d'isolement que vous recherchez sans le casse-tête administratif de gérer plus de 10 000 bases de données sur un nombre illimité de serveurs.

J'ai personnellement exécuté une configuration similaire sur un seul serveur de base de données en utilisant rien de plus que des procédures stockées paramétrées frappant une seule base de données. Si vous pouvez garantir que le seul accès à la base de données se fait par le biais de procédures stockées, il n'y a aucun risque de fusion des données dans les résultats.

Si vous voulez aller de l'avant avec votre conception, voici mes principales préoccupations:

  1. à court de descripteurs de fichiers ouverts ( ulimit -n) sur votre système d'exploitation hôte
  2. réglage de plus de 10 000 bases de données pour différents modèles d'interrogation
  3. administrer plus de 10 000 bases de données avec des problèmes de sécurité différents (sauvegardes et restaurations potentielles, voulez-vous vraiment restaurer plus de 10 000 bases de données en cas de défaillance du serveur?)
  4. déployer des modifications dans plus de 10 000 bases de données

Et combien serait difficile de sauvegarder et de restaurer les données d'un client? Est-ce plus facile de le faire avec des procédures stockées ou avec des schémas? Comme vous l'avez indiqué, la conception de l'application n'utilise qu'un seul utilisateur partagé pour se connecter à la base de données. Au début, l'approche à bases de données multiples a été envisagée pour des raisons de gestion plutôt que de sécurité.
Carlos

Les procédures stockées paramétrées ne protègent contre rien sauf les injections SQL. Si l'une de ces procédures fait un SELECT * WHERE clientId = 3, vous avez une fuite de sécurité.
mikerobi
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.