我的基本理解是,一般来说,只包含您在任何给定时间可能查询/排序的所有字段的单个索引不太可能有用,但我已经看到了这种类型的东西.有人认为,“好吧,如果我们把所有这些东西放在一个索引中,数据库可以用它来找到它需要的东西”,而没有看到一些实际查询的运行执行计划.
想象一下这样的表:
id int pk/uid name varchar(50) customerId int (foreign key) dateCreated datetime
我可能会看到一个索引,包括name,customerId和dateCreated字段.
但我的理解是这样的索引不会在查询中使用,例如:
SELECT [id],[name],[customerId],[dateCreated] FROM Representatives WHERE customerId=1 ORDER BY dateCreated
对于这样的查询,在我看来,更好的想法是包括customerId和dateCreated字段的索引,其中customerId字段是’first’.这将创建一个索引,使得数据的组织方式使得此查询可以按需要的顺序快速找到所需内容.
我看到的另一件事,也许和第一件事一样频繁,就是每个领域的个别索引;所以,名称,customerId和dateCreated字段各占一个.
与第一个例子不同,这种类型的安排在我看来有时至少是部分有用的;查询的执行计划可能会显示至少它正在使用customerId上的索引来选择记录,但它没有使用带有dateCreated字段的索引来对它们进行排序.
我知道这是一个广泛的问题,因为对任何特定表集合的任何特定查询的具体答案通常是查看执行计划所说的内容,并以其他方式将表格和查询的具体内容放入帐户.另外,我知道这取决于运行查询的频率,而不是维护特定索引的开销.
但我想我所要求的是作为索引的一般“起点”,是否有针对特定的,频繁拉取的查询以及WHERE或ORDER BY子句中的字段的特定索引的想法是否有意义?
解决方法
在以下情况下,查询计划程序将考虑使用索引:
>查询中引用了包含在其中的所有字段
>引用从头开始的一些字段
它将无法使用以查询未使用的字段开头的索引.
所以对你的例子:
SELECT [id],[dateCreated] FROM Representatives WHERE customerId=1 ORDER BY dateCreated
它会考虑如下索引:
[customerId] [customerId],[dateCreated] [customerId],[dateCreated],[name]
但不是:
[name],[dateCreated]
如果它同时找到[customerId]和[customerId],那么它更喜欢一个而不是另一个的决定取决于索引统计数据,这取决于字段中数据平衡的估计.如果[customerId],[dateCreated]被定义,它应该优先于其他两个,除非你给出相反的特定索引提示.
在我的经验中看到为每个字段定义一个索引的情况并不少见,尽管这很少是最佳的,因为在插入/更新时更新索引所需的额外管理以及存储它们所需的额外空间是浪费的一半它们可能永远不会被使用 – 但除非您的数据库看到写入量很大的负载,否则即使使用多余的索引,性能也不会严重恶化.
频繁查询的特定索引通常会因表或索引扫描而变慢,但通常不会过度,因为您可能会将一个性能问题替换为另一个性能问题.例如,如果您将[customerId],[dateCreated]定义为索引,请记住查询计划程序将能够将其用于仅在[customerId]上使用索引的查询(如果存在).虽然仅使用[customerId]会比使用复合索引稍微更高效,但可以通过最终让两个索引在RAM中竞争空间而不是一个来缓解(尽管如果你的整个正常工作集很容易适应RAM这个额外的内存竞争可能不是问题).