2011-03-28 39 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的性能问题是测试它的工作负载下,看看说明计划给出,如果性能满足您的要求。测试几个选项,看看它是如何影响解释计划和性能的(在大多数情况下,也就是完成时间)。我发现如果你能用真正的测试来证明它,你甚至不需要对数据库有太多了解。这并不知道怎么没有价值,但是世界上所有的知道如何很少击败真实的世界测试。