詹俊直播的欧洲杯决赛

admin · 2004-09-01

序论

  民众好,我是捡田螺的小男孩。(求个星标置顶)

  著作开篇前,先问民众一个题目:delete in子盘问,能否会走索引呢?良众搭档第一感受便是:会走索引。迩来咱们有个分娩题目,就跟它相合。本文将跟民众沿途研究这个题目,并附上优化计划。

  

   题目复现

  MySQL版本是5.7,假定如今有两张外account和old_account,外布局如下:

  

CREATETABLE`old_account`(`id`int(11)NOTNULLAUTO_INCREMENTCOMMENT主键Id,`name`varchar(255)DEFAULTNULLCOMMENT账户名,`balance`int(11)DEFAULTNULLCOMMENT余额,`create_time`datetimeNOTNULLCOMMENT创修时代,`update_time`datetimeNOTNULLONUPDATECURRENT_TIMESTAMPCOMMENT更新时代,PRIMARYKEY(`id`),KEY`idx_name`(`name`)USINGBTREE)ENGINE=InnoDBAUTO_INCREMENT=1570068DEFAULTCHARSET=utf8ROW_FORMAT=REDUNDANTCOMMENT=老的账户外;CREATETABLE`account`(`id`int(11)NOTNULLAUTO_INCREMENTCOMMENT主键Id,`name`varchar(255)DEFAULTNULLCOMMENT账户名,`balance`int(11)DEFAULTNULLCOMMENT余额,`create_time`datetimeNOTNULLCOMMENT创修时代,`update_time`datetimeNOTNULLONUPDATECURRENT_TIMESTAMPCOMMENT更新时代,PRIMARYKEY(`id`),KEY`idx_name`(`name`)USINGBTREE)ENGINE=InnoDBAUTO_INCREMENT=1570068DEFAULTCHARSET=utf8ROW_FORMAT=REDUNDANTCOMMENT=账户外;

 

  推广的SQL如下:

  

deletefromaccountwherenamein(selectnamefromold_account);

 

  咱们explain推广安插走一奔忙,

  

  从explain了局能够发明:先全外扫描 account,而后逐行推广子盘问判定前提能否餍足;明白,这个推广安插和咱们预期不相符,由于并无走索引。

  然而即使把delete换成select,就会走索引。如下:

  

  为甚么select in子盘问会走索引,delete in子盘问却不会走索引呢?

   因为判辨

  select in子盘问语句跟delete in子盘问语句的分歧点真相正在那边呢?

  咱们推广如下SQL看看

  

explainselect*fromaccountwherenamein(selectnamefromold_account);showWARNINGS;

 

  show WARNINGS 能够检查优化后,终极推广的sql

  了局如下:

  

select`test2`.`account`.`id`AS`id`,`test2`.`account`.`name`AS`name`,`test2`.`account`.`balance`AS`balance`,`test2`.`account`.`create_time`AS`create_time`,`test2`.`account`.`update_time`AS`update_time`from`test2`.`account`semijoin(`test2`.`old_account`)where(`test2`.`account`.`name`=`test2`.`old_account`.`name`)

 

  能够发明,现实推广的光阴,MySQL对select in子盘问做了优化,把子盘问改为join的形式,因而能够走索引。然而很缺憾,看待delete in子盘问,MySQL却没有对它做这个优化。

   优化计划

  那怎样优化这个题目呢?经由过程下面的判辨,明白能够把delete in子盘问改为join的形式。咱们改为join的形式后,再explain看下:

  

  能够发明,改用join的形式是能够走索引的,完满处理了这个题目。

  现实上,看待update或许delete子盘问的语句,MySQL官网也是推举join的形式优化

  

  原本呢,给外加一名,也能够处理这个题目哦,如下:

  

explaindeleteafromaccountasawherea.namein(selectnamefromold_account)

   为甚么加局部名就能够走索引了呢?

  what?为啥加局部名,delete in子盘问又行了,又走索引了?

  咱们回过火来看看explain的推广安插,能够发明Extra那一栏,有个LooseScan。

  

  LooseScan是甚么呢? 原本它是一种战术,是semi join子盘问的一种推广战术。

  由于子盘问改为join,是可让delete in子盘问走索引;加一名呢,会走LooseScan战术,而LooseScan战术,实质上便是semi join子盘问的一种推广战术。

  以是,加一名便可让delete in子盘问走索引啦!

   总结

  本博文判辨了delete in子盘问不走索引的因为,并附上处理计划。delete in正在平时开垦,口角时常睹的,平日民众作事中,须要谨慎一下。同时呢,倡议民众作事的光阴,写SQL的光阴,只管即便养成一个好民俗,先用explain判辨一下SQL。

  本文具体思绪参考共事的博文,曾经颠末他自己赞成。也倡议民众遭遇题目时,众点思索,众点写写总结,防止重蹈覆辙。

  我是捡田螺的小男孩,码字不易,看完著作有成果的话,能够把我公家号推给身旁的步调员哈,感动、比心~

  本文转载自微信公家号「捡田螺的小男孩」,能够经由过程如下二维码存眷。转载本文请合系捡田螺的小男孩公家号。

  

文章推荐:

2022 年中国人工智能行业发展现状与市场规模分析 市场规模超 3000 亿元

该来的总要来! 切尔西老板将彻底退出英国市场

雷神黑武士四代开售:i7搭RTX3060不到9千元

智慧城市中 5G 和物联网的未来