当前位置: 首页 > news >正文

mysql如何执行关联查询与优化

  mysql如何执行关联查询与优化

一、前言

  在数据库中执行查询(select)在我们工作中是非常常见的,工作中离不开CRUD,在执行查询(select)时,多表关联也非常常见,我们用的也比较多,那么mysql内部是如何执行关联查询的呢?它又做了哪些优化呢?今天我们就来揭开mysql关联查询的神秘面纱。

二、mysql如何执行关联查询

  mysql关联执行的策略很简单:mysql对任何关联都执行嵌套循环关联操作。即:mysql先在一个表中循环取出单条数据,然后再嵌套循环到下一个表中寻找匹配的行,依次下去,直到找到所有表中匹配的行为止。然后根据各个表匹配的行,返回查询中需要的各个列。如果mysql在最后一个关联表无法找到更多的行,它将返回上一层关联表,看看能否找到更多的匹配记录,以此类推迭代执行。

  按照这种方式,mysql查找第一个表的记录,再嵌套查询下一个关联表,然后回溯到上一个表,这正如其名——“嵌套循环关联”。看一下下面的例子:

SELECT
    t1.column1,
    t2.column2
FROM
    tb1 t1
INNER JOIN tb2 t2 ON t1.column3 = t2.column3
WHERE
    t1.column1 IN (4, 6)

  假设mysql按照查询中的表顺序进行关联操作,我们可以用伪代码表示其过程:

outer_iter = iterator over t1 WHERE    column3 IN (4, 6) 
outer_row = outer_iter.next
WHILE outer_row 
    inner_iter = iterator over t2    WHERE    column3 = outer_row.column3
    inner_row = inner_iter.next
    WHILE inner_row 
        output [ outer_row.column1,inner_row.column2 ] 
        inner_row = inner_iter.next
    END 
    outer_row = outer_iter.next
END

  上面的执行过程对于单表查询和多表关联查询都适用,如果只是单表查询,那么只需要完成最外层的循环操作即可。如果关联中存在外连接,上面的过程仍然适用,我们只需略作修改。查询sql如下:

SELECT
    t1.column1,
    t2.column2
FROM
    tb1 t1
LEFT OUTER JOIN tb2 t2 ON t1.column3 = t2.column3
WHERE
    t1.column1 IN (4, 6)

  对应的伪代码修改如下:

outer_iter = iterator over t1 WHERE    column3 IN (4, 6) 
outer_row = outer_iter.next
WHILE outer_row 
    inner_iter = iterator over t2    WHERE    column3 = outer_row.column3
    inner_row = inner_iter.next
        IF inner_row
            WHILE inner_row 
                    output [ outer_row.column1,inner_row.column2 ] 
                    inner_row = inner_iter.next
            END 
        ELSE
            output [ outer_row.column1,NULL ] 
        END
    outer_row = outer_iter.next
END

  如果用图表示关联查询的过程,图示如下,请从左至右,从上至下看这幅图:

t1t2结果行
column1=4,column3=1column3=1,column2=1column1=4,column3=1
 column3=1,column2=2column1=4,column3=2
 column3=1,column2=3column1=4,column3=3
column1=6,column3=2column3=2,column2=1column1=6,column3=1
 column3=2,column2=2column1=6,column3=2
 column3=2,column2=3column1=6,column3=3

  mysql的关联方式也可以由一棵树表示,它是一个左侧深度优先树:
                              

三、关联查询优化器

  mysql优化器最重要的一部分就是关联查询优化,它决定了多个表关联时的顺序。通常多表关联的时候,可以有多种不同的关联顺序来获得相同的结果。关联查询优化器则通过评估不同顺序时的成本来选择一个代价最小的关联顺序。

  大家看一下下面的查询,它可以通过不同的关联顺序得到相同的结果:

SELECT
    u.realname,
    u.mobile,
    c.`name`
FROM
    USER u
INNER JOIN user_company uc ON u.id = uc.user_id
INNER JOIN company c ON uc.company_id = c.id

  按照上面的关联执行规则,我们可以给出执行计划,mysql可以从user表开始,通过user_company表的user_id列找到对应的company_id,然后再通过company表的主键找到对应的记录。我们执行了mysql的explain,得出的结果如下:

          

  这和我们给出的执行顺序不一致,这样的效率是否更高呢?我们使用STRAIGHT_JOIN关键字得出的分析结果如下:

          

  我们分析一下mysql为什么会改变关联的顺序,我们可以看到改变顺序后,第一个关联表只需要扫描很少的行数,第二个、第三个关联表的扫描项也是不同的。uc表只有480条记录,而u表有2300条记录。如果先扫描uc表,只返回480条记录,然后进行嵌套循环查询,如果先扫描u表,则返回2300条记录。换句话说,更改顺序后,查询可以进行更少的嵌套循环和回溯操作。

  通过这个例子,我们可以看到mysql是如何选择合适的顺序让查询执行的成本更低的。重新定义关联顺序是优化器的一个重要的功能,它尝试在所有关联顺序中选择一个成本最小的来生成执行计划树。

  至此,mysql是如何进行关联查询的,以及优化,已经介绍完了,欢迎大家多多交流。

 

转载于:https://www.cnblogs.com/boboooo/p/8257798.html

相关文章:

  • HP C7000刀片服务器实战3:Redhat Linux 6.8操作系统安装
  • webview 设置夜间模式
  • 004 Ubuntu上安装truffle
  • 2.windows下安装git
  • 【Java】List转化为数组
  • HyperLedger Fabric ChainCode开发——shim.ChaincodeStubInterface用法
  • python之元组
  • lsyncd实时同步搭建指南——取代rsync+inotify
  • 互相牵制的能力
  • 正则介绍_grep
  • J2EE
  • 编写按键驱动以及在framework层上报按键事件
  • sed工具
  • 【.Net边角料系列】1-单例模式(我真不是你想的那样)
  • 【CodeForces】713 C. Sonya and Problem Wihtout a Legend
  • Akka系列(七):Actor持久化之Akka persistence
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • CEF与代理
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • ES学习笔记(12)--Symbol
  • JAVA SE 6 GC调优笔记
  • JAVA并发编程--1.基础概念
  • mysql 数据库四种事务隔离级别
  • vuex 笔记整理
  • 从setTimeout-setInterval看JS线程
  • 对象管理器(defineProperty)学习笔记
  • 基于HAProxy的高性能缓存服务器nuster
  • 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
  • 微信开放平台全网发布【失败】的几点排查方法
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • 责任链模式的两种实现
  • ​Java并发新构件之Exchanger
  • ​LeetCode解法汇总518. 零钱兑换 II
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • #预处理和函数的对比以及条件编译
  • (12)Hive调优——count distinct去重优化
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (pojstep1.3.1)1017(构造法模拟)
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (力扣题库)跳跃游戏II(c++)
  • (一)u-boot-nand.bin的下载
  • (转)C#调用WebService 基础
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法
  • .gitignore文件---让git自动忽略指定文件
  • .MyFile@waifu.club.wis.mkp勒索病毒数据怎么处理|数据解密恢复
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .NET 中各种混淆(Obfuscation)的含义、原理、实际效果和不同级别的差异(使用 SmartAssembly)
  • .NET 自定义中间件 判断是否存在 AllowAnonymousAttribute 特性 来判断是否需要身份验证
  • .net连接oracle数据库
  • .net企业级架构实战之7——Spring.net整合Asp.net mvc
  • ;号自动换行
  • [ Linux 长征路第二篇] 基本指令head,tail,date,cal,find,grep,zip,tar,bc,unname
  • [16/N]论得趣