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. Spring Cloud之Hystrix

    在微服务架构中,存在那么多的服务单元,若一个单元出现故障(由于网络原因或者自身原因),就很容易因依赖关系而引发故障的蔓延,最终导致整个系统的瘫痪,这样的架构相较传统架构更加不稳定.为了解决这样的问题, ...

  2. ACM-图论-同余最短路

    https://www.cnblogs.com/31415926535x/p/11692422.html 一种没见过的处理模型,,记录一下,,主要是用来处理一个多元一次方程的解的数量的问题,,数据量小 ...

  3. 洛谷 1552 [APIO2012]派遣

    题目背景 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿. 题目描述 在这个帮派里,有一名忍者被称之为Master.除了Master以外,每名忍者都有且仅有一个上级.为保密 ...

  4. Python3 解决 ModuleNotFoundError: No module named 'pygal.i18n' 问题

    在获取国别码集通过导入模块pygal报以下问题: from pygal.i18n import COUNTRIES  解决方法: 安装模块 pip3 install pygal_maps_world ...

  5. requests模块(get请求)篇

    - HTTP for Humans,更简洁更友好- 继承了urllib的所有特征- 底层使用的是urllib3- 开源地址: https://github.com/requests/requests- ...

  6. SpringCloud教程二:Ribbon(Finchley版)

    在上一篇文章,讲了服务的注册和发现.在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于http restful的.Spring cloud有两种服务调用方式,一种是ribbon+r ...

  7. 《java编程思想》P140-P160(第七章复部+第八章部分)

    1.不用修饰符 修饰的方法或类,它们的修饰符是 默认修饰符,即 包访问权限(包内都可以用)(临时记的) 2. final数据: 对于基本类型,final使数值恒定不变,而对于对象引用,final使引用 ...

  8. django渲染高阶

    08.16自我总结 django渲染高阶 一.利用母版渲染 1.创建母版文件 如:stamper.html <!DOCTYPE html> <html lang="en&q ...

  9. 特征真的越多越好吗?从特征工程角度看“garbage in,garbage out”

    1. 从朴素贝叶斯在医疗诊断中的迷思说起 这个模型最早被应用于医疗诊断,其中,类变量的不同值用于表示患者可能患的不同疾病.证据变量用于表示不同症状.化验结果等.在简单的疾病诊断上,朴素贝叶斯模型确实发 ...

  10. gulp——用自动化构建工具增强你的工作流程

    想要使用gulp,就要了解gulp,就像追自己的爱豆,你要知道爱豆的喜好.兴趣 简单的了解你的新爱豆———安装nodejs -> 全局安装gulp -> 项目安装gulp以及gulp插件 ...