如何在SQL Server中为此方案创建索引?

时间:2017-01-22 09:22:38

标签: sql sql-server stored-procedures indexing

以下查询的Item table的最佳索引是什么

select 
    tt.itemlookupcode,
    tt.TotalQuantity,
    tt.ExtendedPrice,
    tt.ExtendedCost,
    items.ExtendedDescription,
    items.SubDescription1,
    dept.Name,
    categories.Name,
    sup.Code,
    sup.SupplierName

from 
    #temp_tt tt

left join HQMatajer.dbo.Item items
on items.ItemLookupCode=tt.itemlookupcode

left join HQMatajer.dbo.Department dept
ON dept.ID=items.DepartmentID

left join HQMatajer.dbo.Category categories
on categories.ID=items.CategoryID

left join HQMatajer.dbo.Supplier sup
ON sup.ID=items.SupplierID

drop table #temp_tt

我创建了像

这样的索引
CREATE NONCLUSTERED INDEX [JFC_ItemLookupCode_DepartmentID_CategoryID_SupplierID_INC_Description_SubDescriptions] ON [dbo].[Item]
(
    [DBTimeStamp] ASC,
    [ItemLookupCode] ASC,
    [DepartmentID] ASC,
    [CategoryID] ASC,
    [SupplierID] ASC
)
INCLUDE (   
    [Description],
    [SubDescription1]
)

但是在执行计划中,当我检查选择另一个索引的索引时。该索引只有TimeStamp column

此方案对该特定表的最佳索引是什么。

2 个答案:

答案 0 :(得分:2)

索引中的第一列应该是过滤的一部分,否则将不使用Index。在您的索引中,第一列是[Description],[SubDescription1],并且不会在您的查询中对其进行过滤。这就是你的索引没有被使用的原因。

同样在覆盖索引中,您使用了ExtendedDescription,items.SubDescription1,但在查询中,您选择了key/Rid lookup,这将增加CREATE NONCLUSTERED INDEX [JFC_ItemLookupCode_DepartmentID_CategoryID_SupplierID_INC_Description_SubDescriptions] ON [dbo].[Item] ( [ItemLookupCode] ASC, [DepartmentID] ASC, [CategoryID] ASC, [SupplierID] ASC ) INCLUDE ( [ExtendedDescription], [SubDescription1] )

的开销

尝试像这样提醒您的索引

Item

已经说过所有仍然优化器都会根据从$icon = $loader->fromFile('/path/to/icon.ico'); foreach ($icon as $idx=>$image) { $im=$loader->renderImage($image); $filename=sprintf('img%d-%dx%d.png', $idx, $image->width, $image->height); imagepng($im, $filename); printf("rendered %s as %s\n", $icon->getDescription(), $filename); }

中检索到的数据进行扫描或选择其他索引

答案 1 :(得分:1)

我对你的索引没有使用感到惊讶。 DBTimeStamp可能具有高度选择性,根本不会在您的查询中引用。

您可能忘记在查询中包含ORDER BY子句,该子句旨在引用DBTimeStamp。但即便如此,您的查询可能还需要扫描整个索引。所以它也可以扫描实际的表格。

使该指数看起来诱人的唯一方法是'将确保它包含使用/返回的 所有 列。即您需要添加ExtendedDescription这可以提供帮助的原因是索引通常比完整表需要更少的存储空间。所以从磁盘读取速度更快。但是,如果您缺少列(在您的情况下为ExtendedDescription),那么无论如何,引擎都需要在整个表格上执行额外的查找。

我无法评论为什么DBTimeStamp列是首选的 - 您还没有给出足够的详细信息。但也许它是CLUSTERED索引?

如果定义为:

,您的索引几乎肯定会被使用
(
    [ItemLookupCode] ASC --The only thing you're actually filtering by
)
INCLUDE (
    /* Moving the rest to include is most efficient for the index tree.
       And by including ALL used columns, there's no need to perform
       extra lookups to the full table.
    */
    [DepartmentID],
    [CategoryID],
    [SupplierID],
    [ExtendedDescription],
    [SubDescription1]
)

但请注意,这种索引策略'找到最适合每个查询使用的'是不可持续的。

  • 你最好找到更窄的'适合多个查询的索引。
  • 每个索引都会降低INSERT和UPDATE查询的速度。
  • 这样的索引会受到更多列的影响而不是首选的“更窄”的列。索引。

索引选择应关注列的选择性。即给定特定值或小范围的值,根据您的查询可能选择的数据百分比

在您的情况下,我希望ItemLookupCodeItems表格中 每个项目唯一 。换句话说,通过进行索引而没有任何包含 应该足够 。但是,由于您已加入临时表,理论上可能包含所有项目代码:在某些情况下,扫描CLUSTERED INDEX可能更好无论如何。