Mysql

一個大查詢還是多個小查詢哪個更快?

  • June 20, 2020

我一直在為不同的公司工作,我注意到他們中的一些人更喜歡將視圖與所有“親戚”連接起來。但有時在應用程序中,我們只需要使用 1 列。

那麼只進行簡單的選擇,然後在系統程式碼中“加入”它們會更快嗎?

該系統可以是 php、java、asp 或任何連接到數據庫的語言。

所以問題是,從伺服器端(php、java、asp、ruby、python ……)到數據庫並執行一個獲取我們需要的一切的查詢或從伺服器端到數據庫並執行的更快一次只能從一個表中獲取列的查詢?

可以解決您的問題的是主題 JOIN DECOMPOSITION。

根據本書第209頁

高性能 MySQL

您可以通過執行多個單表查詢而不是多表連接來分解連接,然後在應用程序中執行連接。例如,而不是這個單一的查詢:

SELECT * FROM tag
JOIN tag_post ON tag_post.tag_id = tag.id
JOIN post ON tag_post.post_id = post.id
WHERE tag.tag = 'mysql';

您可能會執行以下查詢:

SELECT * FROM tag WHERE tag = 'mysql';
SELECT * FROM tag_post WHERE tag_id=1234;
SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904);

你到底為什麼要這樣做?乍一看這看起來很浪費,因為您增加了查詢的數量而沒有得到任何回報。然而,這種重組實際上可以帶來顯著的性能優勢:

  • 記憶體可以更有效。許多應用程序記憶體直接映射到表的“對象”。在這個例子中,如果帶有標籤mysql的對像已經被記憶體,應用程序將跳過第一個查詢。如果您在記憶體中找到 ID 為 123、567 或 908 的文章,您可以將它們從IN()列表中刪除。查詢記憶體也可能受益於這種策略。如果只有一張表經常更改,分解連接可以減少記憶體失效的次數。
  • 單獨執行查詢有時可以減少鎖爭用
  • 在應用程序中進行連接可以通過將表放置在不同的伺服器上來更輕鬆地擴展數據庫。
  • 查詢本身可以更有效。在這個例子中,使用IN()列表而不是連接可以讓 MySQL 對行 ID 進行排序,並比使用連接更優化地檢索行。
  • 您可以減少冗餘行訪問。在應用程序中進行連接意味著每行只檢索一次。而查詢中的連接本質上是一種非規範化,可能會重複訪問相同的數據。出於同樣的原因,這種重組也可能會減少總網路流量和記憶體使用量。
  • 在某種程度上,您可以將此技術視為手動實現雜湊連接,而不是 MySQL 用來執行連接的嵌套循環算法。散列連接可能更有效。

因此,當您記憶體和重用來自早期查詢的大量數據、跨多個伺服器分發數據、用IN()列表替換連接或一個連接多次引用同一個表時,應用程序中的 dos 連接會更有效。

觀察

我喜歡第一個要點,因為 InnoDB 在交叉檢查查詢記憶體時有點笨拙。

至於最後一個要點,我在 2013 年 3 月 11 日寫了一篇文章(在 JOIN 條件和 WHERE 條件之間存在執行差異嗎?),描述了嵌套循環算法。讀完之後,你會看到連接分解可能有多好。

至於書中的所有其他觀點,開發人員確實將性能作為底線。有些依賴外部手段(應用程序之外)來增強性能,例如使用快速磁碟、獲得更多 CPU/核心、調整儲存引擎和調整配置文件。其他人會屈服並編寫更好的程式碼。有些人可能會求助於在儲存過程中對所有商業智能進行編碼,但仍然不應用連接分解(請參閱反對或支持將應用程序邏輯放入數據庫層的論據是什麼?以及其他文章)。這完全取決於每個開發者商店的文化和容忍度。

有些人可能對性能感到滿意,不再接觸程式碼。其他人根本沒有意識到如果他們嘗試加入組合可以獲得很大的好處。

對於那些願意…

試一試 !!!

Postgres(可能還有任何類似程度的 RDBMS,程度較小的 MySQL)中,更少的查詢幾乎總是快得多

在大多數情況下,解析和計劃多個查詢的成本已經超過了任何可能的收益。

更不用說要在客戶端完成的額外工作,結合結果,這通常慢得多。RDBMS 專門從事此類任務,並且操作基於原始數據類型。無需轉換text為中間結果或轉換為客戶端的本機類型,這甚至可能導致不太正確(或不正確!)的結果。想想浮點數……

您還可以在數據庫伺服器和客戶端之間傳輸更多數據。對於一手充滿價值的牌來說,這可能可以忽略不計,或者產生巨大的差異。

如果多個查詢意味著到數據庫伺服器的多次往返,您還會收集多次網路延遲和事務成本,甚至可能是連接成本。大,大損失。

根據您的設置,僅網路延遲就可能比其他所有延遲時間長幾個數量級。

關於 SO 的相關問題:

非常大、長時間執行的查詢可能會有一個轉折點,因為事務會在途中收集數據庫行上的鎖。非常大的查詢可能會長時間持有許多鎖,這可能會導致並發查詢的摩擦。

引用自:https://dba.stackexchange.com/questions/76973