2012-04-22 95 views
-1

我有一個表SpecialOffers並表的特別優惠項目叫做SOItems ,我希望得到一個特定項目的優惠,如果我發現它首先,我這樣做:多SQL查詢或連接?

IF EXISTS(SELECT * FROM SOTtems WHERE ItemType = 2 AND Itemid = @id) 
BEGIN 
     INSERT INTO #SO 
     SELECT * FROM SpecialOffers so 
     INNER JOIN SOItems soi ON so.Id = soi.SpecialOfferID 
     WHERE soi.ItemType = 2 AND soi.Itemid = @id 
END 

但隨後擺脫的INNER JOIN因爲我認爲這是對性能我這樣做更好:

DECLARE @specialOfferID INT 

SET @specialOfferID = (SELECT SpecialOfferID FROM SOTtems WHERE ItemType = 2 AND Itemid = @id) 

IF @specialOfferID IS NOT NULL 
BEGIN 
    INSERT INTO #SO 
    SELECT * FROM SpecialOffers so 
    WHERE ID = @specialOfferID 
END 

因此,這是更有效和性能來執行更多的SQL查詢或使用加入了這個例子,一般

更好

注:在存儲過程中我寫我有這個6倍多,這就是爲什麼我問ü:)

感謝

回答

1

這手優化可能是不必要的,因爲優化超過能夠處理這一點。

您可以將兩者都放入SSMS並將它們一起運行並查看執行計劃中的相關成本。

避免連接通常不是優化的第一步。

我的第一步通常是查看索引策略,並確保我沒有遺漏基本索引,然後查看執行計劃並查看是否存在明顯的問題。

然後,我不會優化,直到我有一個實際的性能問題 - 然後才瞭解什麼是真正導致性能問題。

我真的把它簡化到只:

INSERT INTO #SO 
SELECT * 
FROM SpecialOffers so 
INNER JOIN SOItems soi 
    ON so.Id = soi.SpecialOfferID 
    AND soi.ItemType = 2 
    AND soi.Itemid = @id 

這就是它 - 沒有EXISTS支票或其他任何東西 - 內部聯接意味着生存的檢查是多餘的,因爲這會不會以其他方式將任何東西。這使得代碼具有更好的可維護性,因爲如果它發生更改,則不需要複製該條件,並且連接中的代碼不可能被意外更改。另一方面,如果加入會發生變化,則可能會產生更嚴重的影響。

請注意,您仍然可以在不使用EXISTS檢查的情況下將其編寫爲WHERE版本。

較少的代碼通常意味着缺少隱藏的地方。

+0

非常感謝我同意你的看法,但我不會優化,直到我遇到性能問題,我不同意,我的意思是如果你更好地編寫代碼,你將不會遇到性能問題,那麼您不必優化 – AlaaL 2012-04-22 13:15:55

+0

@TheDarkLord代碼需要首先正確工作,可維護並滿足基本的最佳實踐。之後的一切都是優化。但是你說的對,經過很多(14年,也許是?)年的SQL Server之後,我對基本最佳實踐的定義通常足以避免進一步的優化。 – 2012-04-22 13:26:56

+0

感謝您的幫助。 – AlaaL 2012-04-22 13:53:09

1

在Management Studio的窗口中同時過去兩個查詢,並顯示查詢的執行計劃。這將告訴你到底發生了什麼。

您很可能會看到性能差異很小。什麼可能使第二個稍微快一點是它沒有IF EXISTS(...),但另一方面,結果將被緩存,所以差異仍然很小。

另一件可以有所作爲的事情是,您正在用第一個查詢將更多數據放入#SO表中。正如您使用SELECT *,您獲得的數據比您需要的要多。例如,包含字段SOItems.SpecialOfferIDSpecialOffers.Id,但您知道它們始終是相同的。指定您希望返回的字段,以便您不會獲取比您需要的更多的字段。

+0

是的,謝謝,實際上我並沒有在真實的代碼中使用SELECT *,而是在這裏寫下來,所以我不必寫下字段的名字:) – AlaaL 2012-04-22 13:19:21

+0

@TheDarkLord:很高興聽到。 :) – Guffa 2012-04-22 13:21:04