我如何知道是否应该在聚簇索引或堆上创建非聚簇索引?

时间:2014-10-15 12:07:22

标签: sql-server sql-server-2008-r2 database-performance

我有一个包含一些表的数据库,没有表定义了非聚集索引。使用此DB的大应用程序很慢(因为行数接近一百万)。我想通过添加索引来优化数据库提取操作。当我读到索引时,我遇到了索引名称,如:

  • 聚集索引
  • 聚集索引上的非聚簇索引
  • 堆上的非聚集索引

此外,只需要在某些列上创建索引。如何在表中确定需要创建哪种索引以及哪些列?

P.S。运行查询时的执行计划告诉您在所有列上创建NCI。我可以盲目地继续按照SQL Server的建议创建索引吗?

2 个答案:

答案 0 :(得分:1)

聚集索引是一种索引,它定义了如何存储表的数据(更准确地说,数据的排序方式)。这就是为什么应该非常仔细地选择聚簇索引列的原因(顺序插入的数据是原始的,或者随着时间的推移最终会出现碎片和性能问题,整数" identity"列是一个不错的选择,例如)。 我发现在永久表上总是有一个聚簇索引是一个好习惯。

没有聚集索引的表是一个堆,因为数据没有按特定方式排序(它将被添加到文件的末尾),因此数据难以检索。使用没有索引的堆可以获得的唯一改进是数据插入会更快。

非群集索引是一个单独的文件,可以帮助您加快对所选列的查询速度(它将存储索引数据的值及其对主文件中位置的引用)。随着表的数据变得越来越重要,拥有这些单独的文件可以显着提高查询的性能,因为数据库引擎不必扫描整个表以查找您要查找的数据,但只需查看用于在索引文件中检索的行的位置(其中包含您已选择的列的有序数据)。 添加索引将加速您的选择查询,但由于必须更新索引,因此减慢了写入操作的速度。 因此,不要在太多列上创建太多索引!

答案 1 :(得分:1)

有两种类型的表:堆表(没有聚簇索引)和聚簇表(聚合表)。其中每个都可以在它们上构建任意数量的非聚集索引。

什么时候使用堆表?实际上,仅在一种情况下:当您进行并行批量导入时。此特定方案要求表没有聚簇索引。在所有其他情况下,堆表的性能比具有聚簇索引的表更差 - 尽管如此:不要相信我的话:Microsoft有一个article on this,虽然过时了但仍然相关。换句话说,对于大多数实际的数据库工作,您可以忽略堆表作为好奇心。

您创建聚簇索引的内容是什么?理想情况下,在具有不断增加(或减少)值且未在更新中更改的值的列上。为什么?因为这具有更少的更新开销,因为不必移动数据。由于这两个要求,IDENTITY列形式的代理键很受欢迎,因为它们可以很好地满足它们。这当然不是唯一可能的选择:对不断增加的时间戳进行索引也很受欢迎(例如,在大数据仓库中)。

如果(大部分)不在此,您如何决定要编入索引的其他列?现在这是一个很好的问题,但没有一个我觉得有资格回答这里的所有荣耀。多年来我自己在索引设计方面积累了很多经验,但我不知道我可以推荐的具体书籍或文章(这并不是说它们不存在,我希望其他人可以编钟在提出建议)。对于它的价值,微软本身有written a guide here,这是非常深入的(也许太多),但我自己并没有彻底阅读。

您可以盲目地继续按照查询优化器的建议创建索引吗?如果你的意思是“我应该”,那么答案几乎肯定是否定的。查询优化器非常渴望建议和所有可能加速查询的索引,但这并不意味着它们都应该被创建 - 每个索引都会增加在表上执行插入和更新的开销。如果你遵循优化器的建议,你很可能最终会得到涵盖每个可能的列组合的索引,这对于任何不是SELECT查询的事情来说都是非常可怕的。话虽如此,创建太多索引几乎总是不像创建任何索引那样糟糕,因为这会快速杀死涉及超过大约10,000行的表的大多数查询的性能。

我可以写关于这个主题的书,但我没有时间或(我担心)技能。我希望这至少可以让你开始。