I'm quite new to MySQL and do not really know how to create a good layout for the following setup:
A riddim (rythm) can hold several tunes (songs). A song has the following information/fields: name, artist, label, producer, last modified timestamp, year, lyrics, flag, tag, source.
A riddim has the fields name, last modified, genre, youtube and image.
Here is an illustration for better understanding:
http://img194.imageshack.us/img194/6553/93112345.png
If I put all the information in one table I will have redundant data (such as genre or image), as every row with an artist/tune would have the riddim (rythm) it was sung on in it.
Currently my tables look like the following:
RIDDIMS table:
+---------------+--------------+------+-----+-------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+-------------------+-------+
| riddim | varchar(255) | NO | MUL | NULL | |
| genre | varchar(9) | NO | | NULL | |
| youtube | varchar(11) | NO | | NULL | |
| image | varchar(11) | NO | | NULL | |
| last_modified | timestamp | NO | | CURRENT_TIMESTAMP | |
+---------------+--------------+------+-----+-------------------+-------+
TUNES table:
+---------------+--------------+------+-----+-------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+-------------------+-------+
| riddim | varchar(255) | NO | MUL | NULL | |
| artist | varchar(255) | NO | MUL | NULL | |
| tune | varchar(255) | NO | | NULL | |
| label | varchar(255) | NO | | NULL | |
| producer | varchar(255) | NO | | NULL | |
| year | varchar(4) | NO | | NULL | |
| lyrics | text | NO | | NULL | |
| flag | varchar(12) | NO | | NULL | |
| tag | varchar(255) | NO | | NULL | |
| source | varchar(255) | NO | | NULL | |
| last_modified | timestamp | YES | | CURRENT_TIMESTAMP | |
+---------------+--------------+------+-----+-------------------+-------+
But I'm sure it is not a good layout. Do you guys have suggestions on how the tables/database structure should look like?
Having the 'riddems' and 'tunes' in seperate tables is the right structure to use. Basically model your data as signular objects, if certain fields actually belong to two different objects, it should be in two different tables.
To connect the too tables together, on the table that belongs to the parent table (in this case a riddem has many tunes so tunes belongs to riddem) put a reference to the parents id field. So in this case the tunes table should have a field called 'riddem_id' which is set to the riddem the tune belongs to.
The riddim field of the tunes table should be a foreign key to the primary key of the riddims table. Generally it is not a good idea to use a text field as a primary key unless you are absolutely sure they will be unique. A safer option is to use a field called id, or riddim_id or something, which is a number with the AUTO_INCREMENT property set. That way every new item you add will be given its own unique key automatically. Then you set the foreign key to have the same value as the id of the linked record in the other table.
If you use this structure then you don't need to (and indeed shouldn't) duplicate any data. To find information about the riddim that a tune is in you do a join in a select query.
MySQL is not so different from other relational databases. So if you have some experience working with Oracle, DB2, PostgreSQL you can use it in your design.
In your explanation you did not mention the possible parent-child relations between two tables. Is tunes table a parent of riddim table?
If it is true you have to use riddim field in the riddim table as foreign key pointing to the primary riddim field in the tunes table. You can have multiple riddim records referring to the one tunes record.
It is not obvious for me why image and youtube have 11 characters. If youtune field contains actual URL it needs more characters. Are you going to encode youtube and image fields using enumerators to avoid long strings?
Ask yourself how your typical search is going to perform? What is the most important field
to search for?
I am not sure why you use VARCHAR type for year field.SMALLINT would be sufficient and much more efficient for search as well as for storage. As a rule integer types are much more efficient for search operations.
Related
Today I have seen a video lecture in which they gave the foriegn key by using ADD INDEX on a table -
CASE 1 -
DECRIPTION OF TABLE 1 : subjects
+-----------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| menu_name | int(11) | YES | | NULL | |
| position | int(3) | YES | | NULL | |
| visible | tinyint(1) | YES | | NULL | |
+-----------+------------+------+-----+---------+----------------+
DECRIPTION OF TABLE 2 : pages
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| subject_id | int(11) | YES | | NULL | |
| menu_name | varchar(255) | YES | | NULL | |
| position | int(3) | YES | | NULL | |
| visible | tinyint(1) | YES | | NULL | |
| content | text | YES | | NULL | |
+------------+--------------+------+-----+---------+----------------+
So in the column subject_id of table pages should store the id of table subjects.
Which one should i use and why ? -
ALTER TABLE pages ADD INDEX fk_subject_id (subject_id);
OR
ALTER TABLE pages
ADD FOREIGN KEY (subject_id) REFERENCES students(id);
video lecture uses ALTER TABLE pages ADD INDEX fk_subject_id (subject_id);.
CASE 2 -
Now Please cosider one more example -
According to above details, If I have 5 more tables including pages table(defined above).
All 5 tables have column subject_id which should store the data accodring to column id of table subjects.
So in this case
In this case, Which one Should I use ADD INDEX or FOREIGN KEY and why ?
Q : case 1 - Which one should i use ?
A : I'll choose fk not index,because the reference between pages and subjects is multi to one,if you add index on column with duplicate values that would not be helpful,because in most cases, only one index can be used to optimize a database query,and there's a primary index on subjects,so don't do that again.
note : you have to make pages - subject_id not null
Q : case 2 - Which one should i use ?
A : if the 5 tables between subjects are also multi to one,i'll choose FK not index,the reason like case1's answer.
Using a FOREIGN KEY and an INDEX are different things. FOREIGN KEYs are used for data integrity, so that you cannot have a reference, which points to nothing and that you cannot delete the "base" row without deleting the "linking" rows first (unless you use ON CASCADE DELETE stuff).
Indices are used to improve the search speed to find the correct rows faster in an SELECT and UPDATE query. This has nothing to do with data integrity.
To answer your question: You use a FOREIGN KEY if you want to reference the Id of rows from the other table (like you do with subject_id). Also, you don't need to add an INDEX on the column subject_id, because the InnoDB engine already does that.
i am looking for someone who can help me to achieve a way to store multiple images as a group in mysql.
Basically a user will upload multiple images for example 3 as a group (1 POST), how can i store them in the database.
This is how i store images right now.
+-------------+------------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+-------------------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| userid | int(11) | NO | | NULL | |
| uploaded_at | datetime | YES | | CURRENT_TIMESTAMP | |
| path | varchar(255) | NO | | NULL | |
| is_grouped | int(11) | YES | | 0 | |
| grouped_to | int(11) | YES | | 0 | |
+-------------+------------------+------+-----+-------------------+----------------+
'is_grouped' ( 0 or 1 ) & 'grouped_to' ( id of main image ) are what i though could work but caused problems while retrieving from mysql database.
Any help would be appreciated.
I don't know what exact problem you are having with your current approach, but I would suggest just using the following definition for the images table:
images (id, user_id, uploaded_at, path)
Then, create a junction table which relates images to their groups:
image_groups (image_id, group_id)
We don't really need the is_grouped column any more, because we can simply check image_groups to see if the image appears in a group and/or if that group has more than one image. Similarly, the grouped_to column has now been made redundant because the junction table stores this information. Note that you might also want to have a groups table, which could store some metadata about each image group, such as the name, time of creation, etc.
Let me first explain my situation here , I have a tabled called users which stores the user information.
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| user_id | varchar(10) | NO | PRI | NULL | |
| username | text | NO | | NULL | |
| password | text | NO | | NULL | |
| name | text | NO | | NULL | |
| email | text | NO | | NULL | |
| status | varchar(15) | NO | | active | |
+----------+-------------+------+-----+---------+-------+
And a table called country
+--------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| country_id | varchar(10) | NO | PRI | NULL | |
| country_name | text | NO | | NULL | |
| country_rate | double | NO | | 0.2 | |
+--------------+-------------+------+-----+---------+-------+
Now , I need a process to map the no of countries assigned a particular user.
For Example:
user_001 is allowed to use country_001 , country_002 , country_003 n
user_002 is allowed to use country_003 , country_008
and so on..
What is the best approach to achieve the above?
What I thought is to have a table called say assignment and it will have the following fields:
assignment_id (primary key)
user_id (foreign Key)
country_001 (bool)
country_002 (bool)
...
...
country_010 (bool)
I am not sure if this the best approach , but even if I go for this , I am stuck in the point as to how to alter the structure of assignment , on every insertion in the country table ( Add a BOOL field in assignment with the newly created country_id as the column name).
I hope I was able to explain m situation. I know I can achieve via language support code (PHP , C++ etc) , but I was thinking if this could be done using some kind of TRIGGER so that I don't have to care about it in the code section.
Thanks a Lot.
It would be a better option to define user_countries table like this:
user_id fk on users(user_id)
country_id fk on countries(country_id)
unique key on ( user_id, country_id ) -- composite unique key
I am not sure why you want to define 10 columns in the user-country relation table.
But instead of 10 columns you just define a country_id with a foreign key and
with one-to-many relation ship between user_id and country_id. With this you can easily handle user and country relations. Unique key on their combination makes data access faster and avoids duplicates too.
These are the tables in my database, I need to create a couple superclass/subclass structures.
The first is where...
Superclass-Crew_Member
Subclasses-Director, Producer, Other_Directing, Other_Production, Art, Camera, Sound, Grip, Electrical, Post.
The second is...
Superclass-Producer
Subclasses-Salaries, Budget
+---------------------+
| Tables_in_film_crew |
+---------------------+
| art |
| budget |
| camera |
| crew_member |
| director |
| electrical |
| equipment |
| grip |
| location |
| manufacturer |
| other_directing |
| other_production |
| post_production |
| producer |
| salaries |
| sound |
+---------------------+
So how exactly would I go about creating those relationships?
Edit:
Maybe I should have clarified some other things too.
Here's what's contained in crew_member (Superclass):
+-------------+-------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+-------------------+----------------+
| Member_ID | int(5) | NO | PRI | NULL | auto_increment |
| Member_Name | varchar(25) | YES | | [INSERT EXAMPLE] | |
| DOB | date | YES | | [INSERT EXAMPLE] | |
| Address1 | varchar(25) | YES | | [INSERT EXAMPLE] | |
| Address2 | varchar(25) | YES | | [INSERT EXAMPLE] | |
+-------------+-------------+------+-----+-------------------+----------------+
Meanwhile here's what's contained in Other_Directing (Example Subclass):
+---------------+--------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------+------+-----+---------+----------------+
| O_Director_ID | int(4) | NO | PRI | NULL | auto_increment |
| FAD_ID | int(5) | NO | MUL | NULL | |
| SAD_ID | int(5) | NO | MUL | NULL | |
| SUD_ID | int(5) | NO | MUL | NULL | |
+---------------+--------+------+-----+---------+----------------+
Now all the foreign keys are referring to Member_ID from Crew_Member. All the other tables (except Director and Producer) are created in similar ways.
You could start by following some general rules which have to be taken in consideration when creating a database. Put the information that different groups have in common in 1 table and the specific data in smaller satellite tables.
I would put the generic information about a crew member in the first table:
so we would have an id, name, address and whatever all the members have in common.
Then you create "sub-tables" which relate to the "crew-member" table through the value crew_member_id. In this tables you put only the specific information related to directors, producers etc..
So the fields here might be something like: id, crew_member_id, directed movies, etc..
Even with the superclass producer you should work in the same way. Relate the subtales with the superclass through its primary key to have relations between them.
I would suggest you to read some articles about database designing. It might save your life in the future, cause after a database is made then it becomes much harder to correct mistakes.
http://www.datanamic.com/support/lt-dez005-introduction-db-modeling.html
Yeah this is a really good question, that I was researching as well.
The ideas I came up with were:
1> Have a parent table as the super class with sattelite tables for the attributes for each subclass joined by a foreign key. You could then represent it as a view.
2> Have a parent table as the super class and another single table for all of the extra attributes. This would have to be matched by joined by two foreign keys.
3> One table which holds all of the classes.(Terrible idea)
Theres other ideas but I think the first is the best bet.
Here's more info that suggests the first way.
http://www.tomjewett.com/dbdesign/dbdesign.php?page=subclass.php
I am experimenting with mysql partitioning ( splitting the table up to help it scale better ), and I am having a problem with the keys on the table. First, I am using a python's threaded comments module... here is the schema
+-----------------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+------------------+------+-----+---------+-------+
| content_type_id | int(11) | NO | MUL | NULL | |
| object_id | int(10) unsigned | NO | | NULL | |
| parent_id | int(11) | YES | MUL | NULL | |
| user_id | int(11) | NO | MUL | NULL | |
| date_submitted | datetime | NO | | NULL | |
| date_modified | datetime | NO | | NULL | |
| date_approved | datetime | YES | | NULL | |
| comment | longtext | NO | | NULL | |
| markup | int(11) | YES | | NULL | |
| is_public | tinyint(1) | NO | | NULL | |
| is_approved | tinyint(1) | NO | | NULL | |
| ip_address | char(15) | YES | | NULL | |
| id | int(11) | YES | | NULL | |
+-----------------+------------------+------+-----+---------+-------+
Note, I have modified this database by dropping the id col (primary by default), and re adding it.
Essentially, I want to have id AND content_type_id as my primary keys. I also want id to auto increment. Is this possible.
Second question. Since I am just learning about mysql partitioning, I am wondering if my partitioning logic is sound. There are 67 different content_types, and some (maybe all) of those content types allow comments to be made on them. My plan is to partition based on the type of object that is being commented on. For instance, the images will be commented on a lot, so I put any content type pertaining to images into one partition, and another content type that can be commented on is "blog entries", so there is a separate partition for that, and so on and so on. This will allow me to spread these partitions possibly to dedicated machines as the load grows. How is my understanding of this concept so far?
Thanks so much!
Since id will be auto incremented, it can be the primary key all by itself. Adding content_type to the primary key would not gain you anything in regards to the uniqueness of the key.
If you want to add an index for faster performance to the 2 columns, then add an alternate unique index to the table with the 2 columns instead of trying to add them both to the primary key. However, be aware that enforing uniqueness on the 2 columns would be a waste since id is already guaranteed to be unique by itself, so a regular index would make more sense if needed.