第一种语法通常更高效。
MySQL
缓冲派生查询,因此使用派生查询会剥夺user_profile
作为连接中的驱动表的可能性。
即使user_profile
是主导表,子查询结果也应首先进行缓冲,这意味着会对内存和性能产生影响。
对查询应用LIMIT
将使第一个查询速度更快,而对第二个查询则不适用。
以下是示例计划。在表t_source
中有一个索引(val, nid)
:
第一个查询:
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'
第二个查询:
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'
正如您所看到的,第二种情况只使用了索引的一部分,并且q
被强制成为前导。
更新:
派生查询(这是此问题所涉及的内容)不应与子查询混淆。
虽然MySQL
无法优化派生查询(在FROM
子句中使用的查询),但子查询(在IN
或EXISTS
中使用的查询)则得到了更好的处理。
有关更多详细信息,请参见我的博客中的这些文章: