当需要查询两个表的交集、并集等数据时,除了嵌套子查询的方式外,还可以使用join的方式提升性能。对于MySQL的join语句,需要两个最基础的“角色”:主表即驱动表,关联表即驱动表。join描述的就是驱动表与被驱动表的关联关系。MySQL有三种关联逻辑处理策略,分别为:Index Nested-Loop Join
、Simple Nested-Loop Join
、Block Nested-Loop Join
。在编写SQL时,需要配合explain
使语句选择性能最优的策略。
索引嵌套循环连接,
MySQL
选择驱动表与被驱动表关联逻辑之一。
当使用该策略时,MySQL的执行流程为:
当驱动表关联被驱动表的字段上具有索引时,会使用本策略。在本策略中,驱动表在where条件筛选完毕后,会扫描全表,被驱动表走索引的树搜索。
假设被驱动表共N行数据,对于Index Nested-Loop Join
来说,在查询被驱动表的数据时,会使用二分法进行查找,即时间复杂度为:O(logN),由于每次在被驱动表查一行数据,要先搜索索引再回表搜索,假设驱动表行数是N,执行整个过程复杂度近似:N+N*2*log2M
。
当被驱动表无可用索引时,在驱动表得到一行数据后,需要拿着该数据去被驱动表扫描全表逐行匹配数据,假设驱动表有N行数据,被驱动表有M行数据,那么扫描总行数则为:N*M行。如果驱动表与被驱动表均有十万行数据,则需要扫描100亿行。
当然,MySQL
也没有使用这个Simple Nested-Loop Join
算法,而是使用了另一个叫作“Block Nested-Loop Join”的算法,简称 BNL
。
当被驱动表无可用索引时,算法流程为:
图片引用自极客时间《MySQL实战45讲》。
所以你在判断要不要使用 join 语句时,就是看 explain 结果里面,Extra 字段里面有没有出现“Block Nested Loop”字样。