select * from tag join tag_post on tag_post.id = tag.id join post on post.id = tag_post.id where tag.tag = 'msyql'; 分解为: select * from tag from where tag = 'msyql'; select * from tag_post where id = 1234; select * from post where id in (1,2,3);
MYSQLk客户端/服务端通讯协议mysql
了解这些状态的基本含义很是有用,这可让你很好地了解当前“谁正在持球”。在一个繁忙的服务器上,可能会看到大量的不正常状态,例如statistics正占用大量的时间。这一般表示,某个地方有异常了。sql
在MYSQL的概念中,每一个查询都是一次关联,因此读取结果临时表也是一次关联。数据库
当前MYSQL关联执行的策略很简单:MYSQL对任何关联都执行嵌套循环关联操做,即MYSQL先在一个表中循环取出单条数据,而后再嵌套循环到下一个表中寻找匹配的行,依次下去,知道找到全部表中匹配的行为止。而后根据各个表匹配的行,返回查询中须要的各个列。MYSQL会尝试在最后一个关联表中找到全部匹配的行,若是最后一个关联表没法找到更多的行之后,MYSQL返回到上一层次关联表,看是否可以找到更多匹配记录,一次类推迭代执行。缓存
简单的内链接查询: select tab1.col1, tab2.col2 from tab1 inner join tab2 using(col3) where tab1.col1 in (1,2); 实际执行的伪代码表示: outer_iter = iterator over tabl1 where col1 in (1,2) outer_row = outer_iter.next while outer_row inner_iter = iterator over tab2 where col3 = outer_row.col3 inner_row = inner_iter.next while inner_row output [ outer_row.col1, inner_row.col2] inner_row = inner_iter.next end outer_row = outer_iter.next end
简单的外链接查询: select tab1.col1, tab2.col2 from tab1 outer join tab2 using(col3) where tab1.col1 in (1,2); 实际执行的伪代码表示: outer_iter = iterator over tabl1 where col1 in (1,2) outer_row = outer_iter.next while outer_row inner_iter = iterator over tab2 where col3 = outer_row.col3 inner_row = inner_iter.next if inner_row while inner_row output [ outer_row.col1, inner_row.col2] inner_row = inner_iter.next end else output [ outer_row.col, null ] end outer_row = outer_iter.next end
MYSQL的临时表是没有任何索引的,在编写复杂的子查询和关联查询的时候须要注意这一点。这一点对UNION查询也是同样的。性能优化
select * from tab1 where col1 in ( select col2 from tab2 where col3 = 1; )
- SELECT GROUP_CONCAT(col2) from tab2 where col3 = 1; - Reuslt : 1,2,3,4, select * from tabl1 where col1 in (1,2,3,4);
select * from tab1 where exists ( select * from tab2 where col3 = 1 and tab1.col1 = tab2.col1 );
select * from tab1 inner join tab2 using(col1) where col3 = 1; && select * from tab1 where exists ( select * from tab2 where col3 = 1 and tab1.col1 = tab2.col1 );
(select *from tab1 order by col1) union all (select * from tab2 order by col2) limit 20; 优化为: (select *from tab1 order by col1 limit 20) union all (select * from tab2 order by limit 20)
UNION 临时表的数据会大大减小服务器
select count(*) from tab1 where col >5; 优化为: select (select count(*) from tab1 ) - count(*) from tab1 where col <5; 扫描的数量会减小不少 子查询也会当成常数,使用expand可知
select sum(if(color = blue), 1, 0) as blue , sum(if(color = red), 1, 0) as red from items ; 一样也可使用Count
select col1, col2 from tab1 order by col3 limit 50,5; 改写成: select col1, col2 from tab1 inner join ( select col1 from tab1 order by col3 limit 50,5 ) as lim using(col1);
这里的“延迟关联”将大大提高查询效率,它让MYSQL扫描尽量少的页面,获取须要访问的记录后再根据关联列回原表查询须要的全部列。这个技术能够优化LIMIT查询。网络
有时候也能够将LIMIT查询转换为已知位置的查询,让MYSQL经过范围扫描得到到对应的结果。函数
select col1, col2 from tab1 where col1 between 30 and 50; select col1, col2 from tab1 where col1 < 500 order by col1 limit 20;