MySQL 查询优化 - 关联查询

1. 关联查询执行流程

MySQL执行关联查询的策略很简单,他会从一个表中循环取出单条数据,然后用该条数据到下一个表中寻找匹配的行,然后回溯到上一个表,到所有的数据匹配完成为止。因此也被称为“嵌套循环关联”。

来看下面这个SQL:

select tb1.col1, tb2,col2
  from tb1 inner join tb2 using(col3)
  where tb1.col1 in (5,6)

他的执行顺序为(伪代码):

List outerDataList = "select * from tb1 where col1 in (5,6)"
  for(outerData in outerDataList){
    List innerDataList = "select * from tb2 where col3 = outerData.col3"
      for(innerData : innerDataList){
        output(outterData,innerData)
      }
  }

MySQL认为所有的查询都是一次关联查询,所以如果查询一个表,上述过程也适合,不过只需要完成上面外层的基本操作。

再来看看left outter join查询的过程,SQL如下:

select tb1.col1, tb2,col2
from tb1 left outer join tb2 using(col3)
where tb1.col1 in (5,6)

伪代码如下:

List outerDataList = "select * from tb1 where col1 in (5,6)"
  for(outerData in outerDataList){
    List innerDataList = "select * from tb2 where col3 = outerData.col3"
      if(innerDataList != null){
        for(innerData : innerDataList){
          output(outterData,innerData)
        }
      }else{
        // inner表无对应数据,以outter数据为准
        output(outterData,null)
      }
  }

但是这种遍历的查询方式不能满足所有的联合查询,比如“全外连接”查询(full outer join)不能使用该方法来实现,这可能是MySQL不支持全外接查询的原因 ~~~

2. 优化

MySQL会将查询命令生成一颗指令树,比如四表联合查询的指令树如下:

?

MySQL在生成指令树之前会先对SQL语句的执行效率进行评估,然后选择他认为效率最高的关联顺序执行。对于如下SQL:

EXPLAIN SELECT
    actor.NAME,
    film.title
FROM
    actor actor
    INNER JOIN film_actor USING ( actor_id )
    INNER JOIN film USING ( film_id )

从执行计划可以看出,MySQL选择将film作为第一个关联表,拿到数据后再依次扫描film_actor、actor表取数据。MySQL的选择策略是,尽量让查询执行更少的嵌套循环和回溯操作,因此,他会尽量将外层查询的数据量更少。因为film表只有4条记录,actor表有6条记录,因此他认为选择将film作为第一个表开始查询有更高的执行效率。

但是MySQL的优化策略会比这复杂的多,MySQL会计算所有执行顺序的代价,然后选择他认为的最佳执行计划。但是,如果联合查询的表比较多,他不一定能穷举所有的执行情况选择最佳的执行策略,所以这种默认的优化方式却不一定总是最佳的。还是以上条SQL为例子,假设在film表的film_id字段上建立了索引,那么即使film上的字段少于actor,可能使用actor表作为第一个表进行查询,效率会更高(里层嵌套查询film表数据时可以使用索引)。如果你认为有更佳的执行顺序,可以使用STRAIGHT_JOIN关键字强行执行查询顺序:

EXPLAIN SELECT
    actor.NAME,
    film.title
FROM
    actor actor
    STRAIGHT_JOIN film_actor USING ( actor_id )
    STRAIGHT_JOIN film USING ( film_id )

注意:绝大多数时候,MySQL做出的判断都比人类要准确,绝大多数时候,不推荐强制执行顺序。

原文地址:https://www.cnblogs.com/moongeek/p/11332504.html

时间: 2024-07-30 17:14:21

MySQL 查询优化 - 关联查询的相关文章

mysql数据库关联查询【lert join】常见使用

一,关键词: 1) left(连接类型)   join  on(条件) 二,常见连接: 1)join(获取的是一个笛卡尔积). select * from t_table1  join t_table2 ; 2)左连接 (两表关联,在匹配条件之后,左表保留全部,也就是包含没有匹配到的字段) select * from t_table1  left join t_table2 on t_table1.id = t_table2 .id; 3)右连接(两表关联,在匹配条件之后,右表保留全部,包含没有

Yii2实现跨mysql数据库关联查询排序功能

遇到一个项目,需要跨表网上找了很多的资料,整理一下,方便以后再次使用 背景:在一个mysql服务器上(注意:两个数据库必须在同一个mysql服务器上)有两个数据库: memory (存储常规数据表) 中有一个 user 表(记录用户信息) memory_stat (存储统计数据表) 中有一个 user_stat (记录用户统计数据) 现在在 user 表生成的 GridView 列表中展示 user_stat 中的统计数据 只需要在User的model类中添加关联. public functio

MySQL中关联查询相关语句

-- emp和job查询 SELECT t1.`id`, t1.`ename`, t1.`salary`, t2.`jname`, t2.`descriptions` FROM emp t1,job t2,dept t3 WHERE t1.`job_id`=t2.`id`AND t3.`id`=t1.`dept_id`; -- 查询工资的等级 SELECT t1.ename,t1.`salary`,t2.`grade` FROM emp t1,salarygrade t2 WHERE t1.`s

mysql 表关联查询报错 ERROR 1267 (HY000)

解决翻案:http://stackoverflow.com/questions/1008287/illegal-mix-of-collations-mysql-error 即: SET collation_connection = 'utf8_general_ci'; ALTER DATABASE db CHARACTER SET utf8 COLLATE utf8_general_ci; ALTER TABLE table CONVERT TO CHARACTER SET utf8 COLLA

MySQL多表关联查询与存储过程

1.多表关联查询 --  **************关联查询(多表查询)**************** -- 需求:查询员工及其所在部门(显示员工姓名,部门名称) -- 1.1 交叉连接查询(不推荐.产生笛卡尔乘积现象:4 * 4=16,有些是重复记录) SELECT empName,deptName FROM employee,dept; -- 需求:查询员工及其所在部门(显示员工姓名,部门名称) -- 多表查询规则:1)确定查询哪些表   2)确定查询哪些字段   3)表与表之间连接条件

[转] hibernate Mysql 自增长 注解配置,表无关联的注解方式关联查询

不同数据库 自增长ID配置 正对不同的数据库可以同时使用         @Id         @GeneratedValue(strategy = GenerationType.AUTO) 2 针对mysql  @Id  @GeneratedValue(strategy = GenerationType.IDENTITY) 3 针对oracle        @Id        @GeneratedValue(strategy = GenerationType.SEQUENCE,gener

JDBC MySQL 多表关联查询查询

public static void main(String[] args) throws Exception{ Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb","root",""); String sql ="select

MySQL如何执行关联查询

MySQL中‘关联(join)’ 一词包含的意义比一般意义上理解的要更广泛.总的来说,MySQL认为任何一个查询都是一次‘关联’ --并不仅仅是一个查询需要到两个表的匹配才叫关联,索引在MySQL中,每一个查询,每一个片段(包括子查询,设置基于表单的select)都可能是关联. 所以,理解MySQL如何执行关联查询至关重要.我们先来看一个union 查询的例子.对于union查询,MySQL先将一系列的单个查询结果放到一个临时表中,然后再重新读出临时表数据来完成union查询.在MySQL的概念

Mysql中的关联查询(内连接,外连接,自连接)

Mysql中的关联查询(内连接,外连接,自连接) 在使用数据库查询语句时,单表的查询有时候不能满足项目的业务需求,在项目开发过程中,有很多需求都是要涉及到多表的连接查询,总结一下mysql中的多表关联查询 一,内连接查询 是指所有查询出的结果都是能够在连接的表中有对应记录的. 以t_employee(员工表)和t_dept(部门表)为例: t_employee表中的记录如下:dept代表该员工所在的部门 t_dept表中记录如下: 可以发现,其中人力资源部里没有员工(这里只是举例,可能与实际不符