Estructura de base de datos SQL para API RESTful

11

Estoy creando una API RESTful. Me cuesta decidir la mejor manera de diseñar las tablas de mi base de datos en torno a mis recursos.

Inicialmente, pensé que una tabla por recurso sería una buena opción, pero ahora me preocupa que esto resulte en tablas exponencialmente más grandes a medida que avanza la cadena de recursos.

Por ejemplo, imagine que tengo tres recursos: usuarios, clientes, ventas. Los usuarios son suscriptores de mi API, los clientes son los clientes y las ventas son compras realizadas por cada cliente a la cuenta de los usuarios.

Se accede a un recurso de venta de la siguiente manera

GET /users/{userID}/clients/{clientID}/sales/{salesID}

Entonces, si hay 10 usuarios, cada uno con 10 clientes, y para cada cliente hay 10 ventas, el tamaño de la tabla aumenta a medida que avanzamos en la cadena de recursos.

Estoy bastante seguro de que SQL puede hacer frente a tablas grandes, pero no estoy seguro de cómo la lectura y la escritura retrasarán las cosas. El ejemplo anterior tal vez no lo ilustra, pero mi API cada vez tendrá más escrituras y lecturas a medida que avancemos en la cadena de recursos. Por lo tanto, tengo el escenario en el que las tablas más grandes de mi base de datos se leerán y escribirán más veces que las tablas más pequeñas.

También será necesario unir tablas antes de ejecutar consultas. La razón es que permito que cada usuario tenga un cliente con el mismo nombre. Para evitar obtener datos incorrectos del cliente, la tabla de usuarios y las tablas de clientes se unen por {userID}. Este es también el caso de las ventas. ¿Unir tablas grandes y ejecutar lecturas y escrituras ralentizará aún más las cosas?

Gaz_Edge
fuente

Respuestas:

31

Me cuesta decidir la mejor manera de diseñar las tablas de mi base de datos en torno a mis recursos.

No lo hagas

Diseñe su API de acuerdo con los principios RESTful , diseñe su base de datos de acuerdo con los principios de normalización . Uno no necesita impactar sobre el otro.

Su base de datos no debe contener una SaleResourcetabla, debe contener una tabla Sale(o compra / pedido). Esa tabla incluirá una clave primaria que identifica de forma exclusiva una venta y claves externas para tablas de usuario y cliente relacionadas.

La API REST traducirá una solicitud del recurso identificado por GET /users/{userID}/clients/{clientID}/sales/{salesID}a la consulta de base de datos apropiada, recuperará la fila, construirá el recurso que representa una venta y lo devolverá al cliente.

Tenga en cuenta que actualmente está exponiendo lo que parecen ser identificadores internos de la base de datos (ID de usuario / ID de cliente / SalesID) al mundo exterior. Puede ser apropiado en su caso, pero generalmente se <entity>IDsiente mal en una API RESTful.

Mark Storey-Smith
fuente
Gracias. Entonces, lo que básicamente está diciendo es que mientras normalice mis bases de datos y configure una indexación adecuada, etc., no debería haber problemas de rendimiento para lo que quiero lograr
Gaz_Edge
3
Si. Nada de lo que ha mencionado sugiere que sería necesario desviarse de un esquema normalizado.
Mark Storey-Smith
9

Las bases de datos relacionales (por lo tanto, SQL) son realmente buenas para localizar una (o pocas) filas de una tabla enorme. Para eso están los índices. También son bastante impresionantes en el manejo de uniones. Realmente no tienes una pregunta . Entre líneas, básicamente se pregunta cómo hacer un diseño de base de datos multiinquilino. Le sugiero que lea la arquitectura de datos de inquilinos múltiples antes de hacer más preguntas. Elija uno de los patrones (base de datos separada, esquemas separados de la base de datos compartida, esquema compartido de la base de datos compartida) y luego podemos discutir detalles. En este momento solo imaginas el último patrón, pero no consideraste los pros y los contras. Leer.

Como nota al margen: no necesita user/{userID}en el URI. Conoce el inquilino (ID de usuario) de la información de autenticación.

Remus Rusanu
fuente
gracias. Sí, necesito leer más. Mis proyectos hasta la fecha han tenido muy poco trabajo en la base de datos. Leeré el recurso que me recomendó
Gaz_Edge
Creo que compartido-compartido es el camino a seguir para mí. Mis 'usuarios' no son 'inquilinos'. No requieren datos aislados y nunca necesitarán acceso directo a ninguna función de administración de bases de datos. Por lo que leí, esto sugeriría que compartido-compartido es mejor. ¿Qué piensas?
Gaz_Edge
2
compartido es el más fácil. Debe agregar el user_idcomo una clave a cada tabla y agregar left.user_id = right.user_ida las combinaciones relevantes (generalmente, todas). Algunos ORM admiten el alcance del acceso. Y no se deje engañar, sus usuarios son inquilinos, ya que no desea que el usuario 'foo' vea / modifique las ventas de la 'barra' del usuario.
Remus Rusanu
Gracias. Estoy empezando a ver que los índices son clave para crear la estructura de mi base de datos.
Gaz_Edge
0

Solo para agregar a lo que ya se ha dicho aquí: es posible que desee crear una interfaz entre la API real y su capa de base de datos. Facilita la adición de almacenamiento en caché y tablas de resumen más adelante ...

Matt Koskela
fuente
1
algunos enlaces o más explicaciones serían útiles
Gaz_Edge
Lo siento, no puedo comentar todavía ..
Matt Koskela