mysql 多表查询 优化_MySql多表查询优化
一、多表查詢(xún)連接的選擇
相信內(nèi)連接,左連接什么的大家都比較熟悉了,當(dāng)然還有左外連接什么的,基本用不上,我就補(bǔ)貼出來(lái)了,這個(gè)圖只是讓大家熟悉一下各種連接查詢(xún)。然后要告訴大家的是,需要根據(jù)查詢(xún)的信息,想好使用哪種連接方式效率更高。
二、MySql的Join實(shí)現(xiàn)原理
在MySql中,只有一種Join算法,就是大名鼎鼎的Nested Loop Join,它沒(méi)有其他很多數(shù)據(jù)庫(kù)提供的Hash Join,也米有Sort Merge Join,顧名思義,Nested Loop Join 實(shí)際上就是通過(guò)驅(qū)動(dòng)表的結(jié)果集作為循環(huán)基礎(chǔ)數(shù)據(jù),然后一條一條的通過(guò)該結(jié)果集中的數(shù)據(jù)作為過(guò)濾條件到下一個(gè)標(biāo)中查詢(xún)數(shù)據(jù),然后合并結(jié)果。如果還有第三個(gè)參數(shù)與Join,則再通過(guò)前面兩個(gè)表的Join結(jié)果作為循環(huán)基礎(chǔ)數(shù)據(jù),再次通過(guò)循環(huán)查詢(xún)條件到第三個(gè)表中查詢(xún)數(shù)據(jù),如此往復(fù)。
三、補(bǔ)充:mysql對(duì)sql語(yǔ)句的容錯(cuò)問(wèn)題。
即在sql語(yǔ)句不完全符合書(shū)寫(xiě)建議的情況,mysql會(huì)允許這種情況,盡可能解釋他:
1)一版cross join后面加上where條件,但是用cross join + on 也是被解釋為cross join + where;
2)一版內(nèi)鏈接都需要加上on限定條件,如上面場(chǎng)景一;如果不加會(huì)被解釋為交叉連接;
3)如果連接表格使用的是逗號(hào),會(huì)被解釋為交叉連接;
注意:sql標(biāo)準(zhǔn)中還有union join 和 natural inner join,mysql不支持,而且本身也沒(méi)有多大意義,其實(shí)就是為了“健壯”。但是其實(shí)結(jié)果可以用上面的幾種連接方式得到。
四、超大型數(shù)據(jù)見(jiàn)可能盡力不要寫(xiě)子查詢(xún),使用連接(join)去替換他
當(dāng)然,關(guān)于這句話,也不一定就全是這樣。
1)因?yàn)樵诖笮偷臄?shù)據(jù)處理中,子查詢(xún)是非常常見(jiàn)的,特別是在查詢(xún)出來(lái)的數(shù)據(jù)需要進(jìn)一步處理的情況,無(wú)論是可讀性還是效率上,這時(shí)候的子查詢(xún)都是更優(yōu)。
2)然而在一些特定的場(chǎng)景,可以直接從數(shù)據(jù)庫(kù)讀取就可以的,比如一個(gè)表(A表 a,b,c字段,需要內(nèi)部數(shù)據(jù)交集)join自己的效率必然比放一個(gè)子查詢(xún)?cè)賥here中快得多。
五、使用聯(lián)合Union來(lái)代替手動(dòng)創(chuàng)建得臨時(shí)表
Union是會(huì)把結(jié)果排序的!!
union查詢(xún):它可以把需要使用臨時(shí)表的兩條或更多的select查詢(xún)合并在一個(gè)查詢(xún)中(即把兩次或多次查詢(xún)結(jié)果合并起來(lái))。在客戶(hù)端的查詢(xún)會(huì)話結(jié)束的時(shí)候,臨時(shí)表會(huì)被自動(dòng)刪除。從而保證數(shù)據(jù)庫(kù)整齊、高效。使用union來(lái)創(chuàng)建查詢(xún)的時(shí)候,我們只需要用union作為關(guān)鍵字把多個(gè)select語(yǔ)句連接起來(lái)就可以了,要注意的是所有select語(yǔ)句中的字段數(shù)據(jù)要相同。
要求:兩次查詢(xún)的列數(shù)必須一致(列的類(lèi)型可以不一樣,但推薦查詢(xún)的每一列,對(duì)應(yīng)的數(shù)據(jù)類(lèi)型要一樣)可以來(lái)自多張表的數(shù)據(jù),多次sql語(yǔ)句取出的列名可以不一致,此時(shí)以第一個(gè)sql語(yǔ)句的列名為準(zhǔn)。如果不同的語(yǔ)句中取出的行,有完全相同(這里標(biāo)識(shí)的是每個(gè)列的值都相同)。那么union會(huì)將相同的行合并,最終只保留一行,也可以這樣理解,union會(huì)去掉重復(fù)的行。如果不想去掉重復(fù)的行,可以使用union all。
如果子句中有order by,limit,需要括號(hào)()包起來(lái),推薦放到所有子句之后,即對(duì)最終合并的結(jié)果來(lái)排序或者篩選。
注意:
1、Union結(jié)果集中的列名總是等于第一個(gè)select語(yǔ)句中的列名
2、Union內(nèi)部的select語(yǔ)句必須擁有相同數(shù)量的列,列也必須擁有相似的數(shù)據(jù)類(lèi)型,同時(shí),每條select語(yǔ)句中的列的順序必須相同。
Union all 的作用和語(yǔ)法:
默認(rèn)的,union操作符選取不同的值,如果允許重復(fù)的值,請(qǐng)使用union all,當(dāng)all隨union一起使用時(shí),不消除重復(fù)行。
六、總結(jié)
(1)對(duì)于要求全面的結(jié)果時(shí),我們需要使用連接操作(left join / right join / full join);
(2)應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行null值判斷,否則導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,如:
備注、描述、評(píng)論之類(lèi)的可以設(shè)置為null,其它做好不要使用null。
不要以為null不需要空間,比如:char(100)型,在字段建立時(shí),控件就固定了,不管是否插入值(null也包含在內(nèi))。都是占用100個(gè)字符的空間的。如果是varchar這樣的變長(zhǎng)字段,null不占用空間。
可以在null上設(shè)置默認(rèn)值0,確保表中num列沒(méi)有null值,然后這樣查詢(xún):
select id from t where num=0
(3)in 和 not in 也要慎用,否則會(huì)導(dǎo)致全表掃描,如:
很多時(shí)候,用exists代替in是個(gè)好的選擇:
(4)盡量使用數(shù)字類(lèi)型字段,若只含數(shù)值信息的字段,盡量不要設(shè)計(jì)為字符型,這樣會(huì)降低查詢(xún)和連接的性能,并會(huì)增加存儲(chǔ)開(kāi)銷(xiāo),這是因?yàn)橐嬖谔幚聿樵?xún)和連接時(shí),會(huì)逐個(gè)比較字符串中每一個(gè)字符。而對(duì)于數(shù)字型而言,只需要對(duì)比一次就可以了。
(5)盡量使用表變量來(lái)代替臨時(shí)表,如果表變量包含大量數(shù)據(jù),請(qǐng)注意索引使用非常有限(只有主鍵索引)。
(6)不要以為使用mysql的一些連接查詢(xún)操作對(duì)查詢(xún)有多么大的改善,其核心時(shí)索引。
總結(jié)
以上是生活随笔為你收集整理的mysql 多表查询 优化_MySql多表查询优化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: html编码写出滚动字幕,HTML滚动字
- 下一篇: C#读取Excel表格去掉空行