My sql schema design issues - general design - mysql

I am trying to design my database. for now my schema is as below:
There exist 3 fixed tables already and during time the numbers of my tables will be increasing with the same fields but different values in tables (mm, xx, yy, zz,...). There is not any duplication between each table.
a) user table, who are the internal users.
b) map_platform_user, which mapped the internal users with the external users. Internal users are our users and external users are our partner users.
c) platform, is a partners' platforms.
d) mm or xx, is the user information that are difference for each platforms.
I have created the look up table called map_platform_user. This table have a field user_platform_id that I though to create a relation with the mm table. (PK-FK).
1) I though to create a multiple references like mm_user_id(PK), xx_user_id(PK),... to the user_platform_id (PK). However I am pretty sure that this solution is wrong and I can not have several references to one table.
2) My next solution is to create each time a new field to the table map_platform_user such as user_platform_id1, user_platform_id2,... but this solution requires altering each time the table map_platform_user.
3) The third solution I thought about that is to not create the extra tables and store everything in the map_platform_user table, so if the new platforms are coming based on our demands, I store them in the field user_platform_id. In this case I have to add name,email,.. to the table map_platform_user.
I would like to mention that the user_platform_id is an external_id which should be received from our clients.
The version of mysql is 5.5.47and the engine in InnoDB. I will be appreciated for any solution and discussion in order to improve the performance of my db. I will have a big amount of data.

Related

organizing multi-tenant db/MySQL [SaaS]

Good example will be shopify. Where you have N number of users (in this case each user assume site). And each user will have it's own records in DB. But db schema will be the same (same tables for each user, products, customers, orders etc.).
So question is what will be the best way to organize this kind of solution?
Store everything in one DB but in a different tables, or run separate DB for each user (but then will be question with maintaining, scalability and automatization)
possible solution:
We can use one DB with common tables like products, customers, orders etc. And we will have table users where we store records about each site.
In tables products, customers we will group all records by user_id.
This is one of possible solutions. But if we will have 1000 users (sites), each will have ~2k products, and ~100k customers, we can end up with tables which has millions of records, so questions will be:
how it will perform compare to each user (site) would have it's own DB?
how reliable this approach? bigger data, harder maintain, backup/restore
safety, if something wrong with one source thousands will be affected
Any links etc. will be much appreciated, thanks!
Create a mysql user for each tenant
Add a tenant_id column to each table
Add a view for each table that filters based on tenant_id = mysql_user
Use a trigger to automatically populate the tenant_id column on INSERT
Restrict the tenant mysql users to only access the views, not the raw tables
I wrote up a blog post on how I was able to convert a large single-tenant mysql application to a multi-tenant application in a weekend using this technique.
https://opensource.io/it/mysql-multi-tenant/
I recommend reviewing databases by well-supported open source solutions. With this in mind, here's a pretty simple schema I found real quick that'd explain a good working solution for this with scale-ability in mind.
http://www.zentut.com/sql-tutorial/sql-sample-database/
I have this file Generate_multiTanentMysql.php i do all steps with PHP script
https://github.com/ziedtuihri/SaaS_Application
Solution Design Pattern :
Creating a database user for each tenant
Renaming every table to a different and unique name (e.g. using a prefix ‘someprefix_’)
Adding a text column called ‘id_tenant’ to every table to store the name of the tenant the row belongs to
Creating a trigger for each table to automatically store the current database username to the id_tenant column before inserting a new row
Creating a view for each table with the original table name with all the columns except id_tenant. The view will only return rows where (id_tenant = current_database_username)
Only grant permission to the views (not tables) to each tenant’s database user Then, the only part of the application that needs to change is the database connection logic. When someone connects to the SaaS, the application would need to:
Connect to the database as that tenant-specific username

Need help in designing a database schema for a SaaS application

I am a developer and have never worked on DB before (designing a DB). I am designing a database for an employee management system which is a Node.js + Express application using MySQL as its DB.
I already have the required tables, columns sorted out but there are still few unknowns I am dealing with. This is my plan so far and I need your input on it.
The end users using this application will be small - mid size companies. The companies won't be sharing the tables in the database. So if there is a table named EmployeeCases I plan to create a new EmployeeCases table for each existing company or a new one who signs up for this application. I am planning to name the table as EmployeeCases_989809890 , where "989809890" will be the company id (or customer id). So if we have 3-4 companies who signed up for us, then all the tables (at least the ones which a company uses) will be recreated and named as TableName_CompanyId. My questions, is this a good way to go? Is there a better way?
All the employee's data is held by the Employee table, including their login and password. Now each Employee table in DB will be named as Employee_CompanyId (as per my plan above). My question is, when an employee logs in, how will I know which Employee table to query to? Or should I remove the login from the Employee table and create a universal Users table where all the employees will be stored? The Users table will also have the CompanyId as one of its column and I will read the CompanyId from there which will be used to query other tables.
Any reference, website or blogs on this type of design will be appreciated.
Thanks.
I don't recommend this approach, I think you should either:
A) Put all the information in the same tables and have a companyId column to sort them out
OR
B) Have separate databases for each company and use the appropriate database using the code.
The thing is, with your approach, you'll have a hard time maintaining your application if you have multiple copies of the same table with different names. If you decide to add a column to one of the tables, for instance, you will have to write as many SQL scripts as you have table instances. You'll also have a bad time with all of your unique identifiers.
Here are some advantages/disadvantages of each design:
A) Put all the information in the same tables and have a compagnyId column to sort them out
Advantages:
Simplest
Allow usage of foreign key / constraints
Great for cross / client data extraction
Disadvantages:
Not portable (a client can't just leave with his/her data)
Can be perceived as less secure (I guess you can make the case both ways)
More likely to have huge tables
Does not scale very well
B) Have separate databases for each company and use the appropriate database using the code.
Advantages:
Portable
Can be perceived as more secure
Disadvantages:
Needs more discipline to keep track of all the databases
Needs a good segregation of what's part of your HUB (Your application that tracks which client access which database) and that's part of your client's database.
You need a login page by company (or have your clients specify the company in a field)
An example of an application that uses this "two-step login" is Slack, when you sign-in you first enter your team domain THEN your user credentials.
I think Google Apps for Work as the same approach. Also, I think most CRM I worked with has a separate database for their clients.
Lastly, I'd like to direct you to this other question on stackoverflow that links to an interesting example.
You shouldn't split your tables just because companies won't share their information. Instead, you should have a companyId column in each table and access to the relevant data for each query. This should be implemented in your backend

Creating a table with specific field parameters

I struggling to create a table that sets table parameters as well as creating the columns.
I am using MySQL server.
I require that the table meets the following criteria:
The table should be Called CUSTOMER with the columns CUST, LOCX, LOCY.
The column CUST will be a 1 up serial starting 1001 and will be the primary key.
LOCX and LOCY will contain X and Y Integers no greater than +-11, and will be foreign keys to other tables.
For info: I then intend to add my data to the table using the INSERT INTO function in a separate query that I already have.
Any direction on the construction of a query to create a table meeting the requirements above will be greatly appreciated
you can create a new table with a MySQL-GUI if you have problems with that.
These GUI-tools usually provide a New-Table button that also allows you to define your table without writing any code. They are often limited but should be more than sufficient for your needs. there are 1-month trial versions for paid versions and even completely free GUIs so you don't have to buy anything.
after that use the following code to retrieve "perfect" SQL from MySQL:
show create table your_schema_name.your_table_name
do that a few times and study the code. Soon you will be able to write create-table statements and include more complex column definitions on your own. It will also be easier to understand the MySQL Documentation which can be confusing and somehow intimidating with its completeness for beginners.

How do I keep two article tables synced, but keep stock separate

This is probably a more conceptual problem, but I couldn't find an easy solution.
Scenario: Two shops (say 'M' and 'S']. M is the master and determines the articles in the databases. Each maintains an independent stock. I have M's article table replicating to S, and I separated stock into a separate table with a common reference.
Now when new articles are added in M, they arrive at S too, but they won't have an entry in S's stock table. Similar problem with delete articles. Possible solutions:
Do I create an entry in S's stock table each time a request is made
for a new (not-test-existing) article?
Do I have to scan regularly to check for missing stock entries.
Isn't there a more elegant way to solve this?
NOTE: To clarify, let me explain another way:
M already replicates the 'articles' table to S (using MySQL's replication mechanism.
This works fine.
The problem is that M and S have 'stock' tables which are local to each M and S. What is the normal procedure when, for example, a new product is added (in M) to the 'articles' table, and transferred to S. Now there is new entry which doesn't have a corresponding entry in S's stock table.
I'm guessing this is not an unusual situation - what would be the normal procedure to solve this?
Unless of course if you have two databases located on two different DB servers, why don't you simply create a table articles and a table stock referencing it. You could add the shop (ideally the shop_id) as an extra column of that latter. Something like that:
CREATE TABLE articles(id int primary key not null,
name char(20) not null);
CREATE TABLE stock(article_id int not null,
shop ENUM('M', 'S') not null,
qty int not null,
FOREIGN KEY(article_id) REFERENCES articles(id),
UNIQUE(article_id, shop));
Please see http://sqlfiddle.com/#!2/e6eca/5 for a live example.
If you really need to restrict creation of items on table articles to shop M that could be achieved by creating different users for your DB (*user_m*, *user_s*) and using REVOKE and/or GRANT to setup the various access rights.
EDIT: If the two servers are on distant sites, you would probably be able to use MySQL replication capabilities to keep one or many tables in sync between the two sites. This will require a network access between the two sites. As of myself, for obvious reasons, I would consider using a secure tunnel between the two sites. Finally you still probably have to set-up permissions at DB-level to only allow insert from one site and not the other.
As a "poor's man" solution, you finally have the possibility to backup on regular basis the required tables from one server to update the tables on the second server. A combination of mysqldump + cronjob would be good starting point.
As of myself, I would though push to MySQL replication. The setup is probably more complex. But this will perform better, scale better and have lower latency.

SQL to update column in modified table

I am a reasonably competent SQL programmer but my skills are still pretty much in the domain of simple INSERT, SELECT, UPDATE statements with an occasional LIKE etc thrown in. What I am currently trying to do is rather more complex. Here is the scenario.
I have three tables.
Table 1, *users* identifies users via a User ID, uid. Users can have one or more sub accounts
Table 2 *accounts* keeps a record of subaccounts for each user with, amongst other things the columns uid and sid where uid is the one defined in the *users* table.
Table 3, *data* is currently storing some data, in a data column that is being associated with a particular subaccount, sid.
The thing I have just realized is that there is no particular reason to block users from using those data across subaccounts. No problem - I can change my data subset search SQL to work with the uid instead. However, given the frequency of such searches, it seems well worth while simply sticking in a uid column in *data*.
To do that I would need to write some smart SQL that would get uid,sid pairs from the *accounts* table and use that information to update the newly created uid column in the data table. This I have to admit is beyond my knowledge of SQL.
I should mention that the system using these data is now in production and has several 100s of users so the option of just acting like they are not there is not available. Not terribly relevant I think but I should mention that uid and sid are alphanumeric strinsg with both columns being indexed.
I would be most grateful to anyone here who might be able to help out with it.
Mysql can do updates based on joins and based on reading of your schema here's what I'd do...
UPDATE accounts a, data d
set d.uid=a.uid
where a.sid=d.sid
and d.uid is NULL