4

让我们假设这样的表

[KEY] [int] NOT NULL,
[INT1] [int] NULL,
[INT2] [int] NULL,
[INT3] [int] NULL,
[STR1] [varchar](20) NULL,
[STR2] [varchar](20) NULL,
[STR3] [varchar](20) NULL,

查询非常灵活,但总是喜欢这种格式: SELECT KEY FROM [TABLE] WHERE...

搜索条件很少在单列上,大部分时间在几列上,对于[int]类型,查询为BETWEENor >=<=对于varchar,总是查询为=or IN []。所有条件都与AND

由于查询并不总是固定在同一列上,所以我想知道,如果我INDEX在每一列上创建,它会提高性能,还是完全浪费。

4

3 回答 3

5

不要只在每一列上创建索引——这完全是浪费时间和资源!

基本上,我的方法总是:

  1. 在任何“普通”表上定义一个好的主键和集群键(例如临时表等除外)——这已经是一大步了

  2. 将非聚集索引放在任何外键列上——这些确实有很大帮助,尤其是 JOIN 的

就是这样!

然后:

  • 观察你的系统 - 看看事情何时变慢
  • 测量系统性能
  • 捕获服务器端跟踪以获取有代表性的工作负载
  • 分析该工作量,并查看哪些附加索引可能会有所帮助
  • 做调整 - 一次一个
  • 一次又一次地测量,看看您是否提高了系统性能(或没有)

您需要一个完整的、有代表性的工作负载来查看哪些查询是真正常见的并且被大量使用 - 并查看哪些索引可能对那些频繁的查询有益。否则,您可能会为所有错误的查询提供索引帮助,并且实际上可能会减慢速度……

您会惊讶于非聚集索引真正有帮助的少之又少!

不要过度索引- 这和根本没有索引一样糟糕 - 如果不是更糟的话!可能会更糟,因为您拥有的每个索引也需要在其生命周期内进行维护......而且没有免费的午餐 - 即使在这里......

请参阅 Kimberly Tripp 的优秀博客文章索引:仅仅因为你可以并不意味着你应该!关于这个话题 - 非常有帮助,有很多见解。或者基本上,只需阅读 Kim 在索引上发表的所有博客- 她是索引女王,她在博客上发布的任何内容通常都非常有帮助和有益!

此外,根据 SQL Server 的查询优化器的意见,SQL Server 2005 和更新版本提供 DMV(动态管理视图),允许您找出哪些索引没有被使用(可以删除)或丢失哪些索引。有关详细信息,请参阅SQL Server - 查找丢失和未使用的索引。但请注意:这些是动态视图——它们在每次系统启动时都会重置,可能并不完全准确——不要只做他们告诉你的所有事情——对所有事情都持保留态度,仔细考虑你所做的事情——记录下来,以便您可以撤消它,如果事情变得更糟而不是更好!

于 2012-05-05T21:25:31.570 回答
2

如通用索引设计指南中所述,在每一列上创建索引可能会影响性能:

表上的大量索引会影响 INSERT、UPDATE、DELETE 和 MERGE 语句的性能,因为所有索引都必须随着表中数据的变化而适当调整。

此外,如果您希望始终KEY在查询中检索该列,请考虑将其添加为索引中的包含列,以便仅访问索引即可检索它,避免访问表。但请记住,创建包含列的索引自 SQL Server 2005 及更高版本以来可用。

您可以检查最常见的过滤器组合,并且只添加一些列索引,请记住:

如果索引将包含多个列,请考虑列的顺序。应将在等于 (=)、大于 (>)、小于 (<) 或 BETWEEN 搜索条件中的 WHERE 子句中使用的列或参与连接的列放在首位。附加列应根据其独特性级别进行排序,即从最独特到最不独特。

于 2012-05-05T21:28:17.760 回答
1

如果直接导致正确的结果,放入索引将部分帮助查询,但如果它提高引用的局部性并减少读取的内存量,也会带来很大的好处。

对于所提出的问题,答案是“视情况而定”。这取决于您的查询。如果查询了一个主要列,它总是出现在搜索中,例如INT1,在以下位置创建索引:

 unique (INT1, INT2, INT3, REF)

然后任何引用 INT1 的查询和其他字段的任何组合都会很快。

此外,任何引用 INT2 但不是 INt1 的查询也将受益,因为不需要读取整个表 - 只需读取索引。即使 INT2 不在索引的头部,查询仍然有好处:DB 将跳过 INT1 并只查看 INT2,但它可以获得表 INT2 值的视图,而无需读取整个表。

所以你真的需要更好地理解将要完成的查询。如果总是出现一列,请将其放在索引的开头。如果出现另一列 OFTEN,那应该是第 2 列。

如果有两列都经常出现,你可以这样做:

unique (INT1, INT2, INT3, REF),
unique (INT2, INT1, INT3, REF)

那么我们希望如果没有指定 INT1,但指定了 INT2,则使用第二个索引。

但是不要使用太多索引,它们会占用大量磁盘空间。

底线:测试有和没有索引的查询。您需要至少收集 10-20 个样本查询,并测试它们的 IO 和时钟时间。只有这样才能得到真正的答案。

于 2012-05-05T21:25:05.250 回答