MySQL Relational Database Design for Transactions/Fees - mysql

I'm curious on the best design pattern for my application. I have clients who I process transactions for. I then charge them a fee. I then transfer the fee to me, and the remaining balance to them. Currently I have a transaction table to support all of this, and I feel it's ugly.
Transaction table has
ID | trans_id | amount | type | status | client_id | transfer_id | created | modified
With this model, I assume I can store various types of transactions. I could store a charge in the amount of $100.00 for client 1 and also store a fee for it in the amount of $2.00. When I transfer the funds, I could add a row of the transfer type, and then update the previous rows with the ID of this transfer. But I feel that this will make the queries very complex.
Should I instead have a separate table for charge, fee and transfer?

Having a relational database with different tables would be highly beneficial and more efficient. A relation design structure would reduce redundancies with the use of primary and foreign keys and will prevent duplicates. So go with a relational database with the separate tables.

Related

Several many-to-many relationships to one table

My database has several categories to which I want to attach user-authored text "notes". For instance, an entry in a high level table named jobs may have several notes written by the user about it, but so might a lower level entry in sub_projects. Since these notes would all be of the same format, I'm wondering if I could simplify things by having only one notes table rather than a series of tables like job_notes or project_notes, and then use multiple many-to-many relationships to link it to several other tables at once.
If this isn't a deeply flawed idea from the get go (let me know if it is!), I'm wondering what the best way to do this might be. As I see it, I could do it in two ways:
Have a many-to-many junction table for each larger category, like job_notes_mapping and project_notes_mapping, and manage the MtM relationships individually
Have a single junction table linked to either an enum or separate table for table_type, which specifies what table the MtM relationship is mapping to:
+-------------+-------------+---------------+
| note_id | table_id | table_type_id |
+-------------+-------------+---------------+
| 1 | 1 | jobs |
| 2 | 2 | jobs |
| 3 | 1 | project |
| 4 | 2 | subproject |
| ........... | ........... | ........ |
+-------------+-------------+---------------+
Forgive me if any of these are completely horrible ideas, but I thought it might be an interesting question at least conceptually.
The ideal way, IMO, would be to have a supertype of jobs, projects and subprojects - let's call it activities - on which you could define any common fact types.
For example (I'm assuming jobs, projects and subprojects form a containment hierarchy):
activities (activity PK, activity_name, begin_date, ...)
jobs (job_activity PK/FK, ...)
projects (project_activity PK/FK, job_activity FK, ...)
subprojects (subproject_activity PK/FK, project_activity FK, ...)
Unfortunately, most database schemas define unique auto-incrementing identifiers PER TABLE which makes it very difficult to implement supertyping after data has been loaded. PostgreSQL allows sequences to be reused, which is great, some other DBMSs (like MySQL) don't make it easy at all.
My second choice would be your option 1, since it allows foreign key constraints to be defined. I don't like option 2 at all.
Unfortunately, we have ended up going with the ugliest answer to this, which is to have a notes table for every different type of entry - job_notes, project_notes, and subproject_notes. Our reasons for this were as follows:
A single junction table with a column containing the "type" of junction has poor performance since none of the foreign keys are "real" and must be manually searched. This is compounded by the fact that the Notes field contains a lot of text per entry.
A junction table per entry adds an additional table over simply having separate notes tables for every table type, and while it seems slightly prettier, it does not create substantial performance gains.
I'm not satisfied with this answer, because it seems so wasteful to effectively be duplicating the same Notes table for every job/project/subproject table that is being described. However, we haven't been able to come up with an answer that would hold up performance wise in the long term. I'll leave this open in case anyone has better recommendations for how to do this!

Database design with one giant polymorphic table

I have a MySQL database with many different types that need a lot of the same things. For example, we have tables for reservations, customers, and accounts, and each of these needs EAV-type properties and a set of permission configurations.
My question is: Should I make the EAV and permission implementations polymorphic? So, each reservation, customer, and account gets an entity_id and entity_type_id that can be inserted to the | entity_id | entity_type_id | attribute_id | value | table? There would then be an entities table with | id | entity_type_id | that would need to be inserted whenever a new reservation, customer, or account were created.
Or should I have reservation_eav, customer_eav, accounts_eav tables? We will always know the entity type that we are looking for, so there's no need to return multiple types of entities in a single query. We will, however, need to grab multiple entities of the same type in several cases.
My reason for multiple tables is strictly performance. There's going to be a ton of reservations, not nearly as many accounts, and customers are somewhere in between. Part of me thinks this huge set of reservations will slow down lookups for accounts' / customers' AVs. However, I don't know if the performance advantages will be significant with proper indexing, and I do feel like the single, polymorphic table would make the schema simpler.

Combined or Separate Tables

I have a current database structure that seems to split up some data for indexing purposes. The main tickets table has more "lite" fields such as foreign keys, integers, and dates, and the tickets_info table has the potentially larger data such as text fields and blobs. Is this a good idea to continue with, or should I combine the tables?
For example, the current structure looks something like this (assuming a one-to-one relationship with a foreign key on the indexes):
`tickets`
--------------------------------------------
id | customer | vendor | opened
--------------------------------------------
1 | 29 | 0 | 2013-10-09 12:49:04
`tickets_info`
--------------------------------------------
id | description | more_notes
--------------------------------------------
1 | This thing is broken! | Even longer...
My application does way more SELECTs than INSERTs/UPDATEs, so I can see the theoretical benefit of the splitting when large lists of tickets are queried at once for an overview page (250+ result listings per page). The larger details would then be used on the page that shows just the one ticket and its details with the simple JOIN (amongst the several other JOINS on the foreign keys).
The tables are currently MyISAM, but I am going to convert them to InnoDB once I restructure them if that makes any difference. There are currently about 33 columns in the tickets table and 4 columns in the tickets_info table; the tickets_info table can potentially have more columns depending on the installation ("custom fields" that I have implemented akin to PHPBBv3).
I think this design is fine. The tickets tables is used not only to show single tickets information, but also to do calculation (i.e. total of tickets sold in a specific day) and other analysis (How many tickets sold that vendor?).
Adding the tickets_info will increase the size of you tickets table without any benefits but with the risk to increase access time to the tickets table. I assume good indexing on the tickets table should keep you safe, but MySql is not a columnar database, so I expect that a row with big varchar or blog fields requires more resources.
Beside that if you use the ticket_info for single ticket queries I think you already get good performance when you query that table.
So my suggestion is leave it like it is :)

How can I best structure a link/junction table with a lot of potential columns or repeated rows?

I'm making a site that will be a subscription based service that will provide users several courses based on whatever they signed up for. A single user can register in multiple courses.
Currently the db structure is as follows:
User
------
user_id | pwd | start | end
Courses
-------
course_id | description
User_course_subscription
------------------------
user_id | course_id | start | end
course_chapters
---------------
course_id | title | description | chapter_id | url |
The concern is that with the user_course_subscription table I cannot (at least at the moment I don't know how) I can have one user with multiple course subscriptions (unless I enter the same user_id in multiple times with a different course_id each time). Alternatively I would add many columns in the format calculus_1 chem_1 etc., but that would give me a ton of columns as the list of courses grow.
I was wondering if having the user_id put in multiple times is the most optimal way to do this? Or is there another way to structure the table (or maybe I'd have to restructure all the tables)?
Your database schema looks fine. Don't worry, you're on the right track. As for the User_course_subscription table, both user_id and course_id form the primary key together. This is called a joint primary key and is basically fine.
Values are still unique because no user subscribes to the same course twice. Your business logic code should ensure this anyway. For the database part: You might want to look up in your database system's manual how to set joint primary keys up properly when creating the table (syntax might differ).
If you don't like this idea, you can also create a pseudo primary key, that is having:
user_course_subscription
------------------------
user_course_subscription_id | user_id | course_id | start | end
...where user_course_subscription_id is just an auto-incremented integer. This way, you can use user_course_subscription_id to identify records. This might make things easier in some places of your code, because you don't always have to use two values.
As for heaving calculus_1, chem_1 etc. - don't do this. You might want to read up on database normalization, as mike pointed out. Especially 1NF through 3NF are very common in database design.
The only reason not to follow normal forms is performance, and then again, in most cases optimization is premature. If you're concerned, stress-test the prototype of your appliation under realistic (expected) conditions and measure response times to get some hard evidence.
I don't know what's the meaning of the start and end columns in the user table. But you seem to have no redundancy.
You should check out the boyce-codd normal form wikipedia article. There is a useful example.

Mysql : multiple tables or one big table?

This question has been already asked but I've not found a "1 voice answer".
Is it better to do :
1 big table with :
user_id | attribute_1 | attribute_2 | attribute_3 | attribute_4
or 4 smal tables with :
user_id | attribute_1
user_id | attribute_2
user_id | attribute_3
user_id | attribute_4
1 big table or many small tables ? Each user can only have 1 value for attribute_X. We have a lot of data to save (100 millions users). We are using innoDB. Performance are really important for us (10 000 queries / s).
Thanks !
François
If you adhere to the Zero, One or Many principle, whereby there is either no such thing, one of them, or an unlimited number, you would always build properly normalized tables to track things like this.
For instance, a possible schema:
CREATE TABLE user_attributes (
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
user_id INT NOT NULL,
attribute_name VARCHAR(255) NOT NULL,
attribute_value VARCHAR(255),
UNIQUE INDEX index_user_attributes_name(user_id, attribute_name)
);
This is the basic key-value store pattern where you can have many attributes per user.
Although the storage requirements for this is higher than a fixed-columns arrangement with the perpetually frustrating names like attribute1, the cost is small enough in the age of terabyte-sized hard-drives that it's rarely an issue.
Generally you'd create a single table for this data until insertion time becomes a problem. So long as your inserts are fast, I wouldn't worry about it. At that point you would want to consider a sharding strategy to divide this data into multiple tables with an identical schema, but only if it's required.
I would imagine that would be at the ~10-50 million rows stage, but could be higher if the amount of insert activity in this table is relatively low.
Don't forget that the best way to optimize for read activity is to use a cache: The fastest database query is the one you don't make. For that sort of thing you usually employ something like memcached to store the results of previous fetches, and you would invalidate this on a write.
As always, benchmark any proposed schema at production scale.
1 big table with :
user_id | attribute_1 | attribute_2 | attribute_3 | attribute_4
will make your management easier. Too many individual lookups otherwise, which will also complicate programming against the DB with the chance to increase application errors.