Mysql必读mysql嵌套查询、联表查询的优化详解
《Mysql必读mysql嵌套查询、联表查询的优化详解》要点: MYSQL必读本节内容: MYSQL必读在不考虑特殊的情况下,联表查询要比嵌套查询更有效. MYSQL必读有如下的情况: MYSQL必读创建表的语句: ??? id int not null primary key,? ??? category int not null,? ??? index(category)? ) engine=InnoDB;? ? create table item(? ??? id int not null auto_increment primary key,? ??? subcategory int not null,? ??? index(subcategory)? ) engine=InnoDB;? MYSQL必读又往表里面填入一些样本数据 ??? select i,i/100 from number? ??? where i <= 300000;? ? insert into item(subcategory)? ??? select id? ??? from (? ??????? select id,rand() * 20 as num_rows from subcategory? ??? ) as x? ??????? cross join number? ??? where i <= num_rows;? ? create temporary table t as? ??? select subcategory from item? ??? group by subcategory? ??? having count(*) = 19? ??? limit 100;? ? insert into item (subcategory)? ??? select subcategory? ??? from t? ??????? cross join number? ??? where i < 2000;? MYSQL必读这些语句运行完需要一点时间,不适合放在产品环境中运行. MYSQL必读要求:找出某个category中item数大于2000的全部subcategory. MYSQL必读查询语句: from subcategory as c? ??? inner join item as i on i.subcategory = c.id? group by c.id? having count(*) > 2000;? ? -- choose one of the results,then? select * from subcategory where id = ????? -- result: category = 14? MYSQL必读拿到一个合适的值14,在以下的查询中会用到它. from subcategory as c? ??? inner join item as i on i.subcategory = c.id? where c.category = 14? group by c.id? having count(*) > 2000;? MYSQL必读在样例数据中,查询的结果有10行记录,而且只用10多秒就完成了. MYSQL必读假设要从subcategory取出全部的字段. where id in (? ??? select c.id? ??? from subcategory as c? ??????? inner join item as i on i.subcategory = c.id? ??? where c.category = 14? ??? group by c.id? ??? having count(*) > 2000? );? ? MYSQL必读注意:以上这条查询很消耗时间,请慎重执行. ?????????? id: 1? ? select_type: PRIMARY? ??????? table: subcategory? ???????? type: ALL? possible_keys: NULL? ????????? key: NULL? ????? key_len: NULL? ????????? ref: NULL? ???????? rows: 300783? ??????? Extra: Using where? *************************** 2. row ***************************? ?????????? id: 2? ? select_type: DEPENDENT SUBQUERY? ??????? table: c? ???????? type: ref? possible_keys: PRIMARY,category? ????????? key: category? ????? key_len: 4? ????????? ref: const? ???????? rows: 100? ??????? Extra: Using where; Using index; Using temporary; Using filesort? *************************** 3. row ***************************? ?????????? id: 2? ? select_type: DEPENDENT SUBQUERY? ??????? table: i? ???????? type: ref? possible_keys: subcategory? ????????? key: subcategory? ????? key_len: 4? ????????? ref: c.id? ???????? rows: 28? ??????? Extra: Using index? MYSQL必读如果不熟悉如何分析mysql的语句查询计划,请看大概意思:mysql计划从外到内执行查询,而不是从内到外. MYSQL必读外面的查询简单地变成了SELECT * FROM subcategory.虽然里面的查询对subcategory有个约束(WHERE category = 14),但出于某些原因mysql没有将它作用于外面的查询.我不知道是神马原因. MYSQL必读在外面的查询,对每行都执行一次里面的查询,尽管没有值被里面的查询使用到,因为里面的查询被“优化”成引用外面的查询.照此分析,查询计划变成了嵌套循环. MYSQL必读优化器重写后的查询计划: where <in_optimizer>(? ?? s.id,<exists>(? ?? select c.id? ?? from subcategory as c? ????? join item as i? ?? where ((i.subcategory = c.id) and (c.category = 14))? ?? group by c.id? ?? having ((count(0) > 2000)? ????? and (<cache>(s.id) = <ref_null_helper>(c.id))))? )? MYSQL必读可以通过在EXPLAIN EXTENDED 后面带上SHOW WARNINGS 得到优化后的查询.请把稳在HAVING子句中指向的外部域. MYSQL必读众所皆知mysql在有些情况下还不能很好地优化嵌套查询,这个问题已经被广泛报告过. MYSQL必读注意: MYSQL必读我的原则是“有疑问,EXPLAIN看看”. MYSQL必读如何强制里面的查询先执行? MYSQL必读mysql从临时表来实现嵌套查询(某种程度上被讹传的衍生表). MYSQL必读这也是我写这个查询时所期待的执行方式. MYSQL必读查询语句修改如下: where id in (? ??? select id from (? ??????? select c.id? ??????? from subcategory as c? ??????????? inner join item as i on i.subcategory = c.id? ??????? where c.category = 14? ??????? group by c.id? ??????? having count(*) > 2000? ??? ) as x? );? MYSQL必读以上代码所做的是: MYSQL必读有些情况可以使用这种优化办法,比如mysql抛出错误,嵌套查询的表在其他地方被修改(参考:MySQL SELECT同时UPDATE同一张表 ). 编程之家PHP培训学院每天发布《Mysql必读mysql嵌套查询、联表查询的优化详解》等实战技能,PHP、MYSQL、LINUX、APP、JS,CSS全面培养人才。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |