2008-10-30 88 views
12

显然(methinks),在BIT列上创建索引是不必要的。但是,如果您有需要搜索的列,那么每个值都可能是唯一的,例如BlogPostStreetAddress或其他东西,则索引似乎是合适的(再次,methinks)。何时创建新的SQL Server索引?

但是什么是临界值?如果你期望10,000行,你会有大约20个独特的值。应该创建索引吗?

在此先感谢。

回答

15

对此的最佳答案是分析您的查询并查看索引是否改进您的查询。回答这个问题的困难在于几乎不可能概括查询优化器的行为。这就是说,一个经验法则是,如果您的选择性对于某个表上的给定查询的选择性为10%或更低,那么您很可能会从索引中受益。因此,在您的示例中,如果您的值均匀分布,可能从受益。但是,考虑到你的桌子很小,所以你的表现提升可能可以忽略不计。

这不是一条硬性规则,因为有很多因素可以改变10%的数字,包括使用聚集或其他索引类型,行的大小,如果某些列不内联,查询结构等。

还要记住,插入带有索引的表中存在显着的性能损失。如果此表经常更新或追加,则来自索引的速度提升可能会被较慢的插入和更新所抵消。

请参阅Tablescan vs Index access上的MSDN文章。

编辑:正如其他人指出的,如果您正在执行聚合查询(例如计算特定值出现的次数),则您的查询可能从索引中受益。如果您经常在特定列上排序,您可能也会受益。

1

在您建议的列中,将有理由为数据创建引用或查找表以避免数据冗余。这将使您的列成为外键,指向新查找表的PK。

应对所有外键列进行索引。

否则,我会避免在正常情况下在这样的列上放置索引。

1

BIT列上创建索引是不必要的。

你会感到惊讶。

我已经像一个查询创建涉及有点列的索引:

SELECT foo.Name FROM foo WHERE foo.Active = 1 

有此表约有300,000行虽然。

+0

多大比例行确实比其他可能的值活动= 1代表什么?我怀疑这是整个表格的一个相对较小的子集。 – 2008-10-30 14:33:27

+1

它不起作用。我已经尝试过并且有MS确认 - 无论比例如何,低基数指数都被忽略。 – dkretz 2008-11-08 23:21:09

2

詹姆斯撞在了头上。我只是补充一点,即使是一个列可能会从索引中受益,具体取决于您如何使用该表。例如,如果您需要统计一天中有多次的行数,那么可以使用索引。索引并不总是找到一条记录 - 它们也可以用于聚合。

0

我想说这一切都取决于如何使用表和整个系统的要求。例如,如果它是大JOIN的一部分,并且父类是一个巨大的报表类型表,那么您肯定会希望索引。如果它与数据库中的其他表相比相对较小,并且它被大量插入并且很少被读取,则索引可能不是期望的。

但是,整个数据库与可分配资源之间的操作范围是关键的决定因素。这就是这个表格+可能的索引在整个系统中的行为,而不是你所有的其他表格和他们的需求。如果你不考虑大局,你可以通过试图应用一些任意的规则来杀死整个系统,只是为了应用任意规则。

2

基数低的索引是非常有问题的。如果只有几个可能的值,SQL Server几乎总是进行索引扫描,无论比例如何。

例如:我有一个表只有接受“A”,“N”和“R”值的State字段(对于Active,New和Retired)。通常情况下,其中95%是“R”,4 +%是“A”,少数是“N”。 SELECT WHERE state ='N'将进行表扫描,无论如何。

但 - 有一种新的索引类型,称为Filtered Index,最终处理这种情况。当你想排除具有NULL值的记录时,它也很方便。

0

如果你开始在查询中遇到死锁,你通常应该在SELECT和INSERT/UPDATE之间仔细检查你的索引。索引选择不当可能会导致死锁,因为根本无法获得索引。有关其他信息,请参阅this knowledge base文章。通常,添加索引或修改其包含的列将有助于解决此类死锁问题。一定要检查受影响的查询的查询计划。

0

的最好办法之一是使用在SQL Server MVP的观点我sugest不要重新启动服务器一个星期,然后再运行此查询:

USE master; 
Go 
SELECT d.database_id, 
    d.object_id, 
    d.index_handle, 
    d.equality_columns, 
    d.inequality_columns, 
    d.included_columns, 
    d.statement AS fully_qualified_object, 
    gs.* 
FROM sys.dm_db_missing_index_groups g 
JOIN sys.dm_db_missing_index_group_stats gs ON gs.group_handle = g.index_group_handle 
JOIN sys.dm_db_missing_index_details d ON g.index_handle = d.index_handle 

Go 

SELECT mig.index_group_handle, 
    mid.index_handle, 
    migs.avg_total_user_cost AS AvgTotalUserCostThatCouldbeReduced, 
    migs.avg_user_impact AS AvgPercentageBenefit, 
    'CREATE INDEX missing_index_' + CONVERT (varchar, mig.index_group_handle) 
    + '_' + CONVERT (varchar, mid.index_handle) 
    + ' ON ' + mid.statement 
    + ' (' + ISNULL (mid.equality_columns,'') 
    + CASE 
     WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns 
     IS NOT NULL THEN ',' 
     ELSE '' 
    END 
    + ISNULL (mid.inequality_columns, '') 
    + ')' 
    + ISNULL (' INCLUDE (' + mid.included_columns + ')', '') AS create_index_statement 
FROM sys.dm_db_missing_index_groups mig 
INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle 
INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle 
Order By migs.avg_user_impact Desc 

然后验证表,并创建requerd指数。

0

已经在这里发布了很好的答案...只需添加我的两分钱....执行失踪索引DMV并查看您提到的表是否被列为创建新索引的候选人并查看定义该指数。

Are you using SQL's Missing Index DMVs?

SELECT 
    migs.avg_total_user_cost * (migs.avg_user_impact/100.0) * (migs.user_seeks + migs.user_scans) AS improvement_measure, 
    'CREATE INDEX [missing_index_' + CONVERT (varchar, mig.index_group_handle) + '_' + CONVERT (varchar, mid.index_handle) 
    + '_' + LEFT (PARSENAME(mid.statement, 1), 32) + ']' 
    + ' ON ' + mid.statement 
    + ' (' + ISNULL (mid.equality_columns,'') 
    + CASE WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns IS NOT NULL THEN ',' ELSE '' END 
    + ISNULL (mid.inequality_columns, '') 
    + ')' 
    + ISNULL (' INCLUDE (' + mid.included_columns + ')', '') AS create_index_statement, 
    migs.*, mid.database_id, mid.[object_id] 
FROM sys.dm_db_missing_index_groups mig 
INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle 
INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle 
WHERE migs.avg_total_user_cost * (migs.avg_user_impact/100.0) * (migs.user_seeks + migs.user_scans) > 10 
ORDER BY migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC