查一次left join没有走索引以及原因分析

 更新时间:2023年03月23日 09:19:23   作者:qq_20009015  
这篇文章主要介绍了查一次left join没有走索引以及原因分析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

查一次left join没有走索引的原因

线上有个查询sql,原来是inner join 查询没有问题,后来应业务要求改成left join之后, 查询时间就暴涨了 需要长达24s

通过explain分析,发现订单表没有走索引 ,分析之后解决了,记录下来。

为了简洁起见,这里就将无关的查询字段都用*

具体sql如下

SELECT  * 
 from t_item_detail a
 left join t_order_detail d on a.order_code=d.order_code
 left join t_connection b on a.unique_code = b.funds_unique 
 left join t_capital_detail c on b.capital_unique = c.unique_code 
 where item_receipt_disbursement=1 and a.is_deleted=0
  and order_type_code=00901 group by a.unique_code LIMIT 10 

用explain命令分析如下

发现table d 的type为all, rows居然高达20万行 。

d对应的表为order_detail 表,type为all 说明并没有走索引。

这里首先看关联条件

from t_item_detail a
 left join t_order_detail d on a.order_code=d.order_code

该条件并无问题,然后这两张表的order_code字段是否加索引.

两张表的order_code字段均有索引。

其次再看, 如果两个字段或者两张表的编码不同,也会导致索引失效。

但是这两张表的编码和字段编码也均相同,因此也排除掉。

最后发现,

如果写成

 explain SELECT  * 
 from t_item_detail a
 left join t_order_detail d on a.order_code=d.order_code  and d.order_type_code=00901
 left join t_connection b on a.unique_code = b.funds_unique 
 left join t_capital_detail c on b.capital_unique = c.unique_code 
 where item_receipt_disbursement=1 and a.is_deleted=0
  group by a.unique_code LIMIT 10 

也就是将原来在where条件的order_type_code=00901 写到left join的条件后面

d的索引就生效了,所有的索引都生效了。

查询时间也从原来的24秒 变成了不到1秒。

这是为什么呢?

其实问题就出在这个 d.order_type_code=00901 这个条件上

当有这个条件时候

全文扫描

没有这个条件的时候

从sql的执行顺序来分析:

SELECT  * 
 from t_item_detail a
 left join t_order_detail d on a.order_code=d.order_code
 left join t_connection b on a.unique_code = b.funds_unique 
 left join t_capital_detail c on b.capital_unique = c.unique_code 
 where item_receipt_disbursement=1 and a.is_deleted=0
  and order_type_code=00901 group by a.unique_code LIMIT 10 

这里面的执行顺序为

  • 1.from
  • 2.on
  • 3.join
  • 4.where
  • 5.select
  • 6.group by
  • 7.limit

写的顺序:select … from… where… group by… having… order by… limit [offset,](rows)

执行顺序:from… where…group by… having… select … order by… limit

知道这个,我们再看这个sql

不走索引 有order_type_code条件

SELECT *
from t_item_detail a
left join t_order_detail d on a.order_code=d.order_code
left join t_connection b on a.unique_code = b.funds_unique
left join t_capital_detail c on b.capital_unique = c.unique_code
where item_receipt_disbursement=1 and a.is_deleted=0
and order_type_code=00901 group by a.unique_code LIMIT 10

走索引 没有order_type_code条件

SELECT *
from t_item_detail a
left join t_order_detail d on a.order_code=d.order_code
left join t_connection b on a.unique_code = b.funds_unique
left join t_capital_detail c on b.capital_unique = c.unique_code
where item_receipt_disbursement=1 and a.is_deleted=0
group by a.unique_code LIMIT 10

和走索引有没有order_type_code条件

SELECT *
from t_item_detail a
left join t_order_detail d on a.order_code=d.order_code and d.order_type_cod=‘00901'
left join t_connection b on a.unique_code = b.funds_unique
left join t_capital_detail c on b.capital_unique = c.unique_code
where item_receipt_disbursement=1 and a.is_deleted=0
group by a.unique_code LIMIT 10

会发现 在不走索引有order_type_code条件的那个sql中, 在执行到where的时候,需要去找到条件 order_type_code=00901 ,但是order_type_code这个字段没有索引,所以数据库就去对order_detail进行全表扫描。

因此解决方案

就是给order_type_code加上索引,或者给 left join on就加上条件order_type_code=xxx ,直接过滤掉

因此,谨记,大表查询的时候,where 的条件千万记得加上索引!!!!

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 浅谈MySQL之浅入深出页原理

    浅谈MySQL之浅入深出页原理

    首先,我们需要知道,页(Pages)是InnoDB中管理数据的最小单元。Buffer Pool中存的就是一页一页的数据。当我们要查询的数据不在Buffer Pool中时,InnoDB会将记录所在的页整个加载到Buffer Pool中去;同样,将Buffer Pool中的脏页刷入磁盘时,也是按照页为单位刷入磁盘的
    2021-06-06
  • 详解mysql跨库查询解决方案

    详解mysql跨库查询解决方案

    本文主要介绍了mysql跨库查询解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • mysql连接过多和死掉以及拒绝服务的解决方法

    mysql连接过多和死掉以及拒绝服务的解决方法

    mysql连接过多和死掉以及拒绝服务的解决方法...
    2007-12-12
  • MySQL8.0.26的安装与简化教程(全网最全)

    MySQL8.0.26的安装与简化教程(全网最全)

    MySQL关是一种关系数据库管理系统,所使用的 SQL 语言是用于访问数据库的最常用的标准化语言,今天通过本文给大家分享MySQL8.0.26的安装与简化教程使全网最详细的安装教程,需要的朋友参考下吧
    2021-07-07
  • Workbench通过远程访问mysql数据库的方法详解

    Workbench通过远程访问mysql数据库的方法详解

    这篇文章主要给大家介绍了Workbench通过远程访问mysql数据库的相关资料,文中通过图文介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-06-06
  • MySQL INNER JOIN 的底层实现原理分析

    MySQL INNER JOIN 的底层实现原理分析

    这篇文章主要介绍了MySQL INNER JOIN 的底层实现原理,INNER JOIN的工作分为筛选和连接两个步骤,连接时可以使用多种算法,通过本文,我们深入了解了MySQL中INNER JOIN的底层实现原理,需要的朋友可以参考下
    2023-06-06
  • MySQL入门(四) 数据表的数据插入、更新、删除

    MySQL入门(四) 数据表的数据插入、更新、删除

    这篇文章主要介绍了mysql数据库中表的插入、更新、删除非常简单,但是简单的也要学习,细节决定成败,需要的朋友可以参考下
    2018-07-07
  • mysql自增ID起始值修改方法

    mysql自增ID起始值修改方法

    本文介绍mysql自增ID的起始值修改与设置方法
    2013-11-11
  • MySQL磁盘碎片整理实例演示

    MySQL磁盘碎片整理实例演示

    这篇文章主要给大家介绍了关于MySQL磁盘碎片整理的相关资料,为什么数据库会产生碎片,以及如何清理磁盘碎片,还有一些清理磁盘碎片的注意事项,需要的朋友可以参考下
    2022-04-04
  • 详细介绍windows下MySQL安装教程

    详细介绍windows下MySQL安装教程

    这篇文章主要给大家介绍的是windows下MySQL安装教程,其实好多公司,数据库的面试题都是不可避免的,甚至一些前端工程师面试的时候都避免不了被询问到和数据库有关的一些问题。下面就从最基础的安装教程开始,需要的朋友可以参考一下
    2021-11-11

最新评论