8

我有一张这样的桌子:

keyA keyB data

keyA 和 keyB 一起是唯一的,是我的表的主键并组成了一个聚集索引。

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

例如,根据首先排序哪个键列,可以对以下数据进行 2 种排序:

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

我是否需要告诉聚集索引哪些键列的可能值较少,以允许它首先按该值对数据进行排序?还是就性能而言,先订购哪个无关紧要?

4

9 回答 9

13

您应该首先使用最具选择性的列来订购复合聚集索引。这意味着与总行数相比,具有最不同值的列。

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

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

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

ligget78 关于确保提及复合索引中的第一列的评论很重要,请务必记住。

于 2008-12-05T16:01:03.387 回答
7

如果您使用 (keyA, keyB) 创建索引(无论是否聚集),那么这就是值的排序方式,例如第一个 keyA,然后是 keyB(这是您问题中的第二种情况)。如果你想反过来,你需要指定(keyB,keyA)。

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

于 2008-12-05T15:09:18.483 回答
2

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

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

与其他索引相比,聚集索引对插入的影响也更大。如果您有大量插入并且您的聚集索引位于类似 IDENTITY 列的位置,那么磁盘的特定部分可能会出现争用问题,因为所有新行都被插入到同一个位置。

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

于 2008-12-05T15:38:48.593 回答
1

我相信 SQL Server 完全按照您告诉它的方式对其进行排序。它假定您最了解如何访问您的索引。

无论如何,我会说最好在可能的情况下准确地指定您想要的东西,而不是希望数据库能弄清楚。

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

于 2008-12-05T15:07:24.507 回答
1

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

因此,如果您的聚集索引被定义为 ColA,ColB 查询在与聚集索引相同的顺序时会更快。如果 SQL 必须对 B、A 进行排序,则需要执行后排序才能获得正确的顺序。

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

实际上,您的聚集索引应该代表最有可能访问数据的顺序,并保持插入\更新 IO 成本的微妙平衡。如果您的聚集索引经常插入到页面的中间,您可能会在那里遭受性能损失。

就像其他人所说,不知道表格长度、列大小等,就没有正确答案。进行大量测试的反复试验是您最好的选择。

于 2008-12-05T15:46:59.857 回答
1

以防万一这不明显:索引的排序顺序并不能保证查询中结果的排序顺序。

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

ORDER BY KeyA, KeyB

或者

ORDER BY KeyB, KeyA

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

于 2008-12-05T16:28:35.607 回答
0

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

根据我的经验,索引调优几乎是一门精确的科学。

也许在索引列顺序中在 keyA 之前有 keyB 会更好

于 2008-12-05T15:07:01.670 回答
0

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

不过,我会警惕创建多列聚集索引。根据它的宽度,您可能会对您创建的任何其他索引的大小产生巨大影响,因为所有非聚集索引都包含其中的聚集索引值。此外,如果值经常更改,则必须重新排序行,根据我的经验,非代理键往往会更频繁地更改。因此,如果您的值可能会更改,那么将其创建为聚集副非聚集索引可能会耗费更多的服务器资源时间。我并不是说您不应该这样做,因为我不知道您的列实际包含什么类型的数据(尽管我怀疑它们比 A1、a2 等更复杂);我是说你需要考虑这样做的后果。

于 2008-12-05T15:19:00.460 回答
0

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

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

  • 使用索引的最佳实践
  • 如何获得最佳性能表单索引
  • 聚集索引注意事项
  • 非聚集索引注意事项

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

于 2012-06-26T06:27:17.433 回答