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