大索引INCLUDE字段将如何影响系统性能?


15

这个问题是关于SQL Server索引性能的,其中包含a varchar(2000)作为INCLUDE索引。

我试图在缓慢而不稳定的数据库应用程序中提高性能。在某些情况下,数据是通过大VARCHAR字符串来访问的,与查询包括像multple字符串操作SUBSTRING()SPACE()DATALENGTH()。这是访问的简化示例;

update fattable set col3 =  
   SUBSTRING(col3,1,10) + '*' + 
   SUBSTRING(col3,12,DATALENGTH(col3)-12)
from fattable where substring(col3,10,1) = 'A' and col2 = 2

模式如下所示:

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 [IndexCol2Col3] ON [dbo].[FatTable]  ( [col2] ASC ) 
    INCLUDE( [col3] )

据我所知,将大数据字段放入索引是很糟糕的。我已经阅读了几篇文章,包括http://msdn.microsoft.com/zh-cn/library/ms190806.aspx,其中讨论了分页和磁盘大小对索引性能的影响。话虽如此,查询计划肯定使用覆盖索引。我没有足够的信息来确定这在系统负载方面实际花了我多少钱。我确实知道,总体而言,系统运行不佳,我担心这是问题之一。问题:

  • 将此varchar(2000)列放在索引中INCLUDE曾经是个好主意吗?

  • 由于INCLUDE字段存储在叶节点中,它们对索引性能有很大影响吗?

更新:感谢您的出色答复!从某些方面来说,这是一个不公平的问题-就像你们说的那样,没有实际的统计数据和分析,就没有绝对正确的答案。像许多性能问题一样,我猜答案是“取决于”。


实际值多长时间?一个VARCHAR(2000)通常的店刚十个字符是一回事; 每个记录有2,000字节的固定空间是另外一回事。
所有行业的乔恩2015年

只是一个观察:此处的“臭味”是大列可能包含1)自由文本,在这种情况下,查询可能会受益于使用FULLTEXT索引的重写,或者2)“人类可读”编码数据(例如,广泛的智能键(例如VIN),可以受益于将其拆分为多个单独的列或使用INDEX持久存储计算所得的列。换句话说,情报和数据更改的流程设计得不好。
Graeme

1
是的#Graeme,这里有难闻的气味-我认为这叫做“旧版”。该数据库中存在许多问题。
RaoulRubin 2015年

Answers:


14

曾经是个大词,但总的来说,不,我不会将varchar(2000)字段放入INCLUDE。

是的,在页级别存储数据的方式会严重影响索引的性能,具体取决于索引的使用方式。

关键是,您可以在一个页面中填充的数据行越多,需要访问的页面越少,则系统在大多数情况下就越快。添加非常大的列意味着更少的信息存储在页面上,因此,在进行范围搜索或扫描时,必须读取更多的页面才能获取数据,从而严重降低了存储速度。

为了确定这是您的查询还是系统上的问题,您必须监视读取,尤其是查询使用的页数。


谢谢格兰特。正如我提到的另一条评论一样,缺乏良好的性能信息,因此是抽象的问题。我没有监控页面大小性能成本的经验。我的直觉是,这是一个问题,将查看我是否可以获得一些统计信息。
拉乌尔·鲁宾(RaoulRubin)2012年

1
为查询设置统计信息IO将告诉您很多信息,逻辑读取代表访问的页面数。您还可以监视秒/从perfmon计数器读取以获取常规性能信息。
Grant Fritchey 2012年

6

您是否可以查看当前的聚集索引键,或者col2改为使用聚集索引键?这样一来,您无需复制数据即可获得覆盖的“包含”行为(因为聚簇索引始终“包含”所有内容)。这当然是受到很多ifbut,然而或许是值得考虑的。当然,如果当前的聚集索引正在强制执行约束(主键,唯一键),则该约束将必须移至非聚集索引中。


您对PK的建议是一个好主意,尽管在这种情况下我将无法应用它-现有PK对于其他查询是必需的。(这是我将保留在工具箱中的一项技术!)
RaoulRubin'2

4

很难回答。这完全取决于您的读写比率。您是否在包含和不包含所包含列的情况下在测试系统上测试了工作负载或模拟了整个业务周期?没有它的查找可能会花费很多,但是如果您更新数据的频率比读取数据的频率高,那就可以了。


总体读取与更新基本平衡。组织和隐私问题使得很难获得有用的统计数据和实际测试。由于我们大部分时间都是盲目飞行,因此我们必须从抽象的角度看待事物(因此会出现此问题)。测试将意味着推动生产变更并观察结果-风险很大。
拉乌尔·鲁宾(RaoulRubin)2012年

2
并且大多数阅读实际上是在此VARCHAR(2000)列中进行的吗,还是您要对不代表大多数查询的非常特定的查询的性能进行故障排除?正如Grant所建议的,如果此列在很多查询中使用,或确实导致寻找问题,则最好在需要时为查询支付价格,而在不需要时为存储支付费用。同样,由于我们实际上没有任何细节,因此很难告诉您应该在栅栏的哪一侧(甚至更困难,因为您无法测试-您应该努力解决)。
亚伦·伯特兰

3

我知道我参加这个聚会很晚,但是我会准确地索引用于定位行的表达式,例如substring(col3,10,1)。如果使用了整个col3,我将为CHECKSUM(col3)编制索引(当然,当然可能会发生冲突)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.