天天看點

join和子查詢效率_從阿裡手冊引出的Join查詢思考

Join查詢再熟悉不過了,看視沒有必要把它拿出來說事,但某天一個學生問起了一個問題,有必要拿來說下。

很多同學的畢生夢想都是想進BATJ的某家公司,其中又以案例為多數,是的,不管從哪個角度來說,阿裡都是一個非常棒的公司,值得去挑戰一把。

回到今天的話題,一個同學(阿裡的鐵杆粉),問了我一個問題,在實際工作中到底應不應該用join查詢,到底應該注意點什麼?

别以為這個問題很傻,如果你關注過阿裡的規範,裡面就有顯著的一條:

【強制】超過三個表禁止 join。需要 join 的字段,資料類型必須絕對一緻;多表關聯查詢時,保證被關聯的字段需要有索引。

首先,我要交代,上面這句話出自《阿裡java程式設計規範手冊》,并不是我的原創,另外我想說的是,對于上面這句話,我不管你懂不懂為什麼,請按手冊裡面說的,強制去執行。

不過既然有同學再問,我認為還是有必要把這個問題拿來分析下。

禁止超過3表的JOIN

如果太多的表JOIN對性能的影響是非常大的(Join的性能以及注意事項我後面再分析),這個我相信,對于絕大多數讀者來說都是認可的,起碼能做到表面上了解,但也不排除某些另外情況,比如說...

某天,有個同學小甲,給我發個SQL語句,一方面誇誇其談它對公司的業務,表結構了解的如何透徹。

我打開sql檔案後,一個2132行的sqL語句映入眼簾,我心裡頓時(&%%¥&……),好吧,我得承認這情況并不隻一個,而且他們以這個為榮,我不知道當這同學離職後,後面接手的會不會和我一樣的心情。

現在我也無力反駁他,這可能在某些特殊的情況下對他是好的(誰敢開除他,誰敢接他的手),我現在隻想聊聊出現過多表關聯之後怎麼來解決。

确實答案也出自《阿裡java程式設計規範手冊》

【推薦】字段允許适當備援,以提高查詢性能,但必須考慮資料一緻。

其實雖然規範裡面沒說,但這是資料庫設計裡面非常重要的一條:

反範式設計

·

反範式化是針對範式化而言的,在前面介紹了資料庫設計的範式

·

所謂得反範式化就是為了性能和讀取效率得考慮而适當得對資料庫設計範式得要求進行違反

·

允許存在少量的備援,換句話來說反範式化就是使用空間來換取時間

舉一個簡單的例子:

join和子查詢效率_從阿裡手冊引出的Join查詢思考

上面這個sql語句查詢的資料來自a,b兩張表,仔細看你會發現,其中隻有cl4這一列是出自b表,其他的所有都是a表,這樣可以考慮建立一個c表,把c1l,cl2,cl3,cl4的資料全部關聯起來,實際做的事情就是備援了cl4這個字段。

帶來的好處呢? 查詢的時候隻要查詢c表,效率不會提升才怪。

資料類型必須一緻

資料類型必須一緻,請完全遵守,如果你定是要尋根究底轉牛角尖,那我們做個實驗,做實驗的前提是你要了解些許的執行計劃,當然對索引也得一知半解才行。

join和子查詢效率_從阿裡手冊引出的Join查詢思考

資料和表都準備好了後,我來寫一個sql語句:

join和子查詢效率_從阿裡手冊引出的Join查詢思考
join和子查詢效率_從阿裡手冊引出的Join查詢思考

很棒,結果也查詢出來了,name是varchar類型, 而給出的2000是整型,這有什麼問題嗎?結果不是正确的嘛?

别着急,還記得前面建立了索引嘛?

join和子查詢效率_從阿裡手冊引出的Join查詢思考

使用執行計劃看下:

join和子查詢效率_從阿裡手冊引出的Join查詢思考

看出問題了嗎?雖然我指定的name上面是索引的,但資料類型不一緻,不好意思,結果是全表掃描。

如果資料類型一緻呢?

join和子查詢效率_從阿裡手冊引出的Join查詢思考
join和子查詢效率_從阿裡手冊引出的Join查詢思考

key有值,代表就是用到了索引,so,不需要再鑽牛角尖了吧!

保證被關聯的字段需要有索引

這句話很好了解吧,如果t1,t2表,如sql語句:

join和子查詢效率_從阿裡手冊引出的Join查詢思考

你可能會問straight_join是什麼? 他和join有什麼差別呢?

好吧,你既然問到了,我就還是說下,如果你使用join,Mysql優化器可能會選擇t1或者t2來作為驅動表,而我使用的是straight_join,那麼關系很明确了,t1是驅動表,那t2就是被驅動表。

既然語句知道被驅動表了,那被關聯的字段就是t2.a,按照規範的要求,必須在t2表的a列上必須建立有索引。

t1是驅動表,我從t1表裡面取出資料後,再去t2表查詢:

·

如果t2.a有索引,我根據索引查詢就好,查詢了結果合并t1表的記錄傳回。

·

如果t2.a沒索引,那麼就尴尬了,需對t1表裡面的所有資料都需要在t2表進行一次全表掃描,如果t1是1000行資料,t2是10000,那得掃描多少行呢?結果是(t1行數*t2行數)1000萬。

這個時候我相信你也已經了解為什麼被關聯的字段需要有索引了吧。

join和子查詢效率_從阿裡手冊引出的Join查詢思考