我们在使用mysql数据库时,经常会使用到mysql的联合查询,联合查询分为内连接和外连接,内连接查询结果是联合的表都存在匹配才会有结果,外连接则根据驱动表是否存在匹配来生成结果集。
这里使用mysql用例数据库employees举例,联合查询时的一些优化。这里涉及到的表主要是employees和salaries表。
mysql内连接查询时,查询优化器会选择数据量较小的表作为驱动表。employees表大概是30万的数据量,salaries则接近200万。
我们不知道哪些表作为驱动表合适,可以使用join,让mysql优化器帮我们做出选择。
explain select e.emp_no, s.salary from employees e join salaries s on e.emp_no = s.emp_no order by s.salary limit 10;
explain的结果表明mysql使用employees表作为驱动表,结果集一次查询会包含接近30万的数据,由于要根据工资字段进行排序,这里使用到了临时表和文件排序。这是由于mysql的联表查询的执行策略,是循环嵌套查询,即mysql先在一个表中循环取出单条数据,然后再嵌套循环到下一个表中寻找匹配的行,以此类推,直到找到所有表中匹配的行为止。所对被驱动表的字段进行排序时,会产生临时表,并采用文件排序,在数据量很大的时候效率是很慢的。
为了在排序的时候使用上索引,和不使用临时表。我们先对salary字段建立索引。
alter table salaries add index(salary);
接着我们采用left join,使用salaries表作为驱动表。
explain select e.emp_no, s.salary from salaries s left join employees e on e.emp_no = s.emp_no order by s.salary;
可以看到查询时使用了索引。结果集也会根据limit分页来决定。