2009-12-23 54 views
3

我知道如何使用索引(clustured和非clustured) 但是,当我应该在我的表中使用非clustured索引。 应该有什么样的场景,以便使我的列无法显示索引。 我已经通过msdn的指导,但仍有点混乱。定义索引:哪些列和性能会影响?

我应该只做唯一的列作为NC或应该有任何其他列也作为NC。

如果我用NC指数超载我的表,那么它会降低我的表现吗?

我应该在外键列上使用复合非C索引吗?

我知道主键应该是Clustured,唯一键应该是NC,但外键是什么。

+0

已编辑问题,已添加2条更多信息 – 2009-12-23 18:20:41

回答

4

您每个表只能有一个聚簇索引。它不一定是主要关键,但在大多数情况下会是。

除此之外 - 它确实取决于查询& tipping point for what indexes will be used。但是定义索引也意味着会对DML产生影响 - 插入,删除更新会稍微影响性能。

我应该在外键的列上使用复合非聚集索引吗?

列的内容无关紧要,优化器决定使用哪种索引,集群或其他方式的用法很重要。

2

是的,你可以用太多的索引来重载你的表。一般来说,每个额外的索引都会在索引维护方面花费性能时间。大量更新的表通常应该具有较少的索引。

另一个广泛的规则(来自Richard Campbell,在RunAs Radio和DotNetRocks上)是,一些宽泛的索引会比大量的窄索引表现更好。广泛的索引将涵盖更广泛的查询,查询优化器调查的次数更少。请记住,查询优化器的运行时间有限。

调查SQL Server事件探查器。那里有工具(以前是独立的,但它们已经改变了,我最近没有用过它们)。他们可以分析工作量并制定索引建议。这些将是比“直观地选择”的指标更好的选择。

0

如果您的查询引用了不在索引中的列,那么SQL Server引擎将不得不执行表查找以从实际表中获取不包含的列。

如果您经常运行这些查询,则应通过在索引中包含所有引用列来创建“覆盖”查询的非聚簇索引。这应该包括任何非唯一的列。

向表中添加索引会降低写入性能,因为每次更新表时索引都必须更新。

0

你在做什么字段查找?搜索?等等。 确定您在运行查询时使用的字段(WHERE子句) 并且它们可能是很好的候选人。

例如,想一想图书馆。图书目录有一个用于ISBN编号的聚集索引和一个用于出版年的非聚集索引等等。

另外,Bart Duncan发表很久以前发布的东西。 他值得赞扬。

该文章的标题是“您使用SQL的缺失索引DMV吗?”。查询并运行此查询:

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 

这不是您的最终解决方案,但它会帮助您确定一些索引。 并链接到文章:http://blogs.msdn.com/bartd/archive/2007/07/19/are-you-using-sql-s-missing-index-dmvs.aspx。默认情况下,当你在SQL Server中创建一个PK时,默认情况下它是聚簇索引,它不一定是,但通常是。

8

集群索引定义了您的表的物理结构(某种程度上) - 例如,它定义了数据排序的顺序。想想电话簿,它由(姓氏,名字)“聚集” - 至少在大多数国家是这样。

您每个表只能获得一个聚簇索引 - 所以明智地选择它!根据Queen of Indexing, Kimberly Tripp的福音,聚类关键应该是狭窄的,稳定的(永不改变),独特的(是!),并且理想的是不断增加。

它应该很窄,因为集群密钥将被添加到每个非聚集索引的每个条目 - 毕竟,集群密钥是用于最终找到实际数据的值。

它应该是稳定的,因为不断更新大量的索引值是一件昂贵的事情 - 尤其是因为聚簇键也必须在所有非聚集索引中更新。

它需要是唯一的,因为它再次 - 它最终是用于定位实际数据的值。如果你选择一个不保证是唯一的列,SQL Server将通过向它添加一个4字节值来“分离”你的集群密钥 - 这不是一件好事。

理想情况下,群集密钥应该不断增加,因为这会导致最少的页面和索引碎片,因此最适合于性能。

群集键的理想候选人将是一个INT(或BIGINT)身份 - 它理想地满足所有这些要求。

至于非聚集索引 - 使用和明智地选择它们!我只能给出一条通用规则:属于外键(引用另一个表)的所有列应该位于索引中 - SQL Server不会(与流行的观点和大量的神话相反)将这样的索引放置到位自动 - 永远不会,永远不会。

除此之外 - 你需要关注你的系统,看看你有什么样的查询 - 所有列出现在WHERE或SORT子句中的列都是可能被索引的列 - 但是太多索引不是好东西事情要么....

+1

希望我可以多次投票。很好的答案! – 2009-12-23 19:10:56

+0

@CylonCat:非常感谢!很高兴它对某人 – 2009-12-23 19:26:02

+0

+1非常有用,可以解释很多问题。没有接受bcoz OMG Ponies提供了一个非常好的链接,以便更多地了解非Clustured指数 – 2009-12-23 19:30:23

0

如果您还是不使聚簇索引取决于你的工作量(通常通过点击表格中的数量和种类的SELECT语句为主)

可根据聚簇索引将强制行的磁盘存储以到聚集索引值。 (因为这个原因,每个表只能有一个聚簇索引,因为行只存储在磁盘上一次)如果大多数查询总是要求一组相关的行,那么这很有意义。

示例:假设您正在存储CustomerOrders,并且您经常想知道某个时间段内CustomerOrder的数量(不管客户)。在这种情况下,创建一个OrderDate作为第一列的群集索引可能很有用。另一方面,如果您经常使用相同的CustomerId查找所有CustomerOr,则将CustomerId作为第一列放入聚簇索引中更有意义。

聚簇索引的缺点不在于聚簇索引本身,而是在二级索引上:二级索引本身没有聚集(根据定义,因为行只能存储一次,并且按聚簇的顺序存储索引),并且它们的索引条目指向聚集索引的索引条目。因此,通过二级索引检索一行需要2次读操作:二级索引之一,然后是它指向的聚簇索引之一。

+0

我mrested只在非Clustured指数。我想xpore NCI,因为他们可以很多 – 2009-12-23 18:29:01