join语句的两种算法,分别是:NLJ和BNL

测试数据:

create table t1(id int primary key, a int, b int, index(a));
create table t2 like t1;
drop procedure idata;
delimiter ;;
create procedure idata()
begin
declare i int;
set i=1;
while(i<=1000)do
insert into t1 values(i, 1001-i, i);
set i=i+1;
end while; set i=1;
while(i<=1000000)do
insert into t2 values(i, i, i);
set i=i+1;
end while; end;;
delimiter ;
call idata();

Multi-Range Read优化

MRR的设计思路就是:大多数数据都是按照主键递增的顺序插入得到的,所以我们可以认为,如果按照主键的递增顺序查询的话,多磁盘的读比较接近于顺序读,能够提升读的性能。
此时,执行语句将会变成这样:
  1. 根据索引a,定位满足条件的记录,将id值放入read_rnd_buffer中;
  2. 将read_rnd_buffer中的id进行递增排序
  3. 排序后的id数组,依次到主键 id索引中查找记录,并作为结果返回。
如果我们想稳定低使用MRR优化的话,需要设置set optimizer_switch="mrr_cost_based =off"参数
总结一下:MRR的核心就是,这条查询语句在索引a上做的是一个范围查询(多值查询),可以得到足够多的主键id,这样通过排序后,再去主键索引差数据,才能体现出“顺序性”

Batched key Access优化

MySQL在5.6版本后,引入了BKA算法,其实就是对NLJ算法的优化
NLJ的逻辑是,从驱动表t1,逐行取出a的值,再到驱动表t2去做join。
我们可以把表t1 的数据取出来一部分,先放到一个临时内存中,这个临时内存就是join_buffer
启动BKA算法的参数是:

set optimizer_switch='mrr=on,mrr_cost_based=off,batched_key_access=on';

BNL性能优化

在通常情况下,我们可以直接在被驱动表上建立索引,这样就可以将BNL算法成NLJ算法了。但是有一些被驱动表不适合做索引,例如:
select * from t1 join t2 on (t1.b=t2.b) where t2.b>=1 and t2.b<=2000;

这句SQL表示,在经过where条件过滤,需要参与join的只有2000行数据。如果这条数据是一个低频的SQL,那么在为表t2建立一个字段b的索引,就很浪费了。
但是如果我们使用BNL算法,那么我们首先会将表t1存入join_buffer,然后扫描表t2与join_buffer中的数据进行比对,这里的数据是指所有的数据。这个判断等值条件的次数是1000*100万=10亿次。

这个时候,我们可以考虑使用临时表来优化,大致的思路是:
  1. 把表中t2满足条件的数据,先放在临时表tmp_t中;
  2. 为了让join可以使用BKA算法, 给临时表tmp_t的字段加上索引
  3. 让临时表和t1做join操作
create temporary table temp_t(id int primary key, a int, b int, index(b))engine=innodb;
insert into temp_t select * from t2 where b>=1 and b<=2000;
select * from t1 join temp_t on (t1.b=temp_t.b);

此时,可以明显看出,速度快了很多。
总结:
在被驱动表的字段上加索引
创建临时表,在临时表中加索引

hash join

我们可以自己在业务段,创建hash结构,然后将数据读出来,自己进行数组的匹配和数组集的组装。也可以提高join的性能。

总结:

BKA优化是MySQL内置支持的,建议使用
BNL效率低,建议转成BKA算法
临时表的方案,对于能提前过滤出小数据的join语句来说,效果很好
hash join的效果也是很好的,基于内存计算,路论上效果优于临时表

你知道如何优化Join语句吗?的更多相关文章

  1. 优化join语句

    Mysql4.1开始支持SQL的子查询.这个技术可以使用SELECT语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查询中.使用子查询可以一次性的完成很多逻辑上需要多个步骤才能完成的 ...

  2. 35 | join语句怎么优化?

    在上一篇文章中,我和你介绍了 join 语句的两种算法,分别是 Index Nested-Loop Join(NLJ) 和 Block Nested-Loop Join(BNL). 我们发现在使用 N ...

  3. 如何用 SQL Tuning Advisor (STA) 优化SQL语句

    在Oracle10g之前,优化SQL是个比较费力的技术活,不停的分析执行计划,加hint,分析统计信息等等.在10g中,Oracle推出了自己的SQL优化辅助工具: SQL优化器(SQL Tuning ...

  4. Expert 诊断优化系列------------------语句调优三板斧

    前面三篇通过CPU.内存.磁盘三巨头,讲述了如何透过现在看本质,怎样定位服务器三巨头反映出的问题.为了方便阅读给出链接: SQL SERVER全面优化-------Expert for SQL Ser ...

  5. ORACLE常用SQL优化hint语句

    在SQL语句优化过程中,我们经常会用到hint,现总结一下在SQL优化过程中常见Oracle HINT的用法: 1. /*+ALL_ROWS*/ 表明对语句块选择基于开销的优化方法,并获得最佳吞吐量, ...

  6. mysql优化SQL语句的一般步骤及常用方法

    一.优化SQL语句的一般步骤 1. 通过show status命令了解各种SQL的执行频率 mysqladmin extended-status 或: show [session|global]sta ...

  7. 在优化SQL语句中使用虚拟索引

    定义:虚拟索引(virtual index) 是指没有创建对应的物理段的索引. 虚拟索引的目的:是在不损耗主机CPU,IO,磁盘空间去实际创建索引的情况下,来判断一个索引是否能够对SQL优化起到作用. ...

  8. mysql性能优化之数据库级别优化--优化sql语句

    一  优化SELECT语句 1.1 WHERE子句优化 本文暂时只讨论可以处理WHERE子句的优化,下面的一些实例使用SELECT语句,但是相同的优化同样适用DELETE和UPDATE语句中的WHER ...

  9. 022:SQL优化--JOIN算法

    目录 一. SQL优化--JOIN算法 1.1. JOIN 写法对比 2. JOIN的成本 3. JOIN算法 3.1. simple nested loop join 3.2. index nest ...

随机推荐

  1. 一个最简单的springboot

    现在项目里使用springboot,平时开发并不太关注springboot的一些基本配置,现在想整理一下springboot相关内容. 实际开发中都会因为各种业务需求在springboot上添加很多东 ...

  2. XSS中的同源策略和跨域问题

    转自 https://www.cnblogs.com/chaoyuehedy/p/5556557.html 1 同源策略 所谓同源策略,指的是浏览器对不同源的脚本或者文本的访问方式进行的限制.比如源a ...

  3. Debian更新源加安装Metespolit&&Cobalt Strike

    首先更新下源 修改/etc/apt/sources.list文件 再apt-get update deb http://mirrors..com/debian/ stretch main non-fr ...

  4. Cocos2d-x 学习笔记(11.1) MoveBy MoveTo

    1. MoveBy MoveTo 两方法都是对node的平移,MoveBy是相对当前位置的移动.MoveTo是By的子类,是移动到世界坐标位置. 1.1 成员变量和create方法 MoveBy的主要 ...

  5. linux使用jq工具解析json

    jq类似一个awk或grep一样的神器,可以方便地在命令行操作json 这里我使用海南万宁的天气接口做演示,地址:http://t.weather.sojson.com/api/weather/cit ...

  6. PAT-1022 Digital Library (30 分) 字符串处理

    A Digital Library contains millions of books, stored according to their titles, authors, key words o ...

  7. Leetcode(7)整数反转

    Leetcode(6)Z字形变换 [题目表述]: 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 第一次:转字符串处理 执行用时:40 ms: 内存消耗:11.6MB 效果: ...

  8. .NET Core3.0 日志 logging

    多年的经验,日志记录是软件开发的重要组成部分.没有日志记录机制的系统不是完善的系统.在开发阶段可以通过debug附件进程进行交互调试,可以检测到一些问题,但是在上线之后,日志的记录起到至关重要的作用. ...

  9. vue 开发插件流程

    UI demo UI 插件汇总 我的github iSAM2016 在练习写UI组件的,用到全局的插件,网上看了些资料.看到些的挺好的,我也顺便总结一下写插件的流程: 声明插件-> 写插件-&g ...

  10. unity 基于scrollRect实现翻页显示

    unity 基于scrollRect实现翻页显示,并定为到某一页,而不是某一页的中间方法(第二个脚本采用实际位置计算,并在update里实现平滑过渡): 组场景时,经常需要获取鼠标(或者点击)开始结束 ...