维护SQL Server索引是一个不寻常的实践。如果查询不使用索引,那么往往会有一个新的非聚簇索引被创建,它只是包含一个不同的或是相同的字段组合。但现在并没有发布一个关于为什么SQL Server会忽略这些索引的详细分析。 让我们来看看是如何选择聚簇索引和非聚簇索引,以及为何查询优化器可能选择扫描一个表而不是非聚簇索引。
在本文中,我们将学习页拆分、碎裂索引、表分区和统计更新是如何影响索引使用的。最后,我们还将学习如何维护SQL Server索引以便查询优化器能使用这些索引,以及这些索引能够被快速查询。 索引选择 在索引选择中,聚簇索引是目前最容易理解的。聚簇索引基本上是唯一指向每行……
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
![TechTarget微信公众号二维码](/wp-content/uploads/res/images/spriteimg/ttweixin.jpg)
TechTarget
官方微博
![TechTarget中国官方微博二维码](/wp-content/uploads/res/images/spriteimg/ttweibo.jpg)
TechTarget中国
维护SQL Server索引是一个不寻常的实践。如果查询不使用索引,那么往往会有一个新的非聚簇索引被创建,它只是包含一个不同的或是相同的字段组合。但现在并没有发布一个关于为什么SQL Server会忽略这些索引的详细分析。
让我们来看看是如何选择聚簇索引和非聚簇索引,以及为何查询优化器可能选择扫描一个表而不是非聚簇索引。在本文中,我们将学习页拆分、碎裂索引、表分区和统计更新是如何影响索引使用的。最后,我们还将学习如何维护SQL Server索引以便查询优化器能使用这些索引,以及这些索引能够被快速查询。
索引选择
在索引选择中,聚簇索引是目前最容易理解的。聚簇索引基本上是唯一指向每行记录的键。即使定义一个聚簇索引而未声明它为唯一的,SQL Server仍然通过添加一个4字节的“唯一符”到聚簇索引来使它实际上是唯一的。附加的“唯一符”将增加聚簇索引的宽度,从而导致维护时间增加和查找速度减慢。由于聚簇索引是一个标识每个记录行的键,因此它们被应用在每个查询中。
对于非聚簇索引来说,情况会有一点复杂。由于以下原因,查询会忽略非聚簇索引:
1、高碎片率——当索引有超过40%的碎片时,优化器可能会忽略该索引,因为查找一个碎裂索引比扫描一个表的开销要高。
2、唯一性——如果优化器确定一个非聚簇索引不是唯一的,那么它会认为扫描表会比使用非聚簇索引要效率高些。比如:如果一个查询引用一个比特字段(这里的bit=1)而且字段的统计显示75%的记录行都是1,那么优化器可能认为表扫描比非聚簇索引扫描更快获得结果。
3、过时的统计——如果字段的统计过期了,那么SQL Server会对聚簇索引的好处作出错误的判断。自动更新统计不仅减缓数据修改脚本,而且随着时间的推移,它还会变得与实际的记录统计不同步。有时,最好运行一下sp_updatestats或UPDATE STATISTICS。
4、方法使用——当查询条件带有一个方法时,SQL Server就无法使用索引。如果我们引用了一个非聚簇索引字段,但又使用一个方法,如convert(varchar, Col1_Year) = 2004,那么SQL Server也无法使用Col1_Year上的索引。
5、错误字段——如果一个非聚簇索引是定义在(col1, col2, col3),而我们的查询中有一个WHERE子句,如“where col2 = 'somevalue”,那么就不会使用索引。只有当索引中的第一个字段有在WHERE子句中引用时,才会使用该索引。对于这样的WHERE子句,如“where col3 = 'someval”,将不会使用索引中,但是,如“where col1 = 'someval”或“where col1='someval and col3 = 'someval2”的WHERE子句则会使用索引。
索引不会在查询中使用col3,因为这个字段在索引定义中不并在col1之后。如果想要在类似的这种情况下使用col3来查找,那么最佳的方法就是定义两个单独的非聚簇索引,一个在col1,另一个在col3。
页拆分
为了存储数据,SQL Server使用有8kb数据块的页。而填充到页中的数据量则被称为填充因数,并且填充因数越高,8kb页面就越满。越高的填充因数就意味着需要越少的页,从而IO/CPU/RAM使用也就越少。因此,我们可能会想将索引设置为100%填充因数;然而,这里有个问题:一旦页面填满了,而又有在已填充的索引范围内的新值到达时,SQL Server将通过“页拆分”来为索引提供空间。本质上,SQL Server是将把填满的页拆分成两个页,这样就会有更多的存储空间了。我们可以通过设置填充因数为70%左右来解决这个问题。这样就总是有30%的可用空间预留给将输入的值。这个方法的问题是我们必须不断的“重建”索引,才可以维持30%的可用空间。
作者
Matt在SQL Server和Oracle这两个领域具有12年的经验。他获得微软MCITP认证、是一名数据库开发人员,他还获得了计算机科学专业硕士学位是SQL Server数据库系统高级软件工程师,范围从2 GB到3+ TB、2k和40+ktrans/sec之间。目前他任职于IGT公司,同样是一名独立的咨询师、专攻覆盖自动化、电子商务、娱乐和银行业的SQL Server、Oracle以及.NET方面。Matt擅长OLTP/OLAP数据库管理系统以及用.NET语言写可升级的处理系统。
翻译
TechTarget中国特约技术编辑,某高校计算机科学专业教师和网络实验室负责人,曾任职某网络国际厂商,关注数据中心、开发运维、数据库及软件开发技术。有多本关于思科数据中心和虚拟化技术的译著,如《思科绿色数据中心建设与管理》和《基于IP的能源管理》等。
相关推荐
-
发现那些未被使用的数据库索引
为了确保快速访问数据,和其他关系型数据库系统一样SQL Server会利用索引来快速的查找数据。然而有太多索引的缺点是不得不维护这些索引,维护也需要代价。
-
介绍SQL Server聚集索引指示
借助聚集索引来搜索行一般的情况下借助非聚集索引来搜索行快,其主要有两个原因。原因一是聚集索引只包含了一个指向页的指针而不是指向单个数据行的指针。
-
权衡SQL Server索引对性能的影响
做DBA的应该都知道,SQL Server的诸多元素当中,对于性能影响最大的就莫过于索引了,这一点几乎毫无争议。
-
SQL Server 全文索引的硬伤
全文索引是一种特殊类型的基于标记的功能性索引,由Microsoft SQL Server 全文引擎 (MSFTESQL) 服务创建和维护。