¿Qué tan bien funciona PostgreSQL con una gran cantidad de bases de datos?

9

Tenemos una aplicación web cuya arquitectura requiere que cualquier usuario registrado (una empresa, en realidad) esté aislado del otro, es decir, ejecutaré la misma aplicación web con los mismos modelos de datos, pero con diferentes conjuntos de datos para cada cliente.

Entonces, pensamos en crear una base de datos diferente en Postgres para cada cliente. ¿Puede esta solución escalar a, por ejemplo, bases de datos de 10-20K? ¿Que tan bien?

¿Alguien tiene una mejor solución para esto?

Gracias por adelantado.

Carlos
fuente

Respuestas:

10

En el extremo inferior, básicamente se reduce a "¿puede decir absolutamente que no tiene datos compartidos?" A diferencia de mysql, la base de datos es un límite absoluto en postgresql. No puedes SELECT zip_code FROM common.city_zip WHERE city=...si vas con bases de datos separadas (al menos no sin dblink).

Si tiene datos compartidos, el "esquema" de postgresql es similar a lo que mysql llama una "base de datos" . Puede CREATE SCHEMA clienta; CREATE TABLE clienta.customer (...);. Crearía un esquema para cada cliente, el usuario de ese cliente tendría su esquema primero en su ruta de búsqueda, y se otorgarían permisos para que el usuario del Cliente A tuviera acceso a clientalos publicesquemas (y sus tablas).

Su problema será que en el extremo superior del número de clientes, cada tabla se almacena como un archivo, por lo tanto, ya sea que vaya con una base de datos por cliente, un esquema por cliente o use algo como ${client}_customerpara los nombres de sus tablas, lo hará probablemente se encuentre con los límites del descriptor de archivo con 10k clientes incluso si solo tuviera una tabla por cliente (más un descriptor de archivo por conexión). Por supuesto, puede ajustar el número máximo de descriptores de archivo del núcleo sobre la marcha utilizando sysctl, pero el límite por proceso (ulimit) requerirá reiniciar postgresql si lo configura demasiado bajo la primera vez.

La alternativa es tener "una gran tabla" con una columna de cliente que identifique a qué cliente pertenece esa fila (idealmente, por nombre de usuario si tiene un usuario por cliente, esto hace que las cosas debajo de MUCHO sean más fáciles). Al no otorgar ningún acceso a esta tabla por parte de los clientes, puede crear vistas específicas del cliente (o usar session_userpara identificar al cliente actual). Sin embargo, las actualizaciones no se pueden hacer directamente a través de una vista. Necesitaría tener funciones definidas para insertar / actualizar / eliminar en la tabla (un conjunto de funciones por cliente o usar session_user) con las funciones SECURITY DEFINERque se ejecutan como un usuario especial con permiso para insertar / actualizar / eliminar en las tablas (nota : session_userse usa porque userycurrent_user se basan en el contexto actual, y dentro de una función DEFINIDOR DE SEGURIDAD, este siempre sería el usuario que definió la función).

En cuanto al rendimiento, más allá del problema de fd, honestamente no sé qué pasaría con 10000 bases de datos en postgresql, en comparación con tener una tabla grande con el valor de datos de 10000 clientes. El diseño de índice adecuado debería evitar que la tabla grande sea lenta para consultar.

Diré que fui con bases de datos separadas para cada cliente aquí (agregamos servidores para mantener el sistema utilizable, cambiando las bases de datos de clientes a nuevos servidores según sea necesario, por lo que nunca llegaremos a 10k bases de datos en un servidor). He tenido que restaurar los datos de clientes individuales a partir de copias de seguridad para la depuración o debido a un error del usuario de forma regular, algo que sería una pesadilla absoluta en el diseño de "una gran mesa". Además, si tiene la intención de vender la personalización de su producto a sus clientes, el diseño de "una gran mesa" podría terminar obstaculizando su capacidad de personalizar el modelo de datos.

DerfK
fuente
Hola DerfK. No puedo usar el enfoque de "una gran mesa" debido a la razón que usted indicó. Incluso si hoy los modelos de datos son los mismos para todos los usuarios, no podemos garantizar que siempre sean los mismos. Además, no sabía sobre el límite absoluto de la base de datos en PSQL (ya que tenemos algunos datos compartidos). Creo que he dejado el esquema y los enfoques de nombres de tabla a la izquierda. En su experiencia, ¿qué tan difícil es administrar este número de bases de datos (incluso en diferentes servidores)?
Carlos
@Eduardo La mayor dificultad que tengo es asegurarme de que cuando el modelo de datos deba cambiar para todos, se haga. Algún día adaptaremos algo como el sistema de Rails para administrar los cambios en el modelo de datos, hasta entonces tengo un script que recorre los clientes y ejecuta el mismo comando en cada base de datos. Como no compartimos datos en absoluto, todo lo demás ha sido bastante fácil. Si va con una base de datos con múltiples esquemas, aún puede volcar un esquema de cliente a la vez usando pg_dump -n(¡asegúrese de volcar su esquema común también!) Para enumerar el esquema: psql -Eentonces\dn
DerfK
@Eduardo no diseña para funciones que no tienes derecho. Si ese fuera el caso, mi automóvil sería un submarino y repelería a los osos y podría volar a la luna. Hay muchos patrones sólidos de diseño de bases de datos que le permitirán comenzar con una tabla grande y agregar características adicionales según sea necesario. La clave es preguntarse qué necesita hoy y qué podrá apoyar su equipo de operaciones en función de las proyecciones de crecimiento.
Jeremiah Peschka
@DerfK, ¿cuál es la pila web que usa hoy?
Carlos
@ Jeremías, tienes un buen punto. ¿Tienes experiencia con aplicaciones multitenant?
Carlos
3

Sin más detalles sobre su aplicación, es difícil decir que obtendrá esta seguridad adicional de esta configuración. Si cada cliente se conecta a la aplicación web y hay un usuario compartido de la aplicación web a la base de datos, entonces no ha aislado sus datos de una manera diferente al uso de una sola base de datos monolítica. Acceder a sus datos a través de procedimientos almacenados correctamente parametrizados le proporcionará el nivel de aislamiento que está buscando sin el dolor administrativo de administrar más de 10,000 bases de datos en cualquier número de servidores.

Personalmente, ejecuté una configuración similar en un único servidor de base de datos utilizando nada más que procedimientos almacenados parametrizados que afectan a una sola base de datos. Si puede garantizar que el único acceso a la base de datos es a través de procedimientos almacenados, no hay peligro de que los datos se mezclen en los resultados.

Si desea seguir adelante con su diseño, estas son mis principales preocupaciones:

  1. quedarse sin descriptores de archivo abiertos ( ulimit -n) en su sistema operativo host
  2. ajuste de más de 10,000 bases de datos para diferentes patrones de consulta
  3. administrando más de 10,000 bases de datos con diferentes problemas de seguridad (respaldos y restauraciones potenciales, ¿realmente desea restaurar más de 10,000 bases de datos si hay una falla en el servidor?)
  4. implementar cambios en más de 10,000 bases de datos
Jeremiah Peschka
fuente
¿Y qué tan difícil sería hacer una copia de seguridad y restaurar los datos de un cliente? ¿Es más fácil hacer esto con procedimientos almacenados o con esquemas? Como indicó, el diseño de la aplicación solo utiliza un usuario compartido para conectarse a la base de datos. Al principio, el enfoque de base de datos múltiple se consideró por cuestiones de gestión, en lugar de seguridad.
Carlos
Los procedimientos almacenados parametrizados no protegen contra nada más que inyecciones SQL. Si uno de esos procedimientos hace una SELECT * WHERE clientId = 3, tiene una fuga de seguridad.
mikerobi