MySQL多表關聯查詢效率高點還是多次單表查詢效率高,為什麼?


謝邀。我姑且認為題主說的是內連接。處理內連接肯定是放在資料庫上做,毫無疑問。

從內連接的角度來講,資料庫通常會實現2種執行計劃。第一種是NESTED LOOP。這種執行計劃通常用於小表關聯,能夠最大限度的減少內存開銷並儘快返回結果。第二種是HASH。這種執行計劃通常用於小表和大表關聯,或者大表和大表關聯,會有一些內存開銷,但是大數據量下的處理速度是NESTED LOOP不可比擬的。如果2張表都是十幾萬條記錄的話,資料庫的查詢優化器應該會選擇HASH JOIN來實現內連接操作。而如果關聯操作放在應用里做,幾乎所有程序員都會選擇2重循環去實現,這種邏輯是被HASH JOIN完爆的。

還有就是放在應用層做還有很大的網路開銷,主要是資料庫伺服器和應用伺服器之間的開銷。顯然,從網路開銷的角度來說,也應該把內連接放在資料庫上實現。


謝邀,成都老鄉好。。。回答這個問題,先說效率哪個更高:

A,B兩個表數據規模十幾萬,數據規模都不大,單機MySQL夠用了,在單機的基礎上要關聯兩表的數據,先說一個極端情況,A,B兩個表都沒有索引,並且關聯是笛卡爾積,那關聯結果會爆炸式增長,可能到億級別,這個時候網路IO成了瓶頸,這個時候兩次十萬行結果集的拉去可能遠小於1次億級別的結果集的拉取,那麼將關聯合併拉到service層做更快。但實際業務中一般不會有這麼蠢的行為,一般關聯會有連接條件,並且連接條件上會有索引,一般是有一個結果集比較小,拿到這個結果集去另一張表去關聯出其它信息,如果放到service層去做,最快的方式是,先查A表,得到一個小的結果集,一次rpc,再根據結果集,拼湊出B表的查詢條件,去B表查到一個結果集,再一次rpc,再把結果集拉回service層,再一次rpc,然後service層做合併,3次rpc,如果用資料庫的join,關聯結果拉回來,一次rpc,幫你省了兩次rpc,當然資料庫上做關聯更快,對應到資料庫就是一次blk nested loop join,這是業務常用情況。

但是確實大多數業務都會考慮把這種合併操作放到service層,我覺得有幾方面考慮:

第一:單機資料庫計算資源很貴,資料庫同時要服務寫和讀,都需要消耗CPU,為了能讓資料庫的吞吐變得更高,而業務又不在乎那幾百微妙到毫秒級的延時差距,業務會把更多計算放到service層做,畢竟計算資源很好水平擴展,資料庫很難啊,所以大多數業務會把純計算操作放到service層做,而將資料庫當成一種帶事務能力的kv系統來使用,這是一種重業務,輕DB的架構思路

第二:很多複雜的業務可能會由於發展的歷史原因,一般不會只用一種資料庫,一般會在多個資料庫上加一層中間件,多個資料庫之間還能做毛的join,自然業務會抽象出一個service層,降低對資料庫的耦合。

第三:對於一些大型公司由於數據規模龐大,不得不對資料庫進行分庫分表,這個問題我在《阿里為什麼要禁用三表以上的join》上也回答過,對於分庫分表的應用,使用join也受到了很多限制,除非業務能夠很好的根據sharding key明確要join的兩個表在同一個物理庫中。而中間件一般對跨庫join都支持不好。舉一個很常見的業務例子,在分庫分表中,要同步更新兩個表,這兩個表位於不同的物理庫中,為了保證數據一致性,一種做法是通過分散式事務中間件將兩個更新操作放到一個事務中,但這樣的操作一般要加全局鎖,性能很捉急,而有些業務能夠容忍短暫的數據不一致,怎麼做?讓它們分別更新唄,但是會存在數據寫失敗的問題,那就起個定時任務,掃描下A表有沒有失敗的行,然後看看B表是不是也沒寫成功,然後對這兩條關聯記錄做訂正,這個時候同樣沒法用join去實現,只能將數據拉到service層應用自己來合併了。。。


補充一下,使用join未必效率全低,曾遇到的一個慢sql調優,為方便簡單寫:步驟一,

select tableA.id as ids from tableA where age&>20;

步驟二,使用上一步的查詢結果:

select tableB.score from tableB where id in (ids);

這是一個很常見的查詢,步驟一和步驟二,相當於

select tableB.score from tableB inner join tableA on tableA.id=tableB.id;

這個效率誰高,看具體情況了。最後測試結果是inner join的效率高。

為什麼互聯網公司不讓使用join?

第一,不利於寫操作。執行讀操作時,會鎖住被讀的數據,阻塞其他業務對該部分數據的更新操作(U or D)。如果涉及多個聚合函數(緩存中沒有max or min時),相當於同時鎖住多張表,不能進行讀寫,直接影響其他業務,這影響了系統的整體性能;

第二,不利於維護。業務發生變動時,比如join中一張表改了,可能導致系統中原有的sql不可用,最終導致基於該SQL執行結果的上層顯示失敗(也意味著以往的開發工作已無效)。

如果使用步驟一和步驟二的方式,只需要修改其中一個步驟就行。實際工作中,也就是只需要修改其中的一個service(對應一張表)即可。

既影響性能,又不利於維護,所以我們盡量不要用join。另外,集團不讓用三張表,是在OLTP場景中。不要一葉障目哦,如果是在OLAP的應用場景中,使用join是非常合適的。

碼字,不容易。同意請點贊,不同意請拍磚。


關聯帶分頁

關聯查詢,索引建好,每次查詢外面套分頁,寫得好的話響應速度應該都不會到毫秒吧

震驚!慢SQL居然能優化到這種速度,我不服! @阿里云云棲社區


並非dba,個人愚見,大牛不要見笑,歡迎指正。

sql效率要具體問題具體分析,有時關聯更方便,單表反而增加了代碼複雜性,得不償失。

1 無論是單表,還是關聯查詢,最好是走索引,然後用explain分析下sql。

盡量不用in , not in 等條件。

2 阿里的開發守則里,寫了不要join超過3張表,禁止使用存儲過程。

這主要是防新手犯錯,因為資料庫的一個不小心,後果通常很嚴重。實際上我常常用存儲過程,比寫java邏輯方便的多。

join的多了以後,就很容易出現每張表挨個遍歷的情況,效率比較低,所以where條件要盡量精確定位,盡量不要用模糊查詢。

select a.email, b.name
from A a
left join B b on b.email=a.email
where a.email="1@qq.com"

這個sql,假如B是個大表,效率會很低,盡量用一個精確的多條件語句,代替B,把B的體積壓縮。

join 要做雙向檢查,效率低於left join。union all效率高於union。

具體問題具體分析,同等條件用效率稍高的語句,大表關聯時,先查一遍壓縮體積,然後再關聯。


如果是小型開發的話,其實都差不多,沒維護過太大的資料庫,不了解,不誤人子弟了。

不過我一直不喜歡關聯查詢,更喜歡把數據取來存在Array裡面,自己再處理。

個人寫代碼的習慣是把每一個功能都細化成一個個小功能,能寫兩行就不寫一行。倒不是湊行數,是這樣看起來更清楚。就跟中學時代寫理科題一樣,一步一步寫,結果錯了還有步驟分呢。


資料庫不太懂。

但是趕腳第一種選擇效率高呢。。。


看具體場景吧,都不是絕對的。

舉個極端的場景,如果mysql本身壓力很高,這個時候你的應用就適合在service合併數據;如果mysql壓力不高,在sql中合併也不錯。

當然這只是一種情況,還是那句話,看具體場景


explain打出你的執行計劃


單表對資料庫的壓力小很多吧


不說效率,單表查詢更容易緩存,這個優勢不容忽視


兩張表十幾萬數據,資料庫比你處理的更好,即便是mysql


多次單表吧…


MySQL關聯效率非常低,覺絕對不要超過三個表進行關聯


這裡的關聯查詢時指外鍵還是父子表或是其他方法?

一般在開發中需要根據業務需求來確定策略。比如在銀行等容錯率很低的場景下,使用強邏輯關聯的外鍵查詢,確保不會發生錯誤,但這樣會犧牲一定的效率;在網站查詢這種高訪問量,對響應速度比較敏感的場景,用上層代碼實現邏輯比較靈活,會提高效率,但存在出錯的可能。

上述的效率高低只是相對而言,對不同的場景有不同的表設計,查詢方式。


按照經驗 肯定是分別查詢效率高 mysql不知道怎麼實現的


MySQL的關聯查詢寫得確實一般,但是,通常也比放到應用來做要快非常多。


推薦閱讀:

如何才能招到優秀的 MySQL DBA?
分散式系統架構實戰--簡易版支付系統怎麼部署?
為什麼有關MongoDB採用B樹索引,以及Mysql B+樹做索引?

TAG:資料庫 | MySQL | 資料庫管理員DBA |