MySQL——关联查询优化

MySQL——关联查询优化

1、数据准备

建表

create table if not exists type
(
    id   int(10) unsigned not null auto_increment,
    card int(10) unsigned not null,
    primary key (id)
);

create table if not exists book
(
    bookid int(10) unsigned not null auto_increment,
    card   int(10) unsigned not null,
    primary key (bookid)
);

2、外连接

sql查询分析:type表为驱动表,book表为被驱动表,进行左连接,可以看到,两张表的type类型都是全表扫描

mysql> explain select * from type left join book on type.card = book.card;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                              |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
|  1 | SIMPLE      | type  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   20 |   100.00 | NULL                                               |
|  1 | SIMPLE      | book  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   20 |   100.00 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
2 rows in set, 1 warning (0.00 sec)

给被驱动表book建立索引:

create index idx_book_card on book(card);

sql查询分析:被驱动表type类型为ref,在被驱动表上建立索引,效率会有很大的提升

mysql> explain select * from type left join book on type.card = book.card;
+----+-------------+-------+------------+------+---------------+---------------+---------+-------------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key           | key_len | ref               | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+---------------+---------+-------------------+------+----------+-------------+
|  1 | SIMPLE      | type  | NULL       | ALL  | NULL          | NULL          | NULL    | NULL              |   20 |   100.00 | NULL        |
|  1 | SIMPLE      | book  | NULL       | ref  | idx_book_card | idx_book_card | 4       | testdb1.type.card |    1 |   100.00 | Using index |
+----+-------------+-------+------------+------+---------------+---------------+---------+-------------------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

给驱动表type加上也索引:

create index idx_type_card on type(card);

sql查询分析:驱动表和被驱动表都用上了索引,等值条件的类型要相同

mysql> explain select * from type left join book on type.card = book.card;
+----+-------------+-------+------------+-------+---------------+---------------+---------+-------------------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key           | key_len | ref               | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+---------------+---------+-------------------+------+----------+-------------+
|  1 | SIMPLE      | type  | NULL       | index | NULL          | idx_type_card | 4       | NULL              |   20 |   100.00 | Using index |
|  1 | SIMPLE      | book  | NULL       | ref   | idx_book_card | idx_book_card | 4       | testdb1.type.card |    1 |   100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+---------------+---------+-------------------+------+----------+-------------+
2 rows in set, 1 warning (0.01 sec)

3、内连接

sql查询分析:两张表都是全表扫描,MySQL自动选择驱动表

mysql> explain select * from type inner join book on type.card = book.card;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                              |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
|  1 | SIMPLE      | type  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   20 |   100.00 | NULL                                               |
|  1 | SIMPLE      | book  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   20 |    10.00 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
2 rows in set, 1 warning (0.00 sec)

给被驱动表book建立索引:

create index idx_book_card on book(card);

sql查询分析:

mysql> explain select * from type inner join book on type.card = book.card;
+----+-------------+-------+------------+------+---------------+---------------+---------+-------------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key           | key_len | ref               | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+---------------+---------+-------------------+------+----------+-------------+
|  1 | SIMPLE      | type  | NULL       | ALL  | NULL          | NULL          | NULL    | NULL              |   20 |   100.00 | NULL        |
|  1 | SIMPLE      | book  | NULL       | ref  | idx_book_card | idx_book_card | 4       | testdb1.type.card |    1 |   100.00 | Using index |
+----+-------------+-------+------------+------+---------------+---------------+---------+-------------------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

给驱动表type加上索引:

create index idx_type_card on type(card);

sql查询分析:发现 查询优化器把book作为了驱动表,type作为被驱动表

mysql> explain select * from type inner join book on type.card = book.card;
+----+-------------+-------+------------+-------+---------------+---------------+---------+-------------------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key           | key_len | ref               | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+---------------+---------+-------------------+------+----------+-------------+
|  1 | SIMPLE      | book  | NULL       | index | idx_book_card | idx_book_card | 4       | NULL              |   20 |   100.00 | Using index |
|  1 | SIMPLE      | type  | NULL       | ref   | idx_type_card | idx_type_card | 4       | testdb1.book.card |    1 |   100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+---------------+---------+-------------------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

注:如果等值条件中只有一个字段有索引的情况,那么查询优化器会把有索引字段的表作为被驱动表

4、小结

  • 小结果集驱动大结果集(本质就是减少外层循环的数据数量)
  • 为被驱动表匹配的字段条件增加索引(减少被驱动表的循环匹配次数)
  • 增大 join buffer size的大小,驱动表能不能一次加载完,要看join buffer能不能存储所有的数据,默认情况下join_buffer_size=256k。驱动表一次加载的数据越多,被驱动表的扫表次数就越少。
  • 减少驱动表不必要的字段查询
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万里顾—程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值