mysql表关联中的索引使用情况

mysql在某些情况下可以自动优化表关联的关联条件,如:通过分析条件中的字段是否有索引,关联表中的数据总数之类,通过这些条件mysql便可以实现一些自动优化sql语句的功能。

以下几种情况基本是靠一些简单实验进行验证,没有得到确切的官方文档证实

一、inner join情况下mysql自动优化

表结构细节不做介绍,简单介绍下

bus_creative表中的owner字段和sys_user表中的id字段在业务上是外键关联,n-->1,但是owner字段没有建立索引,业务上一般bus_creative数据量大于sys_user,这下就好玩了,先看下通过EXPLAIN执行后的结果

EXPLAIN select b.id from dshp.bus_creative a inner join dshp.sys_user b on a.`owner`=b.id;


下面是交换完关联条件位置后的结果

EXPLAIN select b.id from dshp.sys_user b join dshp.bus_creative a on b.id=a.`owner`;


这里多说一下EXPLAIN的id选项

id 列
建表:
create table a(a_id int);
create table b(b_id int);
create table c(c_id int);
mysql> explain select * from a join b on a_id=b_id where b_id in (select c_id from c);
+----+--------------------+-------+...
| id | select_type        | table |...
+----+--------------------+-------+...
|  1 | PRIMARY            | a     |...
|  1 | PRIMARY            | b     |...
|  2 | DEPENDENT SUBQUERY | c     |...
+----+--------------------+-------+...

从 3 个表中查询,对应输出 3 行,每行对应一个表, id 列表示执行顺序,id 越大,越先执行,id 相同,由上至下执行。此处的执行顺序为(以 table 列表示):c -> a -> b

从上面两个图中可以看到都是先执行的a表,再执行b表,这是为什么呢?啪啪的你知道吗?

来让哥给你解释下吧,此时mysql会先分析关联条件中的两个字段owner和id,mysql掐指一算id是主键,owner是普通字段没有索引,这就好办了,肯定是以有主键或者索引的表数据为查询基准数据,然后遍历没有索引字段的表数据,这样的结果就是先遍历a表,然后以a表的数据在b表中进行查询(因为b中的id是主键索引,查的快啊,如果顺序反过来你想想会是什么结果,肯定用不到索引,这样查询速度肯定慢!),而且图2证明交换关联条件的位置结果也是一样的,更加印证了上面的逻辑。

乖乖了,原来mysql这么智能啊!

废个话,要不你个屌丝都能搞个数据库系统了,还要人家mysql作甚。。。。这只是毛毛雨啦

接下来看个更屌的

哥哥假想如果把关联条件中owner也做成索引,此时mysql他老人家该怎么玩呢,

走起来,哥先建个索引,索引名称是index_owner,这时我们不妨大胆猜测一下结果,

两个关键点,

1.a表中数据量10万,b表中数据量2千吧

2.a中owner是索引,b中id是主键

此时用你那大腿猜猜都该猜到,肯定是先执行数据量少而且关联字段中对方表字段又是索引的那个啊


然后再看看实验结果吧,上图

EXPLAIN select b.id from dshp.bus_creative a join dshp.sys_user b on a.`owner`=b.id;



看看吧,mysql他老人家也是这么想的,而且该用到的索引也都用到了



二、left/right outer join情况下指定顺序执行

基于上面的结果,如果指定了left/right ouert的话,不用想,此时肯定得以left/right指定的那个表为主表先查询,什么?要问我为什么,呵呵,天机不可泄露!我去,你丫滚犊子吧。。。。

因为如果指定了outer后不管怎么优化指定的表数据肯定是全部显示,所以肯定先执行了。

有图有真相就在这里晒:

EXPLAIN select b.id from dshp.bus_creative a left join dshp.sys_user b on a.`owner`=b.id;


换个位置再来一次

EXPLAIN select b.id from dshp.bus_creative a right join dshp.sys_user b on a.`owner`=b.id;




你可能感兴趣的:(mysq优化)