这个原则不只是写 SQL 语句需要遵循,我们平时写代码的时候也要尽量遵循这个原则。比如写双层 for 循环的时候,尽量把循环次数小的那个 for 放在外层而循环次数多的放在内层,这样就可以减少从内外侧循环切换的次数,减少一些性能消耗。
举个例子,两个 for 循环,一个要循环10次一个要循环100次,当然不管两个循环怎么组合最终都是一共要循环1000次,但是如果把循环10次的放在外层,那么就从外层循环跳到内层循环的次数就只要10次,反之要100次。所以把循环次数少的那个 for 循环放在外面可以减少栈帧的切换次数从而提升性能。
回到 SQL 场景中就是当存在子查询的时候,把数据量大的表放在子查询里而数据量小的表放在主查询里。当然可能有的场景下我们就是必须得把大表放在主查询里,因为我们需要的字段在大表里,那么这时候我们就可以使用 exists 和 in 这两个关键词来做一些转换来提升 SQL 语句的效率了:
首先说一下 in和exists的区别:
select * from t1 where exists(select id from t2 where id=t1.id);
复制代码
反例:
select * from t1 where id in (select id from t2);
复制代码
正例之所以是推荐的写法是因为 exists后面跟了大表,此时子查询可以使用 t2 表的 id 列的索引来提高查询效率,外层是一个小表,内层又可以使用索引来加速查询,所以总体效率较高;而反例之所以不推荐是因为 in 后面跟了大表,所以这个大表会被整个查询一遍和t1做笛卡尔积,很显然没有正例的效率高。 大表在外层时:
正例:
select * from t2 where id in (select id from t1);
复制代码
反例:
select * from t2 where exists(select id from t1 where id=t2.id);