This is a good "there's more than one way to do it" question.
Start by thinking about your data usage:
Think about which fields are going to be read and written more often.
For example, first name and last name are probably written once and are rarely changed, but depending on your app, they could be read very often.
Last login date could be written frequently, and you might want to keep every login date.
Things like activation key and registration date, depending on how authentication works in your app, might be written once and then very rarely read.
You should also think about what data is pulled at the same time, and try to denormalize to make those reads faster. For example, if you are always pulling username and password and first name together (but no other contact info), put firstname in the login table, too. That is, think about avoiding joins if this data will be large, and be kind to yourself.
Also think about which fields might be in the "where" clause of your queries, and index on those fields.
Here's one way I might do it:
Contact Table
(one insert, rare updates, many reads)
+------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------------+------+-----+---------+----------------+
| user_id | int(11) | NO | PRI | NULL | auto_increment |
| first_name | varchar(50) | NO | | NULL | |
| last_name | varchar(50) | NO | | NULL | |
| address | varchar(50) | NO | | NULL | |
| city | varchar(50) | NO | | NULL | |
| state | varchar(50) | NO | | NULL | |
| country | varchar(50) | NO | | NULL | |
| email | varchar(1024) | NO | | NULL | |
+------------+---------------+------+-----+---------+----------------+
Login Table
(one insert, maybe updates, many reads; need first_name to be echoed on login)
+------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------------+------+-----+---------+----------------+
| user_id | int(11) | NO | PRI | NULL | |
| username | varchar(32) | NO | | NULL | |
| password | varchar(32) | NO | | NULL | |
| first_name | varchar(50) | NO | | NULL | |
+------------+---------------+------+-----+---------+----------------+
Login History Table
(many writes, multiple entries per user_id)
+------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------------+------+-----+---------+----------------+
| user_id | int(11) | NO | MUL | NULL | |
| last_login | timestamp | NO | MUL | NULL | |
+------------+---------------+------+-----+---------+----------------+
Signup Table
(one write, rarely read)
+------------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+---------------+------+-----+---------+----------------+
| user_id | int(11) | NO | PRI | NULL | |
| registration_date| timestamp | NO | | NULL | |
| activation_key | varchar(50) | NO | | NULL | |
+------------------+---------------+------+-----+---------+----------------+
Best Answer
If you want to save space, you can use the
"char"
data type. It stores a single byte.you can cast
integer
ortext
to"char"
:An enum uses 4 bytes since it is internally stored as a
real
.What you are out to save space, you'll have to take alignment into account. The values are always aligned according to the type alignment. For example, a
bigint
always has to start at an address that is divisible by 8.Now if your table is defined as
there will be 7 padding bytes between the columns, which would render all the space gains from
"char"
moot.So place your table columns carefully.