SQL Server聚簇索引 - 索引问题的顺序

时间:2008-12-05 15:01:27

标签: sql sql-server database performance indexing

我有一张这样的表:

keyA keyB data

keyA和keyB一起是唯一的,是我的表的主键,并构成聚簇索引。

keyB有5个可能的值,但keyA的可能值不限。 keyB通常递增。

例如,以下数据可以按两种方式排序,具体取决于首先订购的键列:

keyA keyB data
A    1    X
B    1    X
A    3    X
B    3    X
A    5    X
B    5    X
A    7    X
B    7    X

keyA keyB data
A    1    X
A    3    X
A    5    X
A    7    X
B    1    X
B    3    X
B    5    X
B    7    X

我是否需要告诉聚簇索引哪些键列具有较少的可能值,以允许它首先按该值对数据进行排序?或者在首先订购的性能方面无关紧要?

9 个答案:

答案 0 :(得分:13)

您应首先使用最具选择性的列来排序复合聚簇索引。这意味着具有最明显值的列与总行数相比。

“B * TREE索引提高了从表中选择一小部分行的查询的性能。” http://www.akadia.com/services/ora_index_selectivity.html

本文适用于Oracle,但仍然相关。

此外,如果您有一个不断运行并返回少量字段的查询,您可以考虑创建一个包含所有字段的复合索引 - 它不必访问基表,而是从索引中提取数据。

ligget78关于确保在复合索引中提及第一列的评论非常重要。

答案 1 :(得分:7)

如果使用(keyA,keyB)创建索引(无论是否为聚簇),那么这就是如何对值进行排序,例如:第一个keyA,然后是keyB(这是你问题中的第二个案例)。如果你想要反过来,你需要指定(keyB,keyA)。

在性能方面可能很重要,当然取决于您的查询。例如,如果你有(keyA,keyB)索引,并且查询看起来像WHERE keyB = ...(没有提到keyA)那么就无法使用索引。

答案 2 :(得分:2)

正如其他人所说,排序是基于您在索引创建脚本(或PK约束)中指定它的方式。关于聚簇索引的一件事是,要记住很多事情。

通过在PK以外的其他内容上使用聚集索引,可以获得更好的整体性能。例如,如果您正在编写财务系统,并且报表几乎总是基于活动的日期和时间(过去一年的所有活动等),那么该日期列上的聚簇索引可能会更好。正如HLGEM所说,排序也可能受到聚集索引选择的影响。

聚簇索引也可以比其他索引更多地影响插入。如果您有大量的插入,并且您的聚簇索引类似于IDENTITY列,则磁盘的特定部分可能存在争用问题,因为所有新行都插入到同一位置。

对于小型查找表,我总是将聚簇索引放在PK上。对于影响较大的表,尽管在选择最佳的聚簇索引之前花些时间考虑(并测试)各种可能的聚簇索引是个好主意。

答案 3 :(得分:1)

我相信SQL Server会按照您的说法对其进行排序。它假定您最了解如何访问索引。

在任何情况下,我都会说,在可能的情况下,尽可能指定您想要的内容,而不是希望数据库能够解决这个问题。

你也可以尝试两种方式,运行一堆代表性查询,然后比较生成的执行计划,以确定哪种方法最适合你。

答案 4 :(得分:1)

请记住,聚集索引是表存储在磁盘上的物理顺序。

因此,如果您的聚簇索引定义为ColA,那么当按照与聚簇索引相同的顺序进行排序时,ColB查询会更快。如果SQL必须命令B,A它将需要执行后执行排序以实现正确的顺序。

我的建议是在B,A上添加第二个非聚集索引。此外,根据您的数据列的大小INCLUDE(读取包含列),它可以防止需要键查找。当然,只要该表没有大量插入,因为您始终必须平衡查询速度与写入速度。

实际上,您的聚簇索引应该表示最有可能访问数据的顺序,以及保持插入\更新IO成本的微妙平衡。如果您的聚集索引是不断插入页面中间的,那么您可能会遇到性能损失。

像其他人所说的那样,不知道表长,列大小等没有正确的答案。大剂量测试的试错是最好的选择。

答案 5 :(得分:1)

以防这种情况不明显:索引的排序顺序对结果在查询中的排序顺序没有多少承诺

在您的查询中,您仍然必须添加

ORDER BY KeyA, KeyB

ORDER BY KeyB, KeyA

优化器可能很乐意根据需要找到已在索引中物理排序的数据并节省一些时间,但是应该以特定顺序传递数据的每个查询都必须在其末尾具有ORDER BY子句。如果没有顺序,SQL Server就不会对记录集的顺序做出任何承诺,甚至不会从查询到查询以相同的顺序返回。

答案 6 :(得分:0)

您可以做的最好的事情是尝试两种解决方案并测量执行时间。

根据我的经验,索引调整只是精确科学。

可能在索引列顺序中使用keyA之前的keyB会更好

答案 7 :(得分:0)

您可以按照通常希望它们在报表和查询中排序的顺序指定列。

我会担心创建一个多列聚簇索引。根据它的宽度,您可能会对您创建的任何其他索引的大小产生巨大影响,因为所有非聚簇索引都包含聚簇索引值。如果值经常更改,则必须重新排序行,并且我的经验是非代理键往往更频繁地更改。因此,如果您有可能更改的值,则将此作为群集的非聚簇索引创建可能会花费更多时间来处理服务器资源。我不是说你不应该这样做,因为我不知道你的列实际包含什么类型的数据(虽然我怀疑它们比A1,a2等更复杂);我说你需要考虑这样做的后果。在承诺执行此操作之前,彻底阅读有关群集的非聚簇索引的BOL可能是个好主意。

答案 8 :(得分:0)

是的,您应该建议,通常查询引擎会尝试找出最佳执行计划和要使用的索引,但有时最好强制查询引擎使用特定索引。在规划索引时以及在查询中使用索引时还有一些其他考虑因素。例如,索引中的列排序,where子句中的列排序。您可以参考以下链接了解:

http://ashishkhandelwal.arkutil.com/sql-server/quick-and-short-database-indexes/

  • 使用索引的最佳做法
  • 如何获得最佳表现形式指数
  • 聚集索引注意事项
  • 非聚集索引注意事项

我确信这会在规划索引时帮助您。