MySQL子查询慢现象的解决
Jun 07, 2016 pm 04:45 PM当你在用explain工具查看sql语句的执行计划时,若select_type 字段中出现ldquo;DEPENDENT SUBQUERYrdquo;时,你要注意了,你已
当你在用explain工具查看sql语句的执行计划时,若select_type 字段中出现“DEPENDENT SUBQUERY”时,,你要注意了,你已经掉入了mysql子查询慢的“坑"。
相关书籍:高性能MySQL(第3版) 中文PDF带目录清晰版
下面我们来看一个具体的例子
有这样一条查询语句:
SELECT gid,COUNT(id) as count FROM shop_goods g1 WHERE status =0 and gid IN (SELECT gid FROM shop_goods g2 WHERE sid IN (1519066,1466114,1466110,1466102,1466071,1453929))GROUP BY gid;
用explain看了一下,出现关键字“DEPENDENT SUBQUERY”,意味着子查询的第一个select依赖外部的查询;
SUBQUERY:子查询中的第一个SELECT;DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的查询 。
换句话说,就是 子查询对 g2 的查询方式依赖于外层 g1 的查询。它意味着两步:
第一步,MySQL 根据 select gid,count(id) from shop_goods where status=0 group by gid; 得到一个大结果集 t1,其数据量为rows=850672 了;
第二步,上面的大结果集 t1 中的每一条记录,都将与子查询 SQL 组成新的查询语句:select gid from shop_goods where sid in (15...blabla..29) and gid=%t1.gid%。等于说,子查询要执行85万次……即使这两步查询都用到了索引,但不慢才怪;
如此一来,子查询的执行效率居然受制于外层查询的记录数,那还不如拆成两个独立查询顺序执行呢。
对于此类语句一般的优化策略是拆成两个查询语句,你不想拆成两个独立查询的话,也可以与临时表join查询,:
你不想拆成两个独立查询的话,也可以与临时表联表查询,如下所示优化后的sql:
SELECT g1.gid,count(1) FROM shop_goods g1,(select gid from shop_goods WHERE sid in (1519066,1466114,1466110,1466102,1466071,1453929)) g2 where g1.status=0 and g1.gid=g2.gid GROUP BY g1.gid;
用explain看了一下,这次又有了一个新的关键字"DERIVED",意思是用于 from 子句里有子查询的情况。MySQL 会递归执行这些子查询,把结果放在临时表里,然后再做join操作;
DERIVED 的官方含义为:用于 from 子句里有子查询的情况。MySQL 会递归执行这些子查询,把结果放在临时表里。
《高性能MySQL》的第4.4节“MySQL查询优化器的限制(Limitations of the MySQL Query Optimizer)”之第4.4.1小节“关联子查询(Correlated Subqueries)”也有类似的论述:mysql 在处理子查询时,会改写子查询。通常情况下,我们希望由内到外,先完成子查询的结果,然后再用子查询来驱动外查询的表,完成查询。
例如:select * from test where tid in(select fk_tid from sub_test where gid=10);通常我们会感性地认为该 sql 的执行顺序是:sub_test 表中根据 gid 取得 fk_tid(2,3,4,5,6)记录,然后再到 test 中,带入 tid=2,3,4,5,6,取得查询数据。
但是实际mysql的处理方式为:
select * from test where exists (select * from sub_test where gid=10 and sub_test.fk_tid=test.tid);
mysql 将会扫描 test 中所有数据,每条数据都将会传到子查询中与 sub_test 关联,子查询不会先被执行,所以如果 test 表很大的话,那么性能上将会出现问题。
--------------------------------------分割线 --------------------------------------
Ubuntu 14.04下安装MySQL
《MySQL权威指南(原书第2版)》清晰中文扫描版 PDF
Ubuntu 14.04 LTS 安装 LNMP Nginx\PHP5 (PHP-FPM)\MySQL
Ubuntu 14.04下搭建MySQL主从服务器
Ubuntu 12.04 LTS 构建高可用分布式 MySQL 集群
Ubuntu 12.04下源代码安装MySQL5.6以及Python-MySQLdb
MySQL-5.5.38通用二进制安装
--------------------------------------分割线 --------------------------------------
本文永久更新链接地址:

Artikel Panas

Alat panas Tag

Artikel Panas

Tag artikel panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Bagaimanakah bahasa Go melaksanakan operasi penambahan, pemadaman, pengubahsuaian dan pertanyaan pangkalan data?

Tutorial terperinci tentang mewujudkan sambungan pangkalan data menggunakan MySQLi dalam PHP

Perbandingan persamaan dan perbezaan antara MySQL dan PL/SQL

Bagaimanakah Hibernate melaksanakan pemetaan polimorfik?

iOS 18 menambah fungsi album 'Dipulihkan' baharu untuk mendapatkan semula foto yang hilang atau rosak

Analisis prinsip asas sistem pengurusan pangkalan data MySQL

Petua dan amalan untuk mengendalikan aksara Cina bercelaru dalam pangkalan data dengan PHP
