【译注:此文为翻译,由于本人水平所限,疏漏在所难免,欢迎探讨指正】

原文链接:传送门

在本章我们给出一些建议:贯穿本系列我们提取出了十四条基本指南,这些基本的指南将会帮助你为你的数据库创建最佳的索引架构。

这些指南的格式借鉴了 “框架设计指导”,Krzysztof Cwalina 和Brad Abramszai为.NET 程序开发的标准化方面做了优秀的工作,且他们的文章已由Addison Wesley.出版发行。每一条建议都由如下词语定义:“DO”, 'CONSIDER', "AVOID", "DO NOT", 它们表示了如下的意义:

  • DO: 这条建议应该总是被遵守。
  • CONSIDER: 一般说来这条建议需要被遵守,但是如果你完全理解了指南背后的原因,并深入了解你不遵守这条指南的理由,那么便可以适时的从这条指南上转移你的注意力。
  • AVOID: 与 CONSIDER相对的,一般来说这条指南建议了一些不应该被做的事情,但是,如果你完全理解了为什么它不应该被做,并且你也理解无论如何也要做它的原因, 那么, 就做它。
  • DO NOT 是 AVOID 的强化版本,它预示着绝对不要做的一些事。DO NOT 指南也应该总是被遵守。

 指南

   了解你的程序/用户

一个索引最主要目的便是提高你的应用程序的数据收集和收据管理操作的性能,除非你知道这些操作是什么,否则你不可能会改进它们。

在一开始就介入程序,参与到程序的设计和开发是很理想的。但是真实的情况并不总是那样。如果你正在继承一个已经实现了的数据库和应用程序,那么采取两个措施来保证你理解了你继承的东西,外部措施和内部措施。

外部措施包括从你的用你那边学习,与他们交谈,观察你的用户使用应用程序,阅读任何面向用户的文档和指导,以及查阅现有的表格和报告。

内部措施涉及了检查应用程序本身,既包含了程序的定义也包含了程序的执行。诸如此类的工具: Activity Monitor, Profiler, sys.dm_db_index usage_stats, sys.dm_db_missing_index_XXX 系列DMV均 提供了关于最常用的查询,运行时间长的查询,最常用的索引,无用的索引,本应存在但却不存在的索引信息。

检查最常用的以及性能低下的查询的最初的位置,例如,报告服务模板,T-SQL工作步骤,SSIS中的T-SQL任务,以及存储过程,这样以便获取到为什么这些语句对于应用程序来说如此重要的原因。因而便可以被更好的优化。

拥有了这些信息,你便能更好的做出决策,哪些索引是有益的,哪些却并无益处。

  不要过度索引

太多的索引和太少的索引一样是个问题。对于一个表来说, 不存在神奇的“最佳索引数”,每张表都是不同的,然而,一旦你对主键进行了索引,任何候选键,可能的外键,以及任何潜在的索引在你添加到数据库之前都需要认真的分析。

 理解: 一样的数据库+不同的情形 = 不同的索引

不管是否是一个日常处理还是一个临时处理,不管是运行在OLTP数据库上的事务性处理,还是运行在同一 数据库的拷贝上的报告性处理,不同的情况需要不同的索引。

一个每晚接受大量新数据注入的数据库在数据注入时应该比正常时间具有更少的索引数。一个具有有限查询需求的易变数据库比一个每晚更新一次的报告数据库需要更少的索引数,后者会处理复杂的报告生成逻辑。

 每张表都应该有一个主键

虽然主键不是SQL SERVER所必须的,没有主键的表在事务性以及报表数据库中水一件危险的事情,因为它的数据行不能保证是唯一的。如果允许有重复数据,那么它便会发生。并且你不会知道一个对象的相同实例被插入了两次,也不会知道是否具有不同的多个实例他们具有足够的信息来彼此区分。

虽然SQL SERVER没有强制要求主键,但它却是关系理论的基石,是所有关系型系统的基础建筑块,如果没有主键约束,以及其相关的唯一性索引,关系型操作会导致不可预期的结果以及较低的性能。

除此之外,许多客户端的开发工具和组件需要你的表具有主键,举例来说, ADO.Net SqlCommandBuilder 组件和Visual Studio’s Entity Data Modeler都依赖于目标数据库表具有主键约束,请记住,主键约束的名称会成为自动创建的用来实现这个约束的索引的名称。

考虑在每张表都有一个聚集索引

第三章节,聚集索引涵盖了在一个表上具有聚集索引的益处,那就是,使得一张表成为一个聚集索引而不是一个堆,主要的益处是这样的一个简单事实:用户社区作为一个整体趋势以一个默认的序列去查看表的数据,增强了以那种顺序来维护数据的优势。

如果你遵循这一章节列出的建议,每一张表便会有一个主键,因此,每张表都会包含至少一个索引,很有可能会是多个。因此, 使其中的一个变为聚集索引并不会增加索引的数目,但却会给你的表一个比堆更好的表结构。

当决策于聚集索引键时,记住在第六章节-书签-给出的指南:聚集索引键应该是唯一的,短的,并且是不易变的。

 考虑在聚集索引的查询键中使用外键

使用外键作为聚集索引键的最左列,会将相同父节点的子信息聚集起来,这是一个典型的逻辑处理需求。你的信用卡交易信息关联到你的信用卡,我的信用卡交易信息关联到我的卡信息,这种关系比起把一笔交易与出售商品的商家关联起来,或者把这笔交易与处理它的金融机构关联起来更强壮,信用卡号码属于信用卡表聚集索引键,不是商家编号或者银行编号。通过使信用卡号成为聚集索引键的最左列,一个信用卡持有者的所有交易便会聚集到一起,存储在相同的一个或多个数据页中。

给聚集索引键增加一个额外的不易变的列,以确保聚集索引键的唯一性。

考虑在索引中有一个包含列

  无

避免在只有几个不同值的列上具有非聚集,非过滤索引

一个老的法则是:不要在性别列上进行索引,一个典型的页会包含一半的男性数据行和一半的女性数据行,并且不管是请求男性或者女性其丢会被访问,对于任何 WHERE GENDER = XXX查询来说,表扫描总是一个最佳的决策,因而这样的一个索引对于查询优化器来说没有任何益处。

 考虑为具有支配值的列创建过滤索引

对于一个特定的列来说,如果大量的行都具有相同的值,或者都为null,那么就在这个列上创建一个过滤索引,那些查询稀有值的查询便会使用这个小的,高效的索引,查询通用值的数据行的查询将会进行表扫描。 并且SQL SERVER很容易觉得哪个用哪个。

 考虑指定填充因子值以预料未来的数据大小需求

如果一个相关的新的聚集索引表包含一个月的数据行并且被允许增长至包含一年的数据行,那么用一个填充因子值7~8%来重建这个索引,这会导致这个表现在消耗了与一年后相比相同的页数,对于空间需求和处理性能的潜在问题将在不久之后很快便体现出来--比如一个表扫描所需要的IO数。

考虑指定反映了表稳定状态碎片大小的填充因子值

如果一个表已经达到了计划的最大大小,那么上一个指南不会被应用。在这种情况下,产生于表正常活动的填充因子应该在开始时候被指定,如同在第十一章-索引碎片中提到的那样,对于一个典型的事务性表来说,其具有持续性的插入但只有阶段性的删除,这个值是75,对于一个具有相同数量的插入和删除活动的表来说,90~95是一个不错的选择。

在创建表的非聚集索引前创建聚集索引

与这条指南相对的是,在删除它的聚集索引之前删除它的非聚集索引,反之的话会导非聚集索引不必要的重建,把一个表在堆和聚集索引之间来回转换总是导致一个表的非聚集索引进行重建,因为书签的内容必须从行标志更改为聚集索引键。

基于使用场景对你的索引进行碎片整理和重建

如果你的索引经常被扫描, 那么如第十一章-索引碎片-提到的那样,索引的外部碎片便很重要,因为它决定着用来扫描整个或者部分叶子节点所需要的工作量,如果是处于这种情况,当外部碎片达到10%时候考虑重新整理他,当外部碎片达到30%时候考虑重建它。

For most transactional environments, the values mentioned above represent the point at which the benefit of performing the reorganization or rebuild of the index outweighs the cost of doing it.【这句话不理解】

然而,当一个索引被用来查找指定的键值,那么外部碎片对于性能来说几乎微乎其微,遍历从根节点到叶子节点的各个层级的页其所需要的IO数目是相同的,而不管其是否有外部碎片,在这种情况下,重新组织或者重建索引对性能几乎无影响。

有规律的更新索引统计信息

这儿的关键字是“规律性”,因为只有通过知道了你的应用程序正在做什么你才能决定什么时候统计信息需要被更新,第十四章-索引统计-展示了为什么一些过时的统计信息会变得比其他的更快。

结论

这些指南从众多工作于SQL SERVER的开发者的经验中逐步提取出来,并在许多环境中服务了多年。遵守它们可以帮助你为数据库创建最好的索引架构。

       【完结】

【译】索引进阶(十七): SQL SERVER索引最佳实践的更多相关文章

  1. SQL Server集成服务最佳实践:语句优化

        SQL Server集成服务(SQL Server Integration Services,SSIS)在其前辈DTS(Data Transformation Services,数据转换服务) ...

  2. SQL Server SA 最佳实践(也许不仅仅是翻译)

    老实说,本文主要部分是翻译的,并且由于英语水平的问题,我没有完全翻译,有些我觉得不重要的就跳过了,目前看来应该八九不离十,或者说不会影响最终效果,对于英语水平好的读者,可以自行查看原文.但这一年里面我 ...

  3. SQL Server CDC最佳实践

    企业核心业务系统oltp的数据需要通过ETL同步到数据仓库,原始的ETL流程通过定制化从SQL Server中进行数据抽取,经过生产环境的监控,发现ETL过程的query会对生产系统造成额外负载.于是 ...

  4. 清除系统日志及数据库(sql server)日志最佳实践

    在一个项目中遇到的问题:系统日志过大,后来用delete语句删除了(相当的慢),结果数据库日志又变成很大了(差不多10G),所以又得把数据库日志删除. 方法: --备份系统中的部份日志--SELECT ...

  5. c#Winform程序调用app.config文件配置数据库连接字符串 SQL Server文章目录 浅谈SQL Server中统计对于查询的影响 有关索引的DMV SQL Server中的执行引擎入门 【译】表变量和临时表的比较 对于表列数据类型选择的一点思考 SQL Server复制入门(一)----复制简介 操作系统中的进程与线程

    c#Winform程序调用app.config文件配置数据库连接字符串 你新建winform项目的时候,会有一个app.config的配置文件,写在里面的<connectionStrings n ...

  6. SQL Server索引总结二

    从CREATE开始 通过显式的CREATE INDEX命令 在创建约束时作为隐含的对象 随约束创建的隐含索引 当向表中添加如下两种约束之一时,就会创建隐含索引. 主键约束(聚集索引) 唯一约束(唯一索 ...

  7. SQL Server索引碎片整理实际操作记录

    SQL Server 版本是 2008 R2. 查询数据库索引碎片情况的 SQL 语句(来源): SELECT OBJECT_NAME(ind.OBJECT_ID) AS TableName, ind ...

  8. 【译】SQL Server索引进阶第八篇:唯一索引

    原文:[译]SQL Server索引进阶第八篇:唯一索引     索引设计是数据库设计中比较重要的一个环节,对数据库的性能其中至关重要的作用,但是索引的设计却又不是那么容易的事情,性能也不是那么轻易就 ...

  9. 【译】索引进阶(一):SQL SERVER索引介绍

      [译注:此文为翻译,由于本人水平所限,疏漏在所难免,欢迎探讨指正]  原文链接:http://www.sqlservercentral.com/articles/Stairway+Series/7 ...

  10. SQL Server索引进阶:第一级,索引简介

    这个并不是我翻译的,全文共有15篇,但我发现好多网站已经不全,所以自己整理. 原文地址: Stairway to SQL Server Indexes: Level 1, Introduction t ...

随机推荐

  1. 【做题笔记】洛谷P1955[NOI2015]程序自动分析

    第一道蓝题祭- 注意到本题中判断的是下标,即,并不是真的判断 \(i\) 是否等于 \(j\) 显然考虑并查集,把所有标记为"相等"的数放在一个集合里,然后最后扫一遍每个数,如果有 ...

  2. C#堆和栈的入门理解

    声明:以下内容从网络整理,非原创,适当待入个人理解. 解释1.栈是编译期间就分配好的内存空间,因此你的代码中必须就栈的大小有明确的定义:堆是程序运行期间动态分配的内存空间,你可以根据程序的运行情况确定 ...

  3. 前端——语言——Core JS——《The good part》读书笔记——第六章节(Arrays)

    本章介绍数组的内容,Java中的数组在创建时,会分配同等大小的内存空间,一旦创建数组的大小无法改变,如果数据超过数组大小,会进行扩容操作.并且数组的元素类型在创建时必须是已知的,而且只能存放相同数据类 ...

  4. linux shell date的用法

    该随笔引用自https://www.cnblogs.com/alsodzy/p/8403870.html 在 linux shell 里面date命令的参数 %% 一个文字的 % %a 当前local ...

  5. iptables详解(2):四表五链

    关于iptables中“四表五链”,我们今天来好好唠唠: 1.表的概念: 我们把具有相同功能的规则的集合叫做"表",所以说,不同功能的规则,我们可以放置在不同的表中进行管理,而ip ...

  6. 传奇脚本中 SendMsg 编号说明

    0 1 2 3 4 5 60对全服人说1.发送普通红色广播信息. 2.发送普通红色广播信息,并显示NPC名称. 3.发送普通红色广播信息,并人物NPC名称. 4.在NPC头顶,显示普通说话信息. 5. ...

  7. report_delay_calculation/check_timing/report_annotated_parasitics/report_analysis_coverge

    如何debug 一颗cell 或一段net 的delay,  常用的办法是用report_delay_calculation 报这颗cell 或这段net, 会得到形式如下的report, 从该rep ...

  8. windows10重置后,鼠标键盘失灵

    用大白菜u盘选择工具修复一下驱动

  9. mybatis - 执行 getById

    1. getById 的执行 前面一篇 提到过, Mapper.java 创建的时候, 会通过 jdk 代理的方式来创建, 且代理处理类为: MapperProxy . 所以当执行 UserMappe ...

  10. Jmeter BeanShell笔记

    前言:beanshell是支持java语法的,因此当一些复杂的数据结构jmeter处理不了的时候,我们可以借助于java来实现 1,使用beanshell处理JDBC请求返回的值 数据库结构 当JDB ...