我应该使用许多单字段索引,而不是特定的多列索引吗?

这个问题是关于 SQL Server 索引技术的有效性。我认为它被称作“索引交集”。

我正在处理一个已有的 SQL Server(2008)应用程序,它存在一些性能和稳定性问题。开发人员在索引方面做了一些奇怪的事情。我无法得出这些问题的确切基准测试结果,也找不到任何真正好的文档在网络上。

表中有很多可搜索的列。开发人员在每个可搜索的列上创建了单列索引。理论上,SQL Server 将能够组合(交集)这些索引以在大多数情况下高效地访问表格。以下是一个简化的例子(实际表格具有更多字段):

CREATE TABLE [dbo].[FatTable](
    [id] [bigint] IDENTITY(1,1) NOT NULL,
    [col1] [nchar](12) NOT NULL,
    [col2] [int] NOT NULL,
    [col3] [varchar](2000) NOT NULL, ...

CREATE NONCLUSTERED INDEX [IndexCol1] ON [dbo].[FatTable]  ( [col1] ASC )
CREATE NONCLUSTERED INDEX [IndexCol2] ON [dbo].[FatTable] ( [col2] ASC )

select * from fattable where col1 = '2004IN' 
select * from fattable where col1 = '2004IN' and col2 = 4

我认为面向搜索条件的多列索引要好得多,但我可能错了。我见过显示 SQL Server 在两个索引查找上执行哈希匹配的查询计划。也许在不知道表如何被搜索时,这样做是有道理的?谢谢。


1@brentozar有一个很不错的关于索引的视频,值得一看:http://www.brentozar.com/sql-server-training-videos/index-tuning-for-sql-server/ - DForck42
1个回答

你需要的是覆盖索引,即能够单独满足查询的索引。但是“覆盖”索引有一个问题:它只能覆盖特定的查询。因此,为了制定一个良好的索引策略,你需要了解你的工作负载:哪些查询会访问数据库,哪些是关键的,哪些不是,每种类型的查询运行频率等等。然后,你需要权衡每个索引的写入和更新成本,并在此基础上制定你的索引策略。如果听起来很复杂,那是因为它确实很复杂。 然而,你可以应用一些经验法则。MSDN对基础知识有很好的介绍。

社区还贡献了大量的文章,例如网络研讨会录像-DBA达尔文奖:索引版

回答你的问题:具体来说,每个列上的单独索引是可以工作的,前提是每个列具有高选择性(许多不同的值,在数据库中每个值只出现几次)。使用两个索引范围扫描之间的哈希连接得到的访问计划通常效果很好。低选择性的列(少量不同的值,在数据库中每个值出现很多次)没有必要单独建立索引,查询优化器会简单地忽略它们。然而,低选择性的列在与高选择性列配对时,往往可以作为良好的复合键。

谢谢 Remus。我在想创建有针对性的多列索引(和包含字段)相对于使用单独的索引,是否具有相对优势。如果“效果相当不错”已经足够好,那可能可以接受。(会删除低选择性字段上的索引)。这种技术应该在我们无法访问生产数据库并且无法根据实际使用情况来定位索引时有所帮助。 - RaoulRubin