一、多表查詢連接的選擇
相信內連接,左連接什么的大家都比較熟悉了,當然還有左外連接什么的,基本用不上,我就補貼出來了,這個圖只是讓大家熟悉一下各種連接查詢。然后要告訴大家的是,需要根據查詢的信息,想好使用哪種連接方式效率更高。
二、MySql的Join實現原理
在MySql中,只有一種Join算法,就是大名鼎鼎的Nested Loop Join,它沒有其他很多數據庫提供的Hash Join,也米有Sort Merge Join,顧名思義,Nested Loop Join 實際上就是通過驅動表的結果集作為循環基礎數據,然后一條一條的通過該結果集中的數據作為過濾條件到下一個標中查詢數據,然后合並結果。如果還有第三個參數與Join,則再通過前面兩個表的Join結果作為循環基礎數據,再次通過循環查詢條件到第三個表中查詢數據,如此往復。
三、補充:mysql對sql語句的容錯問題。
即在sql語句不完全符合書寫建議的情況,mysql會允許這種情況,盡可能解釋他:
1)一版cross join后面加上where條件,但是用cross join + on 也是被解釋為cross join + where;
2)一版內鏈接都需要加上on限定條件,如上面場景一;如果不加會被解釋為交叉連接;
3)如果連接表格使用的是逗號,會被解釋為交叉連接;
注意:sql標准中還有union join 和 natural inner join,mysql不支持,而且本身也沒有多大意義,其實就是為了“健壯”。但是其實結果可以用上面的幾種連接方式得到。
四、超大型數據見可能盡力不要寫子查詢,使用連接(join)去替換他
當然,關於這句話,也不一定就全是這樣。
1)因為在大型的數據處理中,子查詢是非常常見的,特別是在查詢出來的數據需要進一步處理的情況,無論是可讀性還是效率上,這時候的子查詢都是更優。
2)然而在一些特定的場景,可以直接從數據庫讀取就可以的,比如一個表(A表 a,b,c字段,需要內部數據交集)join自己的效率必然比放一個子查詢再where中快得多。
五、使用聯合Union來代替手動創建得臨時表
Union是會把結果排序的!!
union查詢:它可以把需要使用臨時表的兩條或更多的select查詢合並在一個查詢中(即把兩次或多次查詢結果合並起來)。在客戶端的查詢會話結束的時候,臨時表會被自動刪除。從而保證數據庫整齊、高效。使用union來創建查詢的時候,我們只需要用union作為關鍵字把多個select語句連接起來就可以了,要注意的是所有select語句中的字段數據要相同。
要求:兩次查詢的列數必須一致(列的類型可以不一樣,但推薦查詢的每一列,對應的數據類型要一樣)可以來自多張表的數據,多次sql語句取出的列名可以不一致,此時以第一個sql語句的列名為准。如果不同的語句中取出的行,有完全相同(這里標識的是每個列的值都相同)。那么union會將相同的行合並,最終只保留一行,也可以這樣理解,union會去掉重復的行。如果不想去掉重復的行,可以使用union all。
如果子句中有order by,limit,需要括號()包起來,推薦放到所有子句之后,即對最終合並的結果來排序或者篩選。
注意:
1、Union結果集中的列名總是等於第一個select語句中的列名
2、Union內部的select語句必須擁有相同數量的列,列也必須擁有相似的數據類型,同時,每條select語句中的列的順序必須相同。
Union all 的作用和語法:
默認的,union操作符選取不同的值,如果允許重復的值,請使用union all,當all隨union一起使用時,不消除重復行。
六、總結
(1)對於要求全面的結果時,我們需要使用連接操作(left join / right join / full join);
(2)應盡量避免在where子句中對字段進行null值判斷,否則導致引擎放棄使用索引而進行全表掃描,如:
備注、描述、評論之類的可以設置為null,其它做好不要使用null。
不要以為null不需要空間,比如:char(100)型,在字段建立時,控件就固定了,不管是否插入值(null也包含在內)。都是占用100個字符的空間的。如果是varchar這樣的變長字段,null不占用空間。
可以在null上設置默認值0,確保表中num列沒有null值,然后這樣查詢:
select id from t where num=0
(3)in 和 not in 也要慎用,否則會導致全表掃描,如:
很多時候,用exists代替in是個好的選擇:
(4)盡量使用數字類型字段,若只含數值信息的字段,盡量不要設計為字符型,這樣會降低查詢和連接的性能,並會增加存儲開銷,這是因為引擎在處理查詢和連接時,會逐個比較字符串中每一個字符。而對於數字型而言,只需要對比一次就可以了。
(5)盡量使用表變量來代替臨時表,如果表變量包含大量數據,請注意索引使用非常有限(只有主鍵索引)。
(6)不要以為使用mysql的一些連接查詢操作對查詢有多么大的改善,其核心時索引。