sql优化核心 是数据库中 解析器+优化器的工作,我觉得主要有以下几个大方面:
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方式的更多相关文章

  1. SQL多表连接查询

    SQL多表连接查询 本文主要列举两张和三张表来讲述多表连接查询. 新建两张表: 表1:student  截图如下: 表2:course  截图如下: (此时这样建表只是为了演示连接SQL语句,当然实际 ...

  2. 【转】图解SQL的各种连接join

    原帖地址:http://www.nowamagic.net/librarys/veda/detail/936 图解SQL的各种连接join 让你对SQL的连接一目了然 在 2011年12月22日 那天 ...

  3. sql server 表连接

    本文主要列举两张和三张表来讲述多表连接查询. 新建两张表: 表1:student 截图如下: SQL多表连接查询(详细实例)_新客网 表2:course 截图如下: SQL多表连接查询(详细实例)_新 ...

  4. 性能调优7:多表连接 - join

    在产品环境中,往往存在着大量的表连接情景,不管是inner join.outer join.cross join和full join(逻辑连接符号),在内部都会转化为物理连接(Physical Joi ...

  5. sql优化的8种方式 (下)

    五.条件列表值如果连续使用between替代in        六.无重复记录的结果集使用union all合并 MySQL数据库中使用union或union all运算符将一个或多个列数相同的查询结 ...

  6. SQL的表连接

    每天给自己扫盲,让自己变得越博学. 继续学习<程序员的SQL金典>,这回我们来看看表连接相关的内容.表连接的相关知识在实际的项目开发当中,使用非常广. 所谓表连接,就是通过关联多张表,从而 ...

  7. SQL多表连接查询(详细实例)

    转载博客:joeleo博客(http://www.xker.com/page/e2012/0708/117368.html) 本文主要列举两张和三张表来讲述多表连接查询. 新建两张表: 表1:stud ...

  8. SQL多表连接

    在KS系统中分配好权限以后,在用户登录的时候就要通过用户查到角色,通过角色查到界面,界面又属于某个菜单,一共要查4个表.并且不能有重复的记录这个时候就用到了SQL的内连接.SQL的多表连接很方便,以前 ...

  9. 表连接join on

    表A记录如下:  aID aNum  1 a20050111  2 a20050112  3 a20050113  4 a20050114  5 a20050115  表B记录如下:  bID bNa ...

随机推荐

  1. mysql的存储过程与事务入门

    存储过程是:通过一系列的SQL语句, 根据传入的参数(也可以没有), 通过简单的调用, 完成比单个SQL语句更复杂的功能, 存储在数据库服务器端,只需要编译过一次之后再次使用都不需要再进行编译.主要对 ...

  2. 【swoole2.0】 PHP + swoole2.0 初体验

    背景: centos7   PHP7.1   swoole2.0 准备工作: 一.  swoole  扩展安装 1 下载swoole cd /usr/local wget -c https://git ...

  3. 查询sql server 2008所有表和行数

    查询sql server 2008所有表和行数 SELECT a.name, b.rows FROM sysobjects AS a INNER JOIN sysindexes AS b ON a.i ...

  4. Qt获取CPU编号和硬盘序列号

    windows下执行命令除了用cmd之外,还有个东西叫WMIC,非常强大,可以通过他获取很多信息,包括硬件信息. QString frmMain::getWMIC(const QString & ...

  5. SVN —— 如何设置代理

    如果在使用SVN下载外网的资源时,出现这样的提示:No such host is known. 或者 不知道这样的主机,可能是机器网络的问题. 如果浏览器能够正常访问外网,那应该是网络设置了代理的问题 ...

  6. Karma和Jasmine自动化单元测试

    从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发.Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎.chrome浏 ...

  7. jQuery事件处理(五)

    对原生js不熟悉看jQuery会困难很多.后续需要更多的关注下原生js jQuery封装之后的事件触发,其中一个分支(处理普通事件)是通过:elem.addEventListener( type, e ...

  8. LeetCode 46 Permutations(全排列问题)

    题目链接:https://leetcode.com/problems/permutations/?tab=Description   Problem:给出一个数组(数组中的元素均不相同),求出这个数组 ...

  9. linux常用命令大全3--rpm安装软件

    RPM 包 - (Fedora, Redhat,CentOS及类似系统) rpm -ivh package.rpm 安装一个rpm包 rpm -ivh --nodeeps package.rpm 安装 ...

  10. 使用 Gogs 搭建自己的 Git 服务器

    安装过程分为这些步骤: 新建用户: 下载源码编译 / 下载预编译二进制打包: 运行安装: 配置调整: 配置 nginx 反向代理: 保持服务运行: 注意,这里默认你已经安装好了 MySQL 服务器和 ...