Seriously look at third normal form. I would use surrogate keys with the natural keys implemented as unique keys. You will likely find that author belongs in its own authors table. You may find you have a few tables which are quite similar such as user_content_faves, user_author_faves, user_author_shares. This is normal.
Having a single content table with a content_type column may be appropriate. The content column would need to be capable of storing all the content types.
EDIT: For relationship tables I usually name the join table by concatenating the names of the joined tables, abbreviating as necessary. If there multiple relationships between the two tables, I use one of two options:
- Append the purpose of the relationship (as I did above); or
- Add a type/reason code to the relationship (in which case the type is not needed in the relationship name).
I made the assumption that you would want to track who favorited or shared things. It appears that both the producer (author or user) as well as the content items. Therefore you have users favoriting a producer (user_author_faves now user_user_faves), or a product (user_content_faves). Depending on how you do sharing,
- it could be an attribute on the content, or
- a relationship like user_content_shares, where content is share with a particular user. Re-sharing could be problematic, if you track who shared things, and multiple users share the same content to the same user. Un-sharing re-shared items is problematic if you don't track who did the sharing.
You may want to consider (and set policies for):
- tracking/audit information like when something was done (added, favorited, shared, etc).
- whether to do physical or logical deletes.
- if you do logical deletes how to handle refavoriing or sharing something after a logical delete.
When indexing relationship tables I generally have the primary key consisting of the primary keys of the two tables being joined. A second index with the primary keys reversed, or just the primary key which is the second column in the primary key is usually required. If the relationship between two rows can occur more than once, the column(s) used to differentiate the reason/type and/or timing (since date) of the relationship needs to added to the primary key.
Look at this line
[OK] Key buffer size / total MyISAM indexes: 250.0G/131.6G
The sum of all your MyISAM indexes is 131.6G
You should lower key_buffer_size to 140G. This will give back 110G.
I have a little suggestion for you. You may want to consider using a dedicate keycache for each large table. See my Nov 16, 2012
post Cache all mysql table
Look at this line
[!!] InnoDB data size / buffer pool: 2.2G/2.0G
innodb_buffer_pool_size could be raised to 2560M (That's 2.5G)
Look at these lines
read_buffer_size=2G
sort_buffer_size = 2G
Why is so big? If you change both of these to 32M, you can increase max_connections. In fact, do the following right now:
SET @ThrityTwoMeg = 1024 * 1024 * 32
SET GLOBAL read_buffer_size = @ThrityTwoMeg;
SET GLOBAL sort_buffer_size = @ThrityTwoMeg;
SET GLOBAL join_buffer_size = @ThrityTwoMeg;
Then, go rerun mysqltuner.pl
and you will see a dramatic difference from 4.1G per thread
BTW go change join_buffer_size
to 32M in my.cnf
Give it a Try !!!
UPDATE 2013-04-11 16:53 EDT
I just thought of another change you can make to increase SELECT speed against MyISAM tables. For every MyISAM you need to read a lot from, do this to the table:
ALTER TABLE mydb.mytable ROW_FORMAT=Fixed;
Believe it or not, this will bloat the table 80-100% in size, but SELECTs will go 20-25% faster. I have written about this many times. Here is just few of my posts:
Best Answer
This is called a cartesian product or a
CROSS JOIN
: