9

我有一个包含 a、b、c、d、e、f、g 列的表,其中大约有 500,000 行。

有一个查询经常运行,它会执行SELECT * FROM table WHERE a = @a AND b = @b AND c = @c.

clustered index在 a、b 和 c 上创建 a 更好,还是在 a 、 b 和 c 上创建a 更好。non-clustered indexINCLUDE (d, e, f, g)

自发出 select * 以来,不确定包含是否有助于加快查询速度。

任何帮助,将不胜感激!

4

4 回答 4

15

聚集索引将是最快SELECT,但它不一定是正确的选择。

聚集索引决定了记录的物理存储顺序(这就是每个表只能有一个的原因)。因此,虽然它对于 THAT 查询来说是最快的,但它可能会减慢其他查询的速度,并且如果其中一列发生更改,它可能会 KILL 更新和插入,这可能意味着需要物理重新定位记录。

如果更新了这些字段(包括包含的字段)中的任何一个,则 INCLUDE 将再次以额外的存储和额外的索引维护为代价来加速该查询。

我会从 a、b 和 c 上的非聚集索引开始,看看这是否能让你的表现达到合理的水平。更多的可能只是用一个领域的速度来换取另一个领域的缓慢。

于 2013-05-14T20:54:00.337 回答
2

聚集索引会更快。

使用SELECT *,您的集群和非集群(包含全部)都包含每个页面中的所有列。但是,非聚集索引也包含对聚集键的引用——如果您向表中添加更多列,这是必需的,但实际上也是因为所有索引(索引视图除外)都是指向数据页的指针。NCI 不会包含新列(固定包含列表),但数据页会。

SQL Server可能足够聪明,可以发现SELECT *可以通过 NCI(+includes)上的 INDEX SCAN 完成,而无需通过书签查找回数据页,但即便如此,该索引扫描也将比等效的群集宽一列索引扫描。

拥有 3 列聚类键通常不是一个好主意。您可以考虑使用简单的单列标识集群键的替代方法,并创建围绕 3 列集群的索引视图。

于 2013-05-14T20:53:38.267 回答
1

一般而言,您的主题行中所述问题的答案是否定的。因为您通常更希望拥有最窄的覆盖(可能是非聚集)索引。

但是在您的情况下,您选择 * 因此,如果聚集索引与您的搜索条件足够匹配,它将始终被选中,因为任何更窄的内容都需要进行书签查找。

所以这就提出了一个大问题,为什么这个查询是这样的,对于你的应用程序是否有更好的聚集索引选择(窄的、静态的、递增的、唯一的),以及你是否真的需要得到所有的列。因为你给出的两个选项都不是一个好的设计的典型。

500000 行相当小,但如果性能是一个问题,您想查看每页有多少行适合,以及您是否可以改进这一点,使其在查询中更具选择性并具有覆盖的非聚集索引。

于 2013-05-14T22:38:29.643 回答
-3

您的聚集索引是数据在表中存储的顺序,因此每个表只能有一个聚集索引。如果您创建一个新索引(默认为非聚集),请确保在索引中定义的列与它们在 WHERE 子句中使用的顺序相同,这将允许 SQL 进行直接索引扫描以查找您的记录重新寻找。

于 2013-05-14T20:46:33.423 回答