0、导读

有个采用子查询的DELETE执行得非常慢,改写成SELECT后执行却很快,最后把这个子查询DELETE改写成JOIN优化过程

1、问题描述

朋友遇到一个怪事,一个用子查询的DELETE,执行效率非常低。把DELETE改成SELECT后执行起来却很快,百思不得其解。

下面就是这个用了子查询的DELETE了:

[yejr@imysql.com]mydb > EXPLAIN delete from trade_info where id in (

select id from (

select a.id from trade_info a, order_info b, user c where

b.buyer = c.id and c.itv_account=’90000248′ and a.order_id = b.id) temp)\G

几个表的DDL是这样的:

上面这个SQL的执行耗时是:31.74秒

Query OK, 5 rows affected (31.74 sec)

如果我们把DELETE改写成SELECT的话,执行耗时仅是:0秒,来对比看下执行计划:

[yejr@imysql.com]mydb >EXPLAIN select id from trade_info where

id in (

select id from (

select a.id from trade_info a, order_info b, user c where

b.buyer = c.id and c.itv_account=’90000248′ and a.order_id = b.id) temp)\G

可以看到,trade_info 表从的全表扫描(type=ALL)变成了基于主键的等值查询(type=eq_ref),计划扫描数据量也从571万变成了1条,而且还可以避免回表,这2个SQL对比代价相差巨大。

2、优化思路

既然这个SQL把DELETE改成SELECT后执行效率就可以获得很大提升,除此外没特别区别,可能是查询优化器方面有些不足,导致无法直接优化,就得另想办法了。

我们的思路是把基于子查询的DELETE简化改写成多表JOIN后DELETE(一般来说,子查询效率比较低的话,可以考虑改写成JOIN),多表DELETE的语法课参考:https://dev.mysql.com/doc/refman/5.7/en/delete.html#idm140469624466800,例如这样的:

DELETE t1 FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;

参照上面的形式,改写之后的SQL变成了下面这样:

DELETE trade_info

FROM

trade_info,

(

SELECT

a.id

FROM

trade_info a

JOIN order_info b ON a.order_id = b.id

JOIN user c ON b.buyer = c.id

WHERE

c.itv_account = ‘90000248’

) t2 where trade_info.id = t2.id;

可以看到新的SQL执行效率相对就高很多了,不需要再扫描571万条记录,执行耗时只需:0.01秒。

Query OK, 5 rows affected (0.01 sec)

3、其他建议

虽然MySQL 5.6及以上的版本对子查询做了优化,但从本案例的结果来看,在一些情况下还是不如意。

因此,如果发现有些子查询SQL效率比较差的话,可以尝试改写成JOIN形式,看看是否有所提升。此外,也要勇于怀疑查询优化器个别情况下存在不足,想办法绕过这些坑。

优化系列 | DELETE子查询改写优化的更多相关文章

  1. MySQL 子查询(四)子查询的优化、将子查询重写为连接

    MySQL 5.7 ref ——13.2.10.10优化子查询 十.子查询的优化 开发正在进行中,因此从长远来看,没有什么优化建议是可靠的.以下列表提供了一些您可能想要使用的有趣技巧.See also ...

  2. paip.sql索引优化----join 代替子查询法

    paip.sql索引优化----join 代替子查询法 作者Attilax ,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn.n ...

  3. MySQL子查询的优化

    本文基于MySQL5.7.19测试 创建四张表,pt1.pt2表加上主键 mysql> create table t1 (a1 int, b1 int); mysql> create ta ...

  4. 【SqlServer系列】子查询

    1   概述 1.1  已发布[SqlServer系列]文章 [SqlServer系列]SQLSERVER安装教程 [SqlServer系列]数据库三大范式 [SqlServer系列]表单查询 [Sq ...

  5. [慢查优化]慎用MySQL子查询,尤其是看到DEPENDENT SUBQUERY标记时

    案例梳理时间:2013-9-25 写在前面的话: 在慢查优化1和2里都反复强调过 explain 的重要性,但有时候肉眼看不出 explain 结果如何指导优化,这时候还需要有一些其他基础知识的佐助, ...

  6. mysql update/delete in 子查询改写

    #子查询(不支持) limit ,); #改写 limit ,) t ; #子查询(不支持) delete from `user` where id in ( ) ); #改写 delete from ...

  7. mysql优化---in型子查询,exists子查询,from 型子查询

    in型子查询引出的陷阱:(扫更少的行,不要临时表,不要文件排序就快) 题: 在ecshop商城表中,查询6号栏目的商品, (注,6号是一个大栏目) 最直观的: mysql); 误区: 给我们的感觉是, ...

  8. Mysql查询优化器之关于子查询的优化

    下面这些sql都含有子查询: mysql> select * from t1 where a in (select a from t2); mysql> select * from (se ...

  9. mysql5.6子查询的优化

    https://dev.mysql.com/doc/refman/5.6/en/subquery-optimization.html Semi-join in MySQL 5.6   MySQL 5. ...

随机推荐

  1. POJ - 3281 Dining(拆点+最大网络流)

    Dining Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 18230   Accepted: 8132 Descripti ...

  2. gdb 断点调试C程序

    最近在看CS50的公开课,视频中david用gdb调试C,我跟着敲,一样的代码但是却显示效果与他不一样.因为他的程序是编译好了的,所以也没看到编译步骤,后来回想一下他make 文件名 显示的代码中有一 ...

  3. 更新svn时出错,大概的意思是项目被锁定了

  4. ie8 不支持 position:fixed 的简单解决办法

    今天发现使用 position:fixed 的页面在firefox下没有问题,在IE8下却不能正常显示,在网上找了找,有不少相关文章,但是不是不起作用就是太复杂,后来终于发现一个简单的解决办法,就是在 ...

  5. jdbc 接口学习笔记

    一.JDBC概念 JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系型数据库提供统一访问,它由一组用Jav ...

  6. BZOJ 3727 DP?推式子..

    思路: 设$sum[i]表示i的子树中a[i]的和$ $b[1]=\Sigma a[i]*dis[i] = \Sigma _{i=2} ^n sum[i]$ $b[x]-b[fa[x]]=sum[1] ...

  7. Y - Anton and Letters

    Problem description Recently, Anton has found a set. The set consists of small English letters. Anto ...

  8. Jquery 获取父页面下指定iframe里的指定元素

    var div1=$("#iframe1",window.parent.document).contents().find("#div1");

  9. 前端编码规范(2)HTML 规范

    文档类型 推荐使用 HTML5 的文档类型申明: <!DOCTYPE html> (建议使用 text/html 格式的 HTML.避免使用 XHTML.XHTML 以及它的属性,比如 a ...

  10. Project Management -- How to use GitHub with Git

    如何通过Git使用GitHub ——PM曾子轩 从未使用过Git 一.从官网下载Git 此部分略 二.用Git连接上GitHub(为保持完整性,此部分引用博客:https://www.cnblogs. ...