Cities and States (a few data): single table or splitted?
CHAR(2) CHARACTER SET latin1 takes only 2 bytes.  You are not going to improve significantly on that by using an id TINYINT UNSIGNED (1 byte) to 'normalize' it.

Splitting into 2 tables is something I call "over-normalizing".

JOINs are pretty cheap, but they are not free.  This is a disadvantage of the 2-table approach.

While you are asking this question, I suggest you implement it both ways, see how big the tables are, see how fast the queries are, etc.  Use it as a learning exercise.

Yes, there will be other cases where 2 tables is better.