2011-03-28 64 views
1

我有一個where子句,像這樣一個SQL查詢:3個索引或單個索引與2列在SQL Server 2008中?

Where ManufacturerID = @ManufacturerID 
    AND ItemID IN (SELECT ItemID FROM @T) 
      AND RelatedItemID IN (SELECT RelatedItemID FROM @T) 

什麼會給我最好的表現還是這樣做的正確方法? 3個索引 - 每列一個或包含所有3個索引的單個索引?

這裏是SP被運行的一個更完整的VIWE:

DECLARE @T TABLE (
    [CategoryID] [int] NOT NULL, 
    [ManufacturerID] [int] NULL, 
    [ItemID] [varchar](100) NOT NULL, 
    [ItemName] [varchar](100) NULL, 
    [PhotoName] [varchar](150) NULL, 
    [ModifiedOn] [datetime] NULL, 
    [ModifiedBy] [varchar](50) NULL, 
    [IsDeleted] [bit] NOT NULL) 

    ;WITH T As 
(SELECT  CategoryID, ManufacturerID, ItemID, ItemName, PhotoName, ModifiedOn, ModifiedBy, IsDeleted 
FROM   StagingCategoryItems 
WHERE  (ManufacturerID = @ManufacturerID) 
EXCEPT 
SELECT  CategoryID, ManufacturerID, ItemID, ItemName, PhotoName, ModifiedOn, ModifiedBy, IsDeleted 
FROM   CategoryProducts 
WHERE  (ManufacturerID = @ManufacturerID) 
) 
INSERT INTO @T 
SELECT * 
FROM T 


    DELETE FROM CategoryProducts WHERE ManufacturerID = @ManufacturerID 
     AND ItemID IN (SELECT ItemID FROM @T) 
     AND CategoryID IN(SELECT CategoryID FROM @T) 

    INSERT INTO [CategoryProducts] 
      ([CategoryID] 
      ,[ManufacturerID] 
      ,[ItemID] 
      ,[ItemName] 
      ,[PhotoName] 
      ,[CreatedOn] 
      ,[CreatedBy] 
      ,[ModifiedOn] 
      ,[ModifiedBy] 
      ,[DeletedOn] 
      ,[DeletedBy] 
      ,[IsDeleted]) 
     SELECT [CategoryID] 
     ,[ManufacturerID] 
     ,[ItemID] 
     ,[ItemName] 
     ,[PhotoName] 
     ,[CreatedOn] 
     ,[CreatedBy] 
     ,[ModifiedOn] 
     ,[ModifiedBy] 
     ,[DeletedOn] 
     ,[DeletedBy] 
     ,[IsDeleted] 
    FROM [StagingCategoryItems] 
    WHERE ManufacturerID = @ManufacturerID 
    AND ItemID IN (SELECT ItemID FROM @T) 
      AND CategoryID IN(SELECT CategoryID FROM @T) 
+0

提供關於什麼是數據,您試圖查詢的內容以及完整查詢SQL的更多細節。它很難理解你在這裏試圖達到什麼。 – 2011-03-28 23:55:21

+0

這取決於此查詢的選擇列表中的內容以及總體查詢工作負載和現有索引。 – 2011-03-29 00:07:02

+0

另外,您是否通過測量確定您有性能問題? – 2011-03-29 00:24:55

回答

1
ItemID IN (SELECT ItemID FROM @T) 
AND RelatedItemID IN (SELECT RelatedItemID FROM @T) 

現在這是一個非常危險的狀況。它表示,目前項目ID是@T和RelatedItemID也是@T,但請注意,他們並沒有必須在@T同一行的條件。舉個例子,如果@T包含:

ItemID RelatedItemId 
1  2 
3  4 

,並在表中你有一個像行:

ItemID RelatedItemId 
1  4 

WHERE條件將是TRUE。你確定這是你想要的分辨率嗎?

至於原來的指標問題:不幸的是,答案是「這取決於」。大量的索引組合可能很好,而且根據您的實際數據,完全相同的索引可能很糟糕。當接近像你這樣的問題時,你需要問自己「哪種情況最具限制性,以及限制性如何?」這個問題。

假設您的ManufacturerID = @ManufacturerID將候選行的數量限制爲大約10%(例如,您有10個不同的製造商),則ItemID IN (SELECT ItemID FROM @T)平均限制爲100行的恆定大小,最後一個條件也相同。那麼即使是一個單一的索引ItemID就足夠了。特別是如果是聚集索引,但即使是NC指數,你也在談論平均100個關鍵查找,這是一個小改變。

但是現在讓我們說說你的ManufacturerID = @ManufacturerID會限制候選行的數量到10%左右,ItemID IN (SELECT ItemID FROM @T)限制到總行數的大約5%,最後一個條件也是這樣,但是所有三個條件的精確匹配只有0.0001%的行。現在沒有單列索引 會有所幫助,您需要包含所有三個索引。按什麼順序?很好的問題。

我推薦你去看General Index Design Guidelines

+0

感謝您的洞察力,特別是我遇到的危險情況 - 任何關於如何排除該問題的指針? – Slee 2011-03-29 01:42:13

-1

一個,由於其他兩個是表變量。

任何SQL服務器(PostgreSQL系統,Oracle,MySQL等....)
0

的一般規則不只是微軟SQL Server的性能問題是測試它的工作負載下,看看說明計劃給出,如果性能滿足您的要求。測試幾個選項,看看它是如何影響解釋計劃和性能的(在大多數情況下,也就是完成時間)。我發現如果你能用真正的測試來證明它,你甚至不需要對數據庫有太多瞭解。這並不知道怎麼沒有價值,但是世界上所有的知道如何很少擊敗真實的世界測試。