5.5 版本之前,MySQL本身只支持一种表间关联方式,就是嵌套循环(Nested Loop)。如果关联表的数据量很大,则join关联的执行时间会非常长。在5.5以后的版本中,MySQL通过引入BNL算法来优化嵌套执行
Nested Loop Join
       NLJ 算法:将驱动表/外部表的结果集作为循环基础数据,然后循环从该结果集每次一条获取数据作为下一个表的过滤条件查询数据,然后合并结果。如果有多表join,则将前面的表的结果集作为循环数据,取到每行再到联接的下一个表中循环匹配,获取结果集返回给客户端。
Nested-Loop 的伪算法如下:

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
}
}
}

因为普通Nested-Loop一次只将一行传入内层循环, 所以外层循环(的结果集)有多少行, 内存循环便要执行多少次.在内部表的连接上有索引的情况下,其扫描成本为O(Rn),若没有索引,则扫描成本为O(Rn*Sn)。如果内部表S有很多记录,则Simpl eNested-Loops Join会扫描内部表很多次,执行效率非常差。

Block Nested-Loop Join
       BNL 算法:将外层循环的行/结果集存入join buffer, 内层循环的每一行与整个buffer中的记录做比较,从而减少内层循环的次数.
       举例来说,外层循环的结果集是100行,使用NLJ 算法需要扫描内部表100次,如果使用BNL算法,先把对Outer Loop表(外部表)每次读取的10行记录放到join buffer,然后在InnerLoop表(内部表)中直接匹配这10行数据,内存循环就可以一次与这10行进行比较, 这样只需要比较10次,对内部表的扫描减少了9/10。所以BNL算法就能够显著减少内层循环表扫描的次数.
       前面描述的query, 如果使用join buffer, 那么实际join示意如下:

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
}
}
}

如果t1, t2参与join的列长度只和为s, c为二者组合数, 那么t3表被扫描的次数为
(S * C)/join_buffer_size + 1
扫描t3的次数随着join_buffer_size的增大而减少, 直到join buffer能够容纳所有的t1, t2组合, 再增大join buffer size, query 的速度就不会再变快了

  • MySQL使用Join Buffer有以下要点:

1. join_buffer_size变量决定buffer大小。
2. 只有在join类型为all, index, range的时候才可以使用join buffer。
3. 能够被buffer的每一个join都会分配一个buffer, 也就是说一个query最终可能会使用多个join buffer。
4. 第一个nonconst table不会分配join buffer, 即便其扫描类型是all或者index。
5. 在join之前就会分配join buffer, 在query执行完毕即释放。
6. join buffer中只会保存参与join的列, 并非整个数据行。

  • 如何使用

5.6版本及以后,优化器管理参数optimizer_switch中中的block_nested_loop参数控制着BNL是否被用于优化器。默认条件下是开启,若果设置为off,优化器在选择 join方式的时候会选择NLJ算法。

最新文章

  1. Cordova 3.x入门 - 目录
  2. Linux 内核数据结构:Linux 双向链表
  3. Android 向系统日历中添加事件
  4. Kernel Methods (6) The Representer Theorem
  5. Xcode 8 : iOS xib is missing from working copy、iOS misssing file
  6. Oulipo(poj 3461)
  7. 如何把项目部署到OSChina上
  8. python学习笔记3-celery分布式任务处理器
  9. Python_sklearn机器学习库学习笔记(三)logistic regression(逻辑回归)
  10. 解决yum错误Error: requested datatype primary not available
  11. Service解析
  12. HDU 4544 湫湫系列故事――消灭兔子
  13. Git总结笔记3-把本地仓库推送到github
  14. CRMEB系统开发文档
  15. python多进程multiprocessing模块中Queue的妙用
  16. Linux中DDNS配置
  17. span i s等行内元素标签之间出现奇怪空格符号
  18. openssl 交叉编译
  19. 【ContestHunter】【弱省胡策】【Round6】
  20. java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing,

热门文章

  1. 使用LinQ进行增删改查
  2. H5 动画:轨迹移动 | H5游戏 推金币
  3. JS正则表达式从入门到入土(10)—— 字符串对象方法
  4. 关于文件中的0D、0A
  5. [翻译]理解CSS模块方法
  6. Elasticsearch之中文分词器
  7. [源码解读] ResNet源码解读(pytorch)
  8. jQuery实现输入框提示,当获取焦点时提示消失,当失去焦点时内容为空则显示提示,否则保留输入信息
  9. 谈一谈URL
  10. javascript 跨域访问