MySQL关联查询优化实现方法详解

 更新时间:2022年11月01日 11:53:55   作者:流烟默  
在数据库的设计中, 我们通常都是会有很多张表 , 通过表与表之间的关系建立我们想要的数据关系, 所以在多张表的前提下, 多表的关联查询就尤为重要,这篇文章主要介绍了MySQL关联查询优化

我们准备如下两个表,并插入数据。

#分类
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`)
);

左外连接

首先我们分析SQL如下,type为驱动表(内表),book为被驱动表(外表)。

EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book 
ON type.card = book.card;

每次从type中获取一条数据然后后book中的数据进行对比(全表扫描),这个过程要要重复20次(type 表有20条数据)。

这里可以看到,type均为all。另外还可以看到MySQL帮我们做了一个优化,使用了join buffer进行缓存。

我们为被驱动表 book.card 添加索引优化

CREATE INDEX Y ON book(card);
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book 
ON type.card = book.card;

这里能够看到,虽然type表仍旧是要处理20次,但是拿着type的数据去book中寻找时,走的是索引。对于B+树来讲,其时间复杂度为logN,相比前面的全表扫描要快很多。

也就是对于左外连接来讲,如果只能添加一个索引,那么一定添加到被驱动表上。

当然,给type的card页创建索引也是可以的。

CREATE INDEX X ON `type`(card);
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book 
ON type.card = book.card;

如果索引只加在了驱动表(左表)呢?

DROP INDEX Y ON book;
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book 
ON type.card = book.card;

可以看到,同样使用了join buffer。而对于驱动表来讲,即使用到了索引也要做一个整体的遍历(无非这时走的是索引文件)。而被驱动表没有索引,那么性能会相对较慢。

如下图所示,从其查询成本我们也可以看到显著区别。

结论: 左(外)连接时,索引加在右表的连接字段。left join用于确定如何从右表搜索行,左表一定都有。同理,右(外)连接时,索引创建在左表的连接字段。该连接字段在两个表中的数据类型保持一致。

此外,从上面Using where; Using join buffer (Block Nested Loop)我们也可以想到,如果有条件,那么join buffer给一个较大的容量是有助于提升性能的。

内连接INNER JOIN

我们去掉索引,然后查看执行计划。

DROP INDEX X ON `type`;
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` INNER JOIN book 
ON type.card = book.card;

我们给被驱动表 book.card 添加索引

CREATE INDEX Y ON book(card);
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` INNER JOIN book 
ON type.card = book.card;

我们再给驱动表type添加索引

CREATE INDEX X ON `type`(card);
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` INNER JOIN book 
ON type.card = book.card;

可以看到这里二者均用到了索引。需要说明的是,这时type和book上下次序可能转换,也就是说 对于inner join来讲,查询优化器可以决定谁作为驱动表,谁作为被驱动表出现的 。

那如果book.card没有索引,type.card 有索引呢?

DROP INDEX Y ON book;
EXPLAIN  SELECT SQL_NO_CACHE * FROM `type` INNER JOIN book 
ON type.card = book.card;

可以看到book作为了驱动表,type作为了被驱动表。即,对于内连接来讲,如果表的连接条件中只能有一个字段有索引,则有索引的字段所在的表会被作为被驱动表出现。

如果两个表数据量不一致呢?比如这里我们type为40条,book为20条。

EXPLAIN  SELECT SQL_NO_CACHE * FROM `type` INNER JOIN book 
ON type.card = book.card;

结论: 对于内连接来说,在两个表的连接条件都存在索引的情况下,会选择小表作为驱动表,即“小表驱动大表”。

到此这篇关于MySQL关联查询优化实现方法详解的文章就介绍到这了,更多相关MySQL关联查询优化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SQL数据分表Mybatis Plus动态表名优方案

    SQL数据分表Mybatis Plus动态表名优方案

    这篇文章主要介绍了SQL数据分表Mybatis Plus动态表名优方案,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-08-08
  • 浅谈MySQL之浅入深出页原理

    浅谈MySQL之浅入深出页原理

    首先,我们需要知道,页(Pages)是InnoDB中管理数据的最小单元。Buffer Pool中存的就是一页一页的数据。当我们要查询的数据不在Buffer Pool中时,InnoDB会将记录所在的页整个加载到Buffer Pool中去;同样,将Buffer Pool中的脏页刷入磁盘时,也是按照页为单位刷入磁盘的
    2021-06-06
  • MySql中怎样查询表是否被锁

    MySql中怎样查询表是否被锁

    这篇文章主要介绍了MySql中怎样查询表是否被锁问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • 优化mysql的limit offset的例子

    优化mysql的limit offset的例子

    在mysql中,通常使用limit做分页,而且经常会跟order by 连用。在order by 上加索引有时候是很有帮助的,不然系统会做很多的filesort
    2013-02-02
  • mysql合并多条记录的单个字段去一条记录编辑

    mysql合并多条记录的单个字段去一条记录编辑

    mysql怎么合并多条记录的单个字段去一条记录,今天在网上找了一下,方法如下
    2011-09-09
  • mysql字符串拼接的几种实用方式小结

    mysql字符串拼接的几种实用方式小结

    在SQL语句中经常需要进行字符串拼接,下面这篇文章主要给大家介绍了关于mysql字符串拼接的几种实用方式,文中通过图文以及代码示例介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • MySQL 索引从入门到精通示例详解(核心概念、类型与实战优化)

    MySQL 索引从入门到精通示例详解(核心概念、类型与实战优化)

    本文详细介绍了MySQL索引的概念、类型及其在实际应用中的优化策略,索引可以显著提升查询效率,但过多的索引会增加写操作的开销,文章涵盖了索引的创建、维护和使用技巧,帮助读者更好地理解和应用索引,以优化数据库性能,感兴趣的朋友跟随小编一起看看吧
    2026-01-01
  • mysql自联去重的一些笔记记录

    mysql自联去重的一些笔记记录

    这篇文章主要给大家介绍了关于mysql自联去重的一些笔记记录,文中通过示例代码介绍的非常详细,对大家学习或者使用mysql具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • 解决mysql数据库设置远程连接权限执行grant all privileges on *.* to 'root'@'%' identified by '密码' with grant optio报错

    解决mysql数据库设置远程连接权限执行grant all privileges on&n

    这篇文章主要介绍了解决mysql数据库设置远程连接权限执行grant all privileges on *.* to 'root'@'%' identified by '密码' with grant optio报错,通过本文给大家分享问题原因解析及解决方法,需要的朋友可以参考下
    2022-11-11
  • mysql最左前缀法则导致索引失效的解决

    mysql最左前缀法则导致索引失效的解决

    最左前缀是在使用innodb存储引擎索引时,需要遵守的法则,本文主要介绍了mysql最左前缀法则导致索引失效的解决,具有一定的参考价值,感兴趣的可以了解一下
    2024-07-07

最新评论