MySQL的多表关联查询SQL语句优化实例

    今天我们动手练习下,两个表或多表结合查询的SQL语句是怎样优化的。

还是我们先创建两个表和准备一些数据

create table teacher(
  tid int(4) primary key,
  cid int(4) not null
);
insert teacher values(1,2);
insert teacher values(2,1);
insert teacher values(3,3);


create table course(
  cid int(4) ,
  cname varchar(20)
);
insert course values(1,'java');
insert course values(2,'javaweb');
insert course values(3,'spring');

    下边我们来写一个连接的查询语句,并查看执行计划。

mysql> explain select * from teacher t left outer join course c on t.cid=c.cid where c.cname='java';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                      |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
|  1 | SIMPLE      | c     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |    33.33 | Using where                                |
|  1 | SIMPLE      | t     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |    33.33 | Using where; Using join buffer (hash join) |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
2 rows in set, 1 warning (0.00 sec)

    从执行计划结果看到type是all,说明没有进行任何优化,而且出现了using join buffer,它是什么意思呢,mysql逻辑分层中有一个sql优化器,由于我们写的sql性能太差了,它为我们自动添加了连接缓存。

    那我们怎样优化呢,就算加索引应该往哪个表加,记住下边的规则。

  • 小表驱动大表,当编写sql语句时,先写小表,再写大表
  • 索引加在经常使用的字段上
  • 左连接给左表加索引,右连接给右表加索引

    我们继续往下说,按照上边的规则,我们要加索引的话需要往左连接的表中追加,就是给teacher表的cid加索引后,在来看下执行计划。

alter table teacher add index index_cid(cid);

mysql> explain select * from teacher t left outer join course c on t.cid=c.cid where c.cname='java';
+----+-------------+-------+------------+------+---------------+-----------+---------+---------------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key       | key_len | ref                 | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+-----------+---------+---------------------+------+----------+-------------+
|  1 | SIMPLE      | c     | NULL       | ALL  | NULL          | NULL      | NULL    | NULL                |    3 |    33.33 | Using where |
|  1 | SIMPLE      | t     | NULL       | ref  | index_cid     | index_cid | 4       | explain_test1.c.cid |    1 |   100.00 | Using index |
+----+-------------+-------+------------+------+---------------+-----------+---------+---------------------+------+----------+-------------+
2 rows in set, 1 warning (0.01 sec)

    从这个执行计划结果来看,teacher表已经优化到type是ref级别,效率大大提升了,由于检索条件是按cname检索,我们来试试往cname上在加一个索引后,我们再来分析下执行计划。

alter table course add index index_cname(cname);

mysql> explain select * from teacher t left outer join course c on t.cid=c.cid where c.cname='java';
+----+-------------+-------+------------+------+---------------+-------------+---------+---------------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key         | key_len | ref                 | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+-------------+---------+---------------------+------+----------+-------------+
|  1 | SIMPLE      | c     | NULL       | ref  | index_cname   | index_cname | 83      | const               |    1 |   100.00 | Using where |
|  1 | SIMPLE      | t     | NULL       | ref  | index_cid     | index_cid   | 4       | explain_test1.c.cid |    1 |   100.00 | Using index |
+----+-------------+-------+------------+------+---------------+-------------+---------+---------------------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

    也同样,两张表已经提升到ref级别了,性能也大大增加了,这里我们的例子是两张表结合的优化,而三四张表结合的原理都是一样的,小表驱动大表,将索引加在经常使用的字段上。

    在文章最后,我们已怎样操作索引字段的小技巧来结束今天的文章。

  • 复合索引不要跨列或无序使用
  • 尽量使用全索引匹配
  • 不要在索引上进行任何操作,例如计算,函数,类型转换(显式或隐式)等
  • 索引列不能使用不等于(!= ,<>)或者大于(>)或者小于(<)或者is null或者is not nul
  • 索引优化时尽量达到using index
  • 写like语句时不要以%开头
  • 索引列不能使用or
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值