EDIT: I removed the GROUP BY clause from the example queries but the same problem shows \"When I join table x to an empty/1 row table y MySQL makes a full table
The main reason is the misuse of GROUP BY. Let's take the first query. Even though it is "fast", it is still "wrong":
SELECT *
FROM users
LEFT JOIN user_school_mm on users.id = user_school_mm.user_id
GROUP BY users.id
ORDER BY users.id ASC
LIMIT 2
A user can go to two schools. The use of the many:many mapping user_school_mm claims that is a possibility. So, after doing the JOIN, you get 2 rows for a single user. But then, you GROUP BY users.id, to boil it down to a single row. But... Which of the two school_id values should you use??
I am not going to try to address the performance issues until you present queries that make sense. At that point it will be easier to point out why one query performs better than another.