À 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 clienta
et les public
sché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}_customer
pour 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_user
pour 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 DEFINER
pour exécuter en tant qu'utilisateur spécial avec la permission d'insérer / mettre à jour / supprimer sur les tables (note : session_user
est utilisé parce que user
etcurrent_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.