8.2.1.10 Nested-Loop Join Algorithms 嵌套循环算法:

8.2.1.10 Nested-Loop Join Algorithms 嵌套循环算法:

8.2.1.10 Nested-Loop Join Algorithms 嵌套循环算法:

MySQL 在表之间执行关联使用一个嵌套循环算法:

嵌套循环算法:

一个简单的嵌套关联算法从循环中的第一个表中读取记录, 传递每行给嵌套循环来处理下一个表在关联里,

这个过程是重复很多次的 ,因为还有顺下的表被关联起来。

假设一个关联在表t1,t2,t3 被执行使用下面的关联类型:

Table Join Type
t1 range
t2 ref
t3 ALL

如果一个简单的NLJ 算法被使用,关联被处理如下:

for each row in t1 matching range {
for each row in t2 matching reference key {
for each row in t3 {
if row satisfies join conditions,
send to client
}
}
}

因为嵌套算法传递从外部循环到内部循环,它通常是读取表处理在内部循环很多次。

块嵌套循环算法:

一个块嵌套(BNL) 关联算法使用缓存记录在外部循环读取,来降低内部循环的次数。

比如,如果10条记录被读入到buffer,buffer 被传递到下一个内部循环,

每个记录从内部循环读取可以和buffer 中的10条记录匹配。

MySQL 使用关联buffer 在下面条件:

join_buffer_size 系统变量决定每个关联buffer 的大小:

Join buffering 可以被用于当关联类型是ALL或者Index(换句话说,当没有索引可以读取,就做全表扫描)

或者range 在MySQL 5.6,buffer的使用被扩展应用于外部链接

一个Buffer是被分配给每个关联 ,可以缓存的, 因此给定一个查询可以使用多个join buffers 处理

一个join buffer 永远不会分配给第一个非常量表, 即使它的类型是ALL或者index

join buffer 被有限分配来执行关联,在每次查询完成后释放

只有关联敢兴趣的行被存储在join buffer,不是整条记录。

前面的关联例子描述的嵌套循环算法(没有buffering):

for each row in t1 matching range {
for each row in t2 matching reference key {
store used columns from t1, t2 in join buffer
if buffer is full {
for each row in t3 {
for each t1, t2 combination in join buffer {
if row satisfies join conditions,
send to client
}
}
empty buffer
}
}
}

if buffer is not empty {
for each row in t3 {
for each t1, t2 combination in join buffer {
if row satisfies join conditions,
send to client
}
}
}

如果S 是每次存储的t1的大小,t2 组合是关联buffer,C是 在buffer中组合的次数,表t3的扫描次数如下:

(S * C)/join_buffer_size + 1