The first syntax is usually more efficient.
MySQL buffers derived queries, so using a derived query causes user_profile to be a slave table in a join.
Even if user_profile leads, the results of the subquery must first be buffered, which implies the effect of memory and performance.
A LIMIT applied to queries will make the first query much faster, which does not match the second.
Here is an example of plans. The t_source table has an index on (val, nid) :
First request:
EXPLAIN SELECT * FROM t_source s1 JOIN t_source s2 ON s2.nid = s1.id WHERE s2.val = 1 1, 'SIMPLE', 's1', 'ALL', 'PRIMARY', '', '', '', 1000000, '' 1, 'SIMPLE', 's2', 'ref', 'ix_source_val,ix_source_val_nid,ix_source_vald_nid', 'ix_source_val_nid', '8', 'const,test.s1.id', 1, 'Using where'
Second request:
EXPLAIN SELECT * FROM t_source s1 JOIN ( SELECT nid FROM t_source s2 WHERE val = 1 ) q ON q.nid = s1.id 1, 'PRIMARY', '<derived2>', 'ALL', '', '', '', '', 100000, '' 1, 'PRIMARY', 's1', 'ref', 'PRIMARY', 'PRIMARY', '4', 'q.nid', 10000, 'Using where' 2, 'DERIVED', 's2', 'ref', 'ix_source_val,ix_source_val_nid,ix_source_vald_nid', 'ix_source_vald_nid', '4', '', 91324, 'Using index'
As you can see, in the second case only part of the index is used, and q is the leading one.
Update:
Derived queries (regarding this issue) should not be confused with subqueries.
While MySQL cannot optimize derived queries (those used in the FROM ), subqueries (those used with IN or EXISTS ) are handled much better.
See these blog posts for more details: