一 介绍
相信许多开发/DBA在使用MySQL的过程中,对于MySQL处理多表关联的方式或者说性能一直不太满意。对于开发提交的含有join的查询,一般比较抗拒,从而建议将join拆分,避免join可能带来的性能问题,同时也增加了程序和DB的网络交互。
5.5 版本之前,MySQL本身只支持一种表间关联方式,就是嵌套循环(Nested Loop)。如果关联表的数据量很大,则join关联的执行时间会非常长。在5.5以后的版本中,MySQL通过引入BNL算法来优化嵌套执行,本文介绍两种join算法 Nested-Loop Join (NLJ) 和Block Nested-Loop Join(BNL) .
二 原理
2.1 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有很多记录,则SimpleNested-Loops Join会扫描内部表很多次,执行效率非常差。
2.2 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 的速度就不会再变快了.
2.3 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算法。
四 参考资料
5.6 版本BNL 支持outer join and semi-join ,并且和其他的特性比如BKA 相关联,后面会写文章整理其他的优化点。
《Nested-Loop Join Algorithms》
《Block Nested-Loop and Batched Key Access Joins》
《mysql的join buffer》
分享到:
相关推荐
MySQL中的Nested-Loop ...总的来说,理解MySQL中的Nested-Loop Join机制对于数据库性能优化至关重要。通过深入理解NLJ的工作原理、变形和优化策略,我们可以更好地设计和调优复杂的SQL查询,提高数据库系统的整体性能。
在React Native开发中,我们经常会遇到需要在一个组件中嵌套多个可滚动视图的情况,这时`react-native-nested-scroll-view`就派上用场了。它是一个针对Android平台的NestedScrollView的React Native封装,旨在解决...
索引嵌套循环联接(INLJ) 该项目是关于使用半流联接(INLJ)实现构建和分析数据仓库原型。 操作数据仓库 数据仓库的操作可以分为三个主要步骤: 创建数据仓库。 使用INLJ算法提取,转换和加载。...
本问题主要讨论了四种不同的联接方式:Nested-loop join、Block nested-loop join、Merge join 和 Hash join,并且分析了它们在不同内存大小(M)下的性能表现,具体涉及的数据是关系r1需要800个block,关系r2需要...
Index Nested-Loop Join(NLJ)是一种利用索引减少I/O次数的Join策略,当被驱动表的字段上有索引时,Join操作的效率较高,因此这也是推荐的做法。然而,如果被驱动表的字段上没有索引,则Join操作将退化为Simple ...
Please use the , vue-draggable-nested-tree will no longer be maintained. 请使用新发布的, vue-draggable-nested-tree 将不再维护. Please use the , vue-draggable-nested-tree will no longer be maintained. ...
在本课件“tutorial9 Join Algorithms.ppt”中,主要讨论了数据库系统中的连接算法,包括Block Nested-Loop Join(块嵌套循环连接)、Indexed Nested-Loop Join(索引嵌套循环连接)以及External Sort-Merge(外部...
《Python库深度解析:drf-nested-resources-1.2b2》 在现代Web开发领域,Python以其简洁明了的语法和强大的生态系统,成为后端开发的重要选择。本篇文章将深入探讨一个特定的Python库——`drf-nested-resources`,...
总结来说,优化JOIN语句不仅仅是选择正确的JOIN算法,如Index Nested-Loop Join (NLJ) 或 Block Nested-Loop Join (BNL),还包括利用数据库内部的优化机制,如MRR,来改善查询性能。理解并合理运用这些优化技术,...
标题中的“PyPI 官网下载 | Nested-List-1.0.4.tar.gz”表明这是一个从Python Package Index(PyPI)官方源下载的软件包,名为“Nested-List”。这个包的版本是1.0.4,且是以tar.gz格式压缩的。这种格式是一种常见的...
**Django-Nested-Admin 深入解析** Django-Nested-Admin 是一个扩展了 Django 自带的 admin 模块的第三方库,它为 Django 的管理界面提供了嵌套内联的功能。在标准的 Django admin 中,内联模型(inline models)...
通过使用以下方法将conda-forge添加到您的通道中,可以从conda-forge通道安装nested-lookup : conda config --add channels conda-forge 启用conda-forge频道后,可以使用以下命令安装nested-lookup : conda ...
ibot-manager-winform-client-v1.0 使用winform打开知识库 ...2.使用winfrom-nested-chromium打开浏览器地址 使用winfrom-nested-chromium打开浏览器地址的有点 1.更宽阔的视野 2.更好的适配性
Laravel开发-eloquent-nested-attributes 嵌套属性允许您通过父级保存关联记录的属性。默认情况下,嵌套属性更新被关闭,您可以使用$nested属性启用它。启用嵌套属性时,将在模型上定义属性编写器。
"nested-fragments-master"这个项目显然专注于深入探讨嵌套Fragment(Nested Fragments)的概念和技术,这是Android SDK提供的一种高级特性,允许在一个Fragment内部嵌套其他Fragment。这种做法可以增加应用的模块化...
资源来自pypi官网。 资源全名:django-nested-formset-0.1.tar.gz
资源分类:Python库 所属语言:Python 资源全名:drf-writable-nested-0.1.2.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
5. **块嵌套循环联接(Block Nested-Loop Join)**:为了解决嵌套循环联接的效率问题,块嵌套循环联接会在内存中一次加载右表的一部分,而不是一行一行地处理。这可以显著提高大表联接的性能。 6. **联接优化**:...