2009-12-10 63 views
12

我想知道是否有這兩個選項之間的真正性能增益:SQL加入VS在代碼單獨的查詢,而不加入 - 性能

選項1:

  • 我做一個SQL查詢與加入以選擇所有用戶及其等級。

選項2:

  • 我做一個SQL查詢來選擇所有用戶
  • 我獲取所有用戶,做一套SQL查詢來獲取該用戶的行列。

在代碼中,選項二更容易實現。這只是因爲我設計我的持久層的方式。

所以,我想知道對性能有什麼影響。在考慮採取選項1而不是選項2的情況下,我應該考慮什麼限制?

回答

12

一般而言,數據庫服務器在加入時總是比應用程序代碼快。請記住,您必須爲每個連接執行一次額外的網絡往返查詢。但是,如果您的第一個結果集很小並且您的索引調整得很好,那麼此模型可以正常工作。

如果你只是這樣做來重新使用你的ORM解決方案,那麼你可能正在爲一場失敗的戰鬥而戰。我總是發現我需要只能使用SQL生成的只讀數據集,所以現在我使用ORM進行每個對象的CRUD操作,並使用常規SQL進行搜索,報告,聚合等。

+0

往返是什麼意思?好奇心,你用什麼ORM? – Melursus 2009-12-10 21:53:30

+0

往返意味着從應用程序轉到數據庫服務器並返回。當你在應用程序中加入,你在一個循環中運行子查詢,即在運行ñ額外查詢/往返,它做的非常糟糕 – 2009-12-10 22:49:35

+0

沒錯。如果你的第一個查詢總是要具有行的理智最大數(比如說,超級模特國際象棋冠軍)和子表是速度快,小的(就像他們的孩子的名字),然後在應用程序中加入不具有大後果。如果聯結很大或持續增長(所有客戶和訂單),那麼在您轉移到其他方面後,生產會變得很難看。 – 2009-12-11 17:48:16

0

這取決於您預計有多少用戶。選項一定會更快,但有了合理數量的數據,差異將可以忽略不計。

+0

每天往返傷害,即使有隻有10或20個用戶,你正在做的比需要 – 2009-12-10 19:33:55

1

如果等級是靜態值,請考慮將它們緩存到應用程序中。

如果您需要頻繁使用用戶並且排名很少,請考慮延遲加載排名。 (例如,單獨的查詢,但第二個查詢僅偶爾使用)。

如果您總是需要這兩組數據,那麼它們必須是數據庫的當前副本。

原型可能的選擇,並運行性能測試。

編輯:關於你的持久層的進一步想法,因爲我自己面對這個。考慮將處理連接的「持久性」類添加爲基本查詢,並且是隻讀的。這是否適合您的特定場景是由您決定的,但許多應用程序的很多數據庫訪問都基於聯接,​​聯接可能相當大且複雜。如果你能夠以一致的方式處理這些持久的,可更新的對象,那麼它對你的整體架構來說可能是一個巨大的勝利。從概念上來說,這很像是在數據庫中查看視圖,查詢視圖而不是編寫聯接,但是您在代碼中完成所有工作。

+0

你有你的「Persitence狀」類的一些例子或鏈接大量的工作? – Melursus 2009-12-10 21:55:31

+0

沒有什麼我可以在線發佈,因爲他們還沒有寫!我編寫了實體類,其行爲與LINQ to SQL實體非常相似,但是由「經典」ADO.NET代碼填充。我也有活動記錄類封裝表級查詢和數據訪問代碼,並生成INSERT和UPDATE語句。 Active Record類從DataSet中填充實體。實體類包含支持ActiveRecord函數的元數據。我們將在未來使用代碼生成器來構建這些代碼。相同的結構應該適用於複雜的查詢。希望我可以使用LINQ,但我不能。 – 2009-12-10 22:36:42

0

在99%的情況下,加入會更快。

但是有一種情況可能會比較慢。如果您正在進行一對多的大行連接,並且您正在達到網絡帶寬限制。

例如有在1MB大小的T1 BLOB列,要加入T2其由100行對於每個T1行。結果集將是T1行計數倍數100.

所以,如果你正在查詢一個T1行加入它將是100MB的結果集,如果你取T1行(1MB),然後做單獨的選擇以獲取100 T2的這個T1的結果集將爲1MB。