sql优化 表连接join方式
1>扫表的方法(索引非索引、主键非主键、书签查、索引下推)
2>关联表的方法(三种),关键是内存如何利用
3>处理排序聚合的方法,如何利用内存
即 少扫磁盘多用内存
--=====2 表关联方式
-----0 概述
类别 Nested Loop Hash Join Merge Join
使用条件 任何条件 等值连接(=) 等值或非等值连接(>,<,=,>=,<=),‘<>’除外
相关资源 CPU、磁盘I/O 内存、临时空间 内存、临时空间
Nested Loop 优点: 当有高选择性索引或进行限制性搜索时效率比较高,能够快速返回第一次的搜索结果。
缺点: 当索引丢失或查询条件限制不够时,效率低;当表纪录数多时,效率低
实现: 从一张表中读取数据,访问另一张表(通常是索引)来做匹配,nested loops适用的场合是当一个关联表比较小的时候,效率会更高
Hash Join 优点: 当无索引或索引条件模糊时,Hash Join比Nested Loop有效。通常比Merge Join快。在数据仓库环境下,如果表的纪录数多,效率高
缺点: 为建立哈希表,需要大量内存。第一次的结果返回较慢
实现: 将一个表(通常是小一点的那个表)做hash运算,将列数据存储到hash列表中,从另一个表中抽取记录,做hash运算,到hash 列表中找到相应的值,做匹配。
Merge Join 优点: 当无索引或索引条件模糊时,Merge Join比Nested Loop有效。非等值连接时,Merge Join比Hash Join更有效
缺点: 所有的表都需要排序。它为最优化的吞吐量而设计,并且在结果没有全部找到前不返回数据
实现: 先将关联表的关联列各自做排序,然后从各自的排序表中抽取数据,到另一个排序表中做匹配,因为merge join需要做更多的排序,所以消耗的资源更多
通常来讲,能够使用merge join的地方,hash join都可以发挥更好的性能
选择什么连接类型有以下三要素:
1) 表大小
2) 连接列是否有索引
3) 连接列是否要排序
不同DBMS对表连接的支持:
1) SqlServer, Oracle支持以下三种连接
2) Mysql5.5前支持NestedLoop,之后支持对其的优化算法Block Nested-Loop
-----1 Nested Loop Join
驱动表(outer table),另一个为inner table,驱动表中的每一行与inner表中的相应记录JOIN。类似一个嵌套的循环。适用于驱动表的记录集比较小(<10000)且inner表的连接列上要有Index。
注意:驱动表的记录集一定要小,inner表的连接列要有(UniqueIndex更好)索引。处理过程伪代码:
for oi in count(outer table 行数):do
for ii in count(inner table 行数):do --若inner连接列有主键索引,则不用循环inner表,也不需要回表,效率超高
if oi.column=ii.column:do --若只是普通索引,还需要回表查相应数据(可能需要大量的随机IO),可能会慢许多,但也比没索引强
Send To Client
fi
done
done
--Block Nested-Loop Join(仅Mysql支持)
因为普通Nested-Loop一次只将一行传入内层循环, 所以outer table (的结果集)有多少行, 内存循环便要执行多少次.
在inner table的连接上有索引的情况下,其扫描成本为O(Rn),若没有索引,则扫描成本为O(Rn*Sn)。如果inner table有很多记录,则Nested-Loops Join会扫描内部表很多次,执行效率会非常差。
BNL算法:将outer table结果集存入join buffer, 内层循环的每一行与整个Join buffer中的记录做比较,从而减少内层循环的次数。
举例,outer table结果集是100行,使用NLJ 需扫描内部表100次,如使用BNL,先把Outer Loop表每次读取的10行记录放到join buffer,然后在InnerLoop表中直接匹配这10行数据,
内存循环就可以一次与这10行进行比较, 这样只需要比较10次,对内部表的扫描减少了9/10。所以BNL算法就能够显著减少内层循环表扫描的次数.
MySQL使用Join Buffer有以下要点:
当MySQL的 Join 有使用到 Block Nested-Loop Join,那么调大变量join_buffer_size 才是有意义的。而前面的 Index Nested-Loop Join如果仅使用索引进行Join,那么调大这个变量则毫无意义
a) 只有在join类型为all, index, range的时候才可以使用join buffer。
b) 能够被buffer的每一个join都会分配一个buffer, 也就是说一个query最终可能会使用多个join buffer。
c) 第一个nonconst table不会分配join buffer, 即便其扫描类型是all或者index。
d) 在join之前就会分配join buffer, 在query执行完毕即释放。
e) join buffer中只会保存参与join的列, 并非整个数据行。
f) 5.6版本及以后,优化器管理参数optimizer_switch中的block_nested_loop控制着BNL是否被用于优化器。默认条件下是开启,若果设置为off,优化器在选择 join方式的时候会选择NLJ算法。
-----2 Hash Join
将两表中较小的在内存中构造一个HASH表(只对连接列),扫描另一个表,同样对JOIN KEY进行HASH后探测是否可以JOIN。适用于记录集比较大的情况。
需要注意的是:如果HASH表太大,无法一次构造在内存中,则分成若干个partition,写入磁盘的temporary segment,则会多一个写的代价,会降低效率
-----3 Sort Merge Join
通常情况下Hash Join的效果都比排序合并连接要好,然而如果行源已经被排过序,在执行排序合并连接时不需要再排序了,这时排序合并连接的性能会优于散列连接。
可以使用USE_MERGE(table_name1 table_name2)来强制使用排序合并连接.
Sort Merge join 用在没有索引,并且数据已经排序的情况.
将两个表排序,然后将两个表合并。通常情况下,只有在以下情况发生时,才会使用此种JOIN方式:
1.RBO模式 且 HASH_JOIN_ENABLED=false
2.不等价关联(>,<,>=,<=,<>)
3.数据源已排序
sql优化 表连接join方式的更多相关文章
- SQL多表连接查询
SQL多表连接查询 本文主要列举两张和三张表来讲述多表连接查询. 新建两张表: 表1:student 截图如下: 表2:course 截图如下: (此时这样建表只是为了演示连接SQL语句,当然实际 ...
- 【转】图解SQL的各种连接join
原帖地址:http://www.nowamagic.net/librarys/veda/detail/936 图解SQL的各种连接join 让你对SQL的连接一目了然 在 2011年12月22日 那天 ...
- sql server 表连接
本文主要列举两张和三张表来讲述多表连接查询. 新建两张表: 表1:student 截图如下: SQL多表连接查询(详细实例)_新客网 表2:course 截图如下: SQL多表连接查询(详细实例)_新 ...
- 性能调优7:多表连接 - join
在产品环境中,往往存在着大量的表连接情景,不管是inner join.outer join.cross join和full join(逻辑连接符号),在内部都会转化为物理连接(Physical Joi ...
- sql优化的8种方式 (下)
五.条件列表值如果连续使用between替代in 六.无重复记录的结果集使用union all合并 MySQL数据库中使用union或union all运算符将一个或多个列数相同的查询结 ...
- SQL的表连接
每天给自己扫盲,让自己变得越博学. 继续学习<程序员的SQL金典>,这回我们来看看表连接相关的内容.表连接的相关知识在实际的项目开发当中,使用非常广. 所谓表连接,就是通过关联多张表,从而 ...
- SQL多表连接查询(详细实例)
转载博客:joeleo博客(http://www.xker.com/page/e2012/0708/117368.html) 本文主要列举两张和三张表来讲述多表连接查询. 新建两张表: 表1:stud ...
- SQL多表连接
在KS系统中分配好权限以后,在用户登录的时候就要通过用户查到角色,通过角色查到界面,界面又属于某个菜单,一共要查4个表.并且不能有重复的记录这个时候就用到了SQL的内连接.SQL的多表连接很方便,以前 ...
- 表连接join on
表A记录如下: aID aNum 1 a20050111 2 a20050112 3 a20050113 4 a20050114 5 a20050115 表B记录如下: bID bNa ...
随机推荐
- C语言中如何计算时间差
#include <time.h> #include <stdio.h> int main() { time_t start ,end ; ...
- 微信小程序的wx-charts插件
还有就是可以使用一些小程序的插件,比如wx-charts. 先来看一下网上对这个插件的评价: 目前在github上有1804颗星,使用的比较广泛. github地址:https://github.co ...
- 简析iOS动画原理及实现——Core Animation
本文转载至 http://www.tuicool.com/articles/e2qaYjA 原文 https://tech.imdada.cn/2016/06/21/ios-core-animati ...
- Linux IPC BSD Pipe
mkfifo() //创建有名管道(FIFO special file),创建完了就像普通文件一样open(),再读写,成功返回0,失败返回-1设errno.VS$man 3 mkfifo #incl ...
- 微信小程序源码案例大全
微信小程序demo:足球,赛事分析 小程序简易导航 小程序demo:办公审批 小程序Demo:电魔方 小程序demo:借阅伴侣 微信小程序demo:投票 微信小程序demo:健康生活 小程序demo: ...
- 【HubbleDotNet】HubbleDotNet配置安装注册key获取
今天配置HubbleDotNet发现一个问题 安装界面需要注册key 点击[get key],跳转网页: http://www.hubbledotnet.com/key.aspx 结果网页有bug,坑 ...
- canvas - drawImage()方法绘制图片不显示的问题
canvas有个很强大的api是drawImage()(w3c): 他的主要功能就是绘制图片.视频,甚至其他画布等. 问题: 慕名赶来,却一脚踩空,低头一看,地上一个大坑. 事情是这样的,在我看完 ...
- GTID与MHA
MHA 基于binlog文件位置的复制 * Phase 3: Master Recovery Phase.. * Phase 3.1: Getting Latest Slaves Phase.. La ...
- 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十八:SDRAM模块① — 单字读写
实验十八:SDRAM模块① — 单字读写 笔者与SDRAM有段不短的孽缘,它作为冤魂日夜不断纠缠笔者.笔者尝试过许多方法将其退散,不过屡试屡败的笔者,最终心情像橘子一样橙.<整合篇>之际, ...
- File类使用
简介 File类的实例代表了一个文件或者一个目录,通过API可以获取这个对象的相关信息. File类代表的文件或者目录可以真实存在,也可以是不存在的,可以使用File.exists()来判断. 在Wi ...