PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

in postgresql, le partizioni o più database sono più efficienti?

Consiglierei di cercare informazioni nelle mailing list di PostgreSQL sulla progettazione multi-tenant. Ci sono state molte discussioni lì e la risposta si riduce a "dipende". Ci sono tutti i compromessi tra isolamento garantito, prestazioni e manutenibilità.

Un approccio comune consiste nell'utilizzare un unico database, ma uno schema (spazio dei nomi) per cliente con la stessa struttura di tabella in ogni schema, più uno schema condiviso o comune per i dati che è lo stesso in tutti loro. Uno schema PostgreSQL è come un "database" MySQL in quanto è possibile eseguire query su schemi diversi ma sono isolati per impostazione predefinita. Con i dati dei clienti in uno schema separato puoi utilizzare search_path impostazione, di solito tramite ALTER USER customername SET search_path = 'customerschema, sharedschema' per garantire che ogni cliente veda i propri dati e solo i propri dati.

Per una protezione aggiuntiva, dovresti REVOKE ALL FROM SCHEMA customerschema FROM public quindi GRANT ALL ON SCHEMA customerschema TO thecustomer quindi sono gli unici ad avere accesso ad esso, facendo lo stesso con ciascuno dei loro tavoli. Il tuo pool di connessioni può quindi accedere con un account utente fisso che non ha nessun GRANT ed accedere a qualsiasi schema del cliente ma ha il diritto a SET ROLE diventare qualsiasi cliente. (Fai ciò dando loro l'appartenenza a ciascun ruolo cliente con NOINHERIT impostato in modo che i diritti debbano essere esplicitamente rivendicati tramite SET ROLE ). La connessione dovrebbe immediatamente SET ROLE al cliente attualmente operante come. Ciò ti consentirà di evitare il sovraccarico di creare nuove connessioni per ciascun cliente, pur mantenendo una forte protezione contro gli errori del programmatore che portano all'accesso ai dati del cliente sbagliato. Finché il pool esegue un DISCARD ALL e/o un RESET ROLE prima di distribuire le connessioni al prossimo client, questo ti darà un isolamento molto forte senza la frustrazione delle connessioni individuali per utente.

Se l'ambiente dell'app Web non dispone di un pool di connessioni decente integrato (ad esempio, stai utilizzando PHP con connessioni persistenti), allora davvero è necessario inserire un un buon pool di connessioni comunque in atto tra Pg e il server web, perché troppe connessioni al backend danneggeranno le tue prestazioni. PgBouncer e PgPool-II sono le opzioni migliori e può occuparsi facilmente di fare il DISCARD ALL e RESET ROLE per te durante il trasferimento della connessione.

Lo svantaggio principale di questo approccio è il sovraccarico dovuto al mantenimento di così tante tabelle, poiché il set di base di tabelle non condivise viene clonato per ogni cliente. Si sommerà man mano che il numero dei clienti cresce, al punto che il numero di tabelle da esaminare durante le esecuzioni di autovacuum inizia a diventare costoso e qualsiasi operazione che si ridimensiona in base al numero totale di tabelle nel DB rallenta. Questo è più un problema se stai pensando di avere molte migliaia o decine di migliaia di clienti nello stesso DB, ma io fortemente ti consiglio di eseguire alcuni test di ridimensionamento con questo progetto utilizzando dati fittizi prima di impegnarti.

È probabile che l'approccio ideale sia costituito da tabelle singole con sicurezza automatica a livello di riga che controlla la visibilità delle tuple, ma sfortunatamente è qualcosa che PostgreSQL non ha ancora. Sembra che sia in arrivo grazie al lavoro di SEPostgreSQL che aggiunge infrastruttura e API adeguate, ma non è in 9.1.