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;