WinterTime
WinterTime

Reputation: 183

Feedback about my database design (multi tenancy)

The idea of the SaaS tool is to have dynamic tables with dynamic custom fields and values of different types, we were thinking to use "force.com/salesforce.com" example but is seems to be too complicated to maintain moving forward, also making some reports to create with a huge abstraction level, so we came up with simple idea but we have to be sure that this is kinda good approach.

This is the architecture we have today (in few steps).

  1. Each tenant has it own separate database on the cluster (Postgres 12).
  2. TABLE table, used to keep all of those tables as reference, this entity has ManyToOne relation to META table and OneToMany relation with DATA table.
  3. META table is used for metadata configuration, has OneToMany relation with FIELDS (which has name of the fields as well as the type of field e.g. TEXT/INTEGER/BOOLEAN/DATETIME etc. and attribute value - as string, only as reference).
  4. DATA table has ManyToOne relation to TABLES and 50 character varying columns with names like: attribute1...50 which are NULL-able.

Example flow today:

  1. When user wants to open a TABLE DATA e.g. "CARS", we load the META table with all the FIELDS (to get fields for this query). User specified that he want to query against: Brand, Class, Year, Price columns.
  2. We are checking by the logic, the reference for Brand, Class, Year and Price in META>FIELDS table, so we know that Brand = attribute2, Class = attribute 5, Year = attribute6 and Price = attribute7.
  3. We parse his request into a query e.g.: SELECT [attr...2,5,6,7] FROM DATA and then show the results to user, if user decide to do some filters on it, based on this data e.g. Year > 2017 AND Class = 'A' we use CAST() functionality of SQL for example SELECT CAST(attribute6 AS int) AND attribute5 FROM DATA WHERE CAST(attribute6 AS int) > 2017 AND attribute5 = 'A';, so then we can actually support most principles of SQL.

However moving forward we are scared a bit:

We are on super early stage, so we can/should make those before we scale, as we knew that this is most likely not the best approach, but we kept it to run the project for small customers which for now is working just fine.

We were thinking also about JSONB objects but that is not the option, as we want to keep it simple for getting the data.

What do you think about this solution (fyi DATA has PRIMARY key out of 2 tables - (ID,TABLEID) and built in column CreatedAt which is used form most of the queries, so there will be maximum 3 indexes)?

If it seem bad, what would you recommend as the alternative to this solution based on the details which I shared (basically schema-less RDBMS)?

Upvotes: 0

Views: 301

Answers (1)

Saravanan
Saravanan

Reputation: 7854

IMHO, I anticipate issues when you wanted to join tables and also using cast etc.

We had followed the approach below that will be of help to you

We have a table called as Cars and also have a couple of tables like CarsMeta, CarsExtension columns. The underlying Cars table will have all the common fields for a ll tenant's. Also, we will have the CarsMeta table point out what are the types of columns that you can have for extending the Cars entity. In the CarsExtension table, you will have columns like StringCol1...5, IntCol1....5, LongCol1...10

In this way, you can easily filter for data also like,

  • If you have a filter on the base table, perform the search, if results are found, match the ids to the CarsExtension table to get the list of exentended rows for this entity
  • In case the filter is on the extended fields, do a search on the extension table and match with that of the base entity ids.
  • As we will have the extension table organized like below

    id - UniqueId

    entityid - uniqueid (points to the primary key of the entity)

    StringCol1 - string,

    ...

    IntCol1 - int, ...

In this case, it will be easy to do a join for entity and then get the data along with the extension fields.

In case you are having the table metadata and data being inferred from separate tables, it will be a difficult task to maintain this over long period of time and also huge volume of data.

HTH

Upvotes: 1

Related Questions