select sum(case intention_type when 1 then 1 else 0 end) as p1_sum, sum(case intention_type when 2 then 1 else 0 end) as p2_sum from user_intention where user_id=1;
select a.expenditure, b.balance from bill a, account b where a.account_id = b.account_id and a.payee=13301087 and b.account_bank='icbc.beijing.fengtai';
select account_id from bill where payee between 51906734 and 51907000 and expenditure>0.00;
复制代码
由于payee between 51906734 and 51907000这个条件,得到的实行筹划中只能使用索引index_payee_expenditure中的payee列,而无法使用expenditure列。
在SQL中出现范围限定条件后,可以考虑这个范围条件对应到数据时,包含的值是否是有限个(个数不是太多)。如果存在这种特性,可以将范围条件转换为多个等值条件in()。MySQL对于in()条件处理和等值条件一样,不会影响索引中其他列(右边列)的使用。针对上述应用场景,可以改为用in():
select account_id from bill where payee in (51907000, 51906734, 51906740) and expenditure>0.00;
MySQL Query Optimizer通过实行explain命令告诉我们它将使用一个怎么样的实行筹划来优化query。因此explain是在优化query中最直接有效的验证我们想法的工具。
要使用explain,只需把explain 放在查询语句的关键字select前面就可以了。MySQL会在查询里设置一个标记,当它实行查询时,这个标记会促使MySQL返回实行筹划里每一步的信息。用不着真正实行。它会返回一行或多行。每行都会显示实行筹划的每一个组成部分,以及实行的次序。
MySQL5.6以前只能表明select查询,其他语句只有通过重写这些非select语句为select,才能够被explain。
下面来详细表明下explain功能中展示的各种信息的表明。
1.1.1 id
MySQL Query Optimizer选定的实行筹划中查询的序列号。表示查询中实行select子句或操作表的顺序,id值越大优先级越高,越先被实行。id相同,实行顺序由上至下,id为NULL最后实行。
1.1.2. select_type
select_type 表示对应行所使用的查询类型,有以下几种类型:
simple:简单查询。查询不包含子查询和union;
primary:复杂查询中最外层的select ;
subquery:包含在 select 中的子查询(不在 from 子句中);
derived:包含在 from 子句中的子查询。MySQL会将效果存放在一个临时表中;
union:在 union 中的第二个和随后的 select;
1.1.3. table
这一列表示 explain 的一行正在访问的的表名称。
当 from 子句中有子查询时,table列是格式,表示当前查询依赖 id=N 的查询,于是先实行 id=N 的查询。当有 union 时,UNION RESULT 的 table 列的值为,1和2表示参与 union 的 select 行id。
1.1.4. type
这一列表示关联类型或访问类型,即MySQL决定如何查找表中的行,查找数据行记录的大概范围。 依次从最优到最差分别为:system > const > eq_ref > ref > range > index > ALL 。
一般来说,得保证查询到达range级别,最好到达ref ;
explain select * from film_actor left join film on film_actor.film_id = film.id;
复制代码
ref
相比 eq_ref,不使用唯一索引,而是使用普通索引大概唯一性索引的部分前缀,索引要和某个值相比较,可能会 找到多个符合条件的行。
(1) 简单 select 查询,name是普通索引(非唯一索引)
explain select * from film where name = ‘film1’;
( 2)关联表查询,idx_film_actor_id是film_id和actor_id的联合索引,这里使用到了film_actor的左边前缀film_id部分。
explain select film_id from film left join film_actor on film.id = film_actor.fi
lm_id;
复制代码
range
范围扫描通常出现在 in(), between ,> ,= 等操作中。使用一个索引来检索给定范围的行。
explain select * from actor where id > 1;
复制代码
index
扫描全索引就能拿到效果,一般是扫描某个二级索引,这种扫描不会从索引树根节点开始快速查找,而是直接 对二级索引的叶子节点遍历和扫描,速率还是比较慢的,这种查询一般为使用覆盖索引,二级索引一般比较小,所以这 种通常比ALL快一些。