SQL Server索引进阶:第十五级,索引的最佳实践
在本文中我们将推荐14条贯穿本系列的规则,这些规则帮助你为数据库创建最好的索引结构。
格式来自于《Framework Design Guidelines》。每条推荐用四个词来总结:Do做,Consider考虑,Void避免,Do Not不要做。
- 做。总是要遵守的规则。
- 考虑。通常来说应该遵守,但是如果你完全理解了规则背后的原因,并且有你不遵守的原因。
- 避免。和考虑相反,通常建议不这么做,但是如果你完全理解了为什么不应该这么做,你有这么做的原因,你可以这么做。
- 不要做。比避免语气要强,表面有些事永远不要做。
指导原则
Do know your Application/Users
索引的主要目的是提高查询和操作数据的性能,除非你知道这些操作是什么,否则你没有希望改进他们。
最好是在应用的开始就考虑,在设计和开发中加入。如果你继承了一个已经存在的数据库和应用,从两方面理解你继承的是什么:内部和外部。
外部包括从用户角度,和他们聊天,观察他们使用应用,阅读用户文档和手册,查看当前的表格和报表。
内部包括检查应用本身,应用的定义和应用的执行。使用工具,Activity Monitor,Profiler,sys.dm_db_index usage_stats动态视图,以及sys.dm_db_missing_index_XXX系列的动态视图观察常用查询,慢查询,常用索引,未使用的索引,应该存在但却没有建立的索引。
检查常用查询和慢查询的源头,例如,报表服务的模板。TSQL作业的步骤,SSIS应用中的TSQL任务,存储过程,都应该被优化。
在了解了这些信息之后,对于那些索引是好的,那些索引是不好的,你就可以做出更好的决定。
Do Not Over Index
索引太多和太少都是不好的。对表来说没有“最佳索引个数”这种说法。每张表的情况都不同。但是如果你要在主键,候选键,合适的外键,潜在的查询列上建立索引,请在建立之前做一些分析。
Do Understand that:Same Database + Different Situation = Different Indexing
不管是白天处理,还是非高峰期处理;不管是联机处理,还是对数据库拷贝的报表处理;不同的情况,建立的索引是不同的。
Do Have a Primary Key on Every Table
尽管主键不是SQL Server必须的,但是没有主键的表在事务的时候是非常危险的,因为不能保证行是唯一的。如果允许重复行,就会发生,你不知道是同一个实体重复插入了两次,还是没有足够的信息来区分这两个实体。
尽管SQL Server没有要求,主键是关系理论的基础,所有关系系统的基本构成。没有主键的约束,或者是唯一索引,可能会导致意外的结果,或者不好的性能。
另外,很多客户端开发工具和组件都需要你的表有主键。主键约束的名称就是索引的名称。
Consider Having a Clustered Index on Every Table
在第三级,聚集索引介绍了聚集索引的好处。让表成为聚集索引表而不是堆表。主要的好处是一个简单的事实,用户在查看表数据的时候肯定会以一个默认的顺序,所以就以哪个顺序来维护表。
如果你按照本文的规则,每张表都有主键,每张表至少有一个索引,甚至更多。因此,一个聚集索引不会增加索引的数量,但是相比堆表,会给你的表带来一个很好的结构。
在决定聚集索引列的时候,要记住第六级,标签中的指导原则:一个聚集索引应该唯一,短小,不变的。
Consider Using a Foreign Key in the Search Key of the Clustered Index
考虑将外键作为聚集索引键中最左面的列,这样可以将子item的信息聚集在父的周围,这是一个典型的需求。你的信用卡的消费信息和信用卡关联,我的消费信息和我的卡关联。这个关系要比消费记录和商家,或者消费记录和处理消费记录的金融机构,要比这些关系强。卡号是包含在消费表的聚集索引键中的外键,而不是商家编号和银行编号。将卡号放在聚集索引的最左边,同一个持卡人的消费记录就会聚集在相同的页中。
Consider Having Included Columns in your Indexes
考虑在你的非聚集索引中添加包含列。
因为一般的非聚集索引都是从某种角度查看表,或者是建立的外键的基础上,但是除了非聚集索引的键列,还会需要一些其他列,但是这些列不作为查询条件,只是需要显示或者统计它们,这时候,这些列就可以添加为包含列,就不用再去访问数据行了,直接在非聚集索引中就可以完成请求。
Avoid Nonclustered, Unfilterd Indexes on Columns that have few Distinct Values
有句老话:“不要在性别列上建立索引”。表中的一页将会有一半的值为男,一半的值为女,不管是请求男还是女,扫描表都是最好的决定。因此,这样的一个索引永远不会被查询优化器使用。
Consider Create a Filtered Index for Columns that Have a Dominate Value
如果表中有一列,大部分行的值都相同,或者都是NULL,那么就在这列上创建一个过滤索引。那些查询小部分值的时候,就会使用索引;查询大部分值的时候就扫描表。
Consider Specifying Fill Factor Values that Anticipate Future Size Requirements
Consider Specifying Fill Factor Values that Reflect the Table's Steady-state Page Fragmentation Value
Do Create a Table's Clustered Index Before Creating its Nonclustered Indexes
这条规则的一个推论就是:删除聚集索引之前,先删除非聚集索引。否则会导致非聚集索引出现不必要的重建。表从堆表,转变成聚集索引表,总是会导致非聚集索引的重建,因为非聚集索引的书签的内容会从行号变成聚集索引的键。
Do Plan Your Index Defragmenting and Rebuilding Based Upon Usage
如果一个索引经常被扫描,索引的外部碎片是很重要的,对于全扫描或者扫描部分叶子层会产生重要的影响。如果是这种情况,在外部碎片达到10%的时候,考虑重新组织索引,当达到30%的时候,考虑重建索引。
但是,如果,索引只是通过一个键来查询,外部碎片对性能的影响很小,甚至没有影响。从根页到叶子层的一页所需要的IO,将会忽略外部碎片,将会是相同的。这时候,重新组织和重建索引对于性能没有提升。
Do Update Index Statistics On a Regular Basis
关键字是“规律的”,因为只有知道你的应用在做什么,你才能决定什么时候统计信息需要更新。在第十四级中有这部分的介绍。
结论
这些指导原则来自于很多在SQL Server上工作过多年的开发人员,根据这些指导原则,你可以在你的数据库上创建最好的索引。
SQL Server索引进阶:第十五级,索引的最佳实践的更多相关文章
- 为运行SQL Server的虚拟机切换装有DB Logs的最佳实践
上一篇说到虚拟机启动不了, 原因是有一块VHDX的文件找不到了. 解决了这个问题之后, 又遇到了另一个问题, 那就是我的这台SQL Server的虚机启动之后, 我的几个重要database变成了su ...
- SQL Server 2005 中的分区表和索引
SQL Server 2005 中的分区表和索引 SQL Server 2005 69(共 83)对本文的评价是有帮助 - 评价此主题 发布日期 : 3/24/2005 | 更新 ...
- SQL Server 2016:内存列存储索引
作者 Jonathan Allen,译者 谢丽 SQL Server 2016的一项新特性是可以在“内存优化表(Memory Optimized Table)”上添加“列存储索引(Columnstor ...
- SQL Server ->> ColumnStore Index(列存储索引)
Columnstored index是SQL Server 2012后加入的重大特性,数据不再以heap或者B Tree的形式存储(row level)存储在每一个数据库文件的页里面,而是以列为单位存 ...
- SQL Server 性能调优2 之索引(Index)的建立
前言 索引是关系数据库中最重要的对象之中的一个,他能显著降低磁盘I/O及逻辑读取的消耗,并以此来提升 SELECT 语句的查找性能.但它是一把双刃剑.使用不当反而会影响性能:他须要额外的空间来存放这些 ...
- SQL Server的唯一键和唯一索引会将空值(NULL)也算作重复值
我们先在SQL Server数据库中,建立一张Students表: CREATE TABLE [dbo].[Students]( ,) NOT NULL, ) NULL, ) NULL, [Age] ...
- SQL Server索引进阶:第五级,包含列
原文地址: Stairway to SQL Server Indexes: Level 5, Included Columns 本文是SQL Server索引进阶系列(Stairway to SQL ...
- 【译】索引进阶(十二):SQL SERVER中的索引碎片【中篇】
原文链接:传送门. 为了讨论碎片产生的原因,以及避免和移除索引碎片的技术,我们必须从本进阶系列后续将介绍的两个章节借用一些知识点:创建/更新索引的知识,以及向一个索引表插入数据行的相关知识. 当我们讲 ...
- 解读SQL Server 2014可更新列存储索引——存储机制
概述 SQL Server 2014被号称是微软数据库的一个革命性版本,其性能的提升的幅度是有史以来之最. 可更新的列存储索引作为SQL Server 2014的一个关键功能之一,在提升数据库的查询性 ...
- SQL SERVER中关于OR会导致索引扫描或全表扫描的浅析
在SQL SERVER的查询语句中使用OR是否会导致不走索引查找(Index Seek)或索引失效(堆表走全表扫描 (Table Scan).聚集索引表走聚集索引扫描(Clustered Index ...
随机推荐
- C语言入门(18)——数组与字符串
用来存放字符量的数组称为字符数组.字符串可以看作一个数组,它的元素是字符型的. 字符数组的定义 形式与前面介绍的数值数组相同.例如: char c[10]; 由于字符型和整型通用,也可以定义为int ...
- SWOT自我分析
个人信息: 大三学生 二本大学 软件工程专业 一:SWOT自我分析 Strenghs(优势): 1.有着良好的作息习惯,坚持锻炼 2.专注力强,能沉下心来学习 3.有着强烈的危机意思,明白不仅则退的道 ...
- Redis事务和分布式锁
Redis事务 Redis中的事务(transaction)是一组命令的集合.事务同命令一样都是Redis最小的执行单位,一个事务中的命令要么都执行,要么都不执行.Redis事务的实现需要用到 MUL ...
- Gunner II(二分,map,数字转化)
Gunner II Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total ...
- php这样实现伪静态
mod_rewrite是Apache的一个非常强大的功能,它可以实现伪静态页面.下面我详细说说它的使用方法 1.检测Apache是否支持mod_rewrite 通过php提供的phpinfo()函数查 ...
- Android dump .so 文件crash log
众所周知,在android系统上,有时候我们遇到so文件的crash仅仅能打log,可是非常多时候并不知道crash在什么地方,幸运的是crash后,一般能够产生一个.dmp文件. 我们能够依据这个文 ...
- 在spring中进行基于Executor的任务调度
Executor java.util.concurrent.Executor接口的主要目的是要将“任务提交”和“任务执行”两者分离解耦.该接口定义了任务提交的方法,实现者可以提供不同的任务运行机制,解 ...
- Javaweb整合mongo和kettle6.0的环境配置
为了编译能通过,maven需要加入仓库地址以及一些必须要的包的依赖情况: pentaho中央仓库: 在properties里面配置版本号: <kettle.version>6.0.0.0- ...
- tomcat异常
java.lang.UnsupportedClassVersionError: org/apache/lucene/store/Directory : Unsupported major.minor ...
- mysql函数操作(4)
<?php ... $query = "INSERT INTO contactInfo (name, address, phone) VALUES (?, ?, ?)"; $ ...