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. 移动端的<meta>标签

    <head> <meta charset="UTF-8" /> <!-- 页面关键词 --> <meta name="keywo ...

  2. bs4 UnicodeEncodeError: 'gbk' codec can't encode character '\xa0'

    Problem: 写爬虫时,出现了以下错误: 意思是Unicode编码错误,gbk编解码器不能编码\xa0字符. 爬取信息包含中文,使用BeautifulSoup库解析网页,用get_text()方法 ...

  3. 域渗透-Kerberos协议中spn的应用

    0x01 关于SPN 服务主体名称(SPN)是Kerberos客户端用于唯一标识给特定Kerberos目标计算机的服务实例名称. 服务主体名称是服务实例(可以理解为一个服务,比如 HTTP.MSSQL ...

  4. 概率图模型(PGM):贝叶斯网(Bayesian network)初探

    1. 从贝叶斯方法(思想)说起 - 我对世界的看法随世界变化而随时变化 用一句话概括贝叶斯方法创始人Thomas Bayes的观点就是:任何时候,我对世界总有一个主观的先验判断,但是这个判断会随着世界 ...

  5. Intellij idea 自动生成serialVersionUID

    1 什么是UID 网络间的数据传输最终都是要转化为二进制流的方式进行传输,为了方便转换以及进行验证,我们应该把对角序列化,当实现Seriabizable接口时,UID就是一个必须的属性,可以方便进行版 ...

  6. H5 video踩坑实录

    前段时间公司APP做了一个APP论坛会议,嵌入了h5播放器.我以为很简单,没想到,这正是我踩进泥潭的开始... (想要吸取经验的小伙伴可以慢慢往下看,想要解决方案的直接看最后!) 一.一开始我以为直接 ...

  7. The usage of Markdown---引用

    目录 1. 序言 2. 引用与嵌套引用 3. 列表中的引用 更新时间:209.09.14 1. 序言   在本篇,我们来仔细谈一下Markdown的引用. 2. 引用与嵌套引用   在Markdown ...

  8. LeetCode 5024 除数博弈 --(简单博弈论)

    今天在LeetCode的看到一到题目 这道题目有点坑,没有思路的话容易钻牛角. 刚刚开始时,我想的是直接用while循环来模拟计算,后来觉得这么好麻烦,也有复制的逻辑在里面.后面我推导了一下 以下是我 ...

  9. ubuntu12.04 添加程序启动器

    方法: 1. 在/usr/share/applications目录下创建eclipse启动器配置文件 cd /usr/share/applications vim eclipse.desktop 2. ...

  10. mysql实现海量数据的存储、访问的解决方案

    mysql实现海量数据的存储.访问的解决方案: mysql数据库水平切分的实现原理可分为以下几个:分库,分表,主从,集群,负载均衡器等 第1章 引言 随着互联网应用的广泛普及,海量数据的存储和访问成为 ...