【译】SQL Server索引进阶第十五篇:索引的最佳实践

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介:
  索引设计是数据库设计中比较重要的一个环节,对数据库的性能其中至关重要的作用,但是索引的设计却又不是那么容易的事情,性能也不是那么轻易就获取到的,很多的技术人员因为不恰当的创建索引,最后使得其效果适得其反,可以说“成也索引,败也索引”

    本系列文章来自Stairway to SQL Server Indexes,翻译和整理发布在agilesharp和博客园,希望对广大的技术朋友在如何使用索引上有所帮助。

 

    在本篇文章中,我们在学习了之前的知识之后,推荐14条指导方针。这14条指导方针可以帮助你更好的为数据库构建索引。

    本篇文章的格式使用了由Addison Wesley出版社出版的<Framework Design Guidelines>中使用的格式。每一个最佳实践之前都使用了如下4个动词:要,考虑,避免、不要,分别代表如下意思:

    要(Do):这个原则要坚决遵守

    考虑(Consider):通常情况下都要遵循这个原则,但如果你对原则背后的原理有了深入了理解,可以根据实际情况不采用这个原则

    避免(Avoid):考虑的反义词,意味着避免做某这类事,但同样,如果你了解了背后的原理,则可以根据实际情况做这类事。

    不要(Do Not):避免的增强版,意思是无论什么时候都不要做这类事。

 

指导方针

   

要了解跑在数据库上的应用程序/用户

    使用索引的主要目的是为了提高跑在数据库上应用程序读取和操作数据的速度,如果你不知道程序主要对数据库进行什么操作,索引优化就无从谈起。

    当然,如果你全程参与了程序的设计和开发,那再好不过。但这种情况少之又少,大多数情况都是你直接接手数据库和应用程序,这时你就需要两步走的了解你所接手的东西-通过外部和内部。

    外部方法包括从用户那里了解程序相关的信息,观察他们使用程序的过程,阅读用户文档和交接文档。

    内部方法是去看程序本身对数据库产生的操作。比如说Activity Monitor, Profiler等工具,也可以使用sys.dm_db_index usage_stats和sys.dm_db_missing_index_XXX系列DMV中找到所需信息,这些信息包括用的最多的查询,用的最多的索引,用的少的索引以及本应建却没有建的索引。

    通过找到拖累系统性能的查询,比如报表服务中用到的语句,agent中执行的T-SQL,SSIS中执行的T-SQL以及存储过程。找到这类信息就可以知道优化该从何处下手。

    得到上面的信息后,就可以知道哪些索引应当存在,哪些索引应该删除。

 

不要过度创建索引

    过多的索引和太少的索引都不是好事。表中该有多少索引可不是一个固定的数字。当你为主键,候选键和外键建立了索引之后,剩下的索引该怎么建就需要谨慎分析后再做定夺了。

 

要明白这点:同样的数据库在不同的环境下要有不同的索引

    在忙时或是闲时;在OLTP环境或是OLAP环境下,所需要的索引是不同的。

    比如每天晚上一次性大量更新数据的报表数据库在这时只需要少量索引,而在日间忙时则需要大量索引。数据库上跑少量查询要比数据库跑大量查询需要更少的索引。

 

要给每个表设置主键

    虽然SQL Server并不强制要求设置主键。但一个没有主键的表无论在OLTP还是OLAP环境下都是一件危险的事,因为没有主键就不能保证每行是唯一的。这时你就无法知道同一行数据是否在表中存在两条,尤其是在你还没有足够的信息去分析这点时。

    尽管SQL Server不强制要求设置主键,但主键是关系数据库的一个关键理论。如果没有主键约束,那么与之关联的唯一索引或是连接操作就有可能产生意料之外的性能问题。

    除此之外,很多第三方开发工具或插件也要求表有主键,比如说吧,ADO.Net的SqlCommandBuilder和Entity Data Modeler都依赖表中存在主键约束。另外,主键约束会创建一个同名的唯一索引来保证主键的唯一性。

 

考虑给每个表设置聚集索引

    本系列第三篇关于聚集索引的文章阐述了聚集索引带来的好处。使用聚集索引表中的数据就是按聚集索引键的顺序存在而不再以堆存放。使用聚集索引的好处是使得数据按照聚集索引键的顺序存放,并使得后插入的元素依然保持这个顺序。

    如果你遵循了上一个建议,那么每个表都应该有主键,因此,每一个表都应该有一个或多个索引,让其中的一个索引成为聚集索引。聚集索引本身并不会使得表上多了一个索引,而是让表的结构更好的组织。

    选择聚集索引键时,要记住第六篇文章中所说的,聚集索引键应该唯一,短和尽量不需要改动。

 

考虑使用外键作为聚集索引键的最左列

    将外键设置为聚集索引的最左列就是将表中的数据按照这列的值进行汇总和组织,这也是查询所需。比如说你用信用卡消费这个行为是和卡关联最强的的,而不是和你刷卡的商场以及处理这笔消费的银行。则将信用卡号作为消费记录表中聚集索引的最左列,使得所有同一张卡的消费信息就会存在连续的页中。

    当然了,你还需要另外一个很少变动的列和这个信用卡号列组合起来保证聚集索引键的唯一性。

 

考虑为索引添加包含列

    (译者注:这里作者文章有BUG,这段和上段一样,我就大胆的写一下原因吧。)为索引添加包含列的原因是减少对索引所在表的书签查找。因为包含列不会占用索引的非叶子节点空间,所以不会影响B树的高度,通过在叶子节点附加上一些列,使得索引更容易的“覆盖”所请求的查询,从而减少了书签查找,降低了查询成本。

    但同样,使用包含列使得非聚集索引占用的空间增加了,所以使用包含列时要综合考虑。

 

避免为重复值很多的未过滤列创建非聚集索引

    更早之前的一条建议“永远不要索引性别列”,是由于这列只会存在男性和女性两个值。当遇到WHERE Gender=的语句时使用表扫描要远远好于书签查找,查询优化器无法从这个索引中获益。

 

考虑为列中重复值最多的值创建过滤索引

    如果某列大量的行中都存在相同的值,这个值可以是NULL,那么使用过滤索引将这个值过滤掉,剩下的值所生成的索引就会更小,小索引使得查询优化器选择书签查找而不是表扫描,SQL Server也就更容易使用索引。

 

考虑使用填充因子来面对未来的数据增长

    假如一个表中只有几个月的数据,但这个表年底的数据已经可以估算出来时,重建索引的过程中将填充因子设置为7或8,这将使索引占用的页和年底占用的页大致相同,这可以更早的暴漏性能问题,比如说表扫描时IO的占用。

 

考虑使用填充因子来减少页分裂

    加入表中的数据已经达到了页所能容纳的最大值。那么再插入数据就会导致页分裂了。因此重建索引时可以使用填充因子,如果数据库写大于读的话,设置填充因子为75,如果读写大致相等的话,设置填充因子为90到95.

 

要在创建非聚集索引之前,先创建聚集索引

    与之对应的指导方针是:在删除聚集索引之前,先删除非聚集索引。如果你不按照这条方针做,则会导致无意义的重建非聚集索引。将表由聚集索引变为堆会使得表上的非聚集索引重建,因为非聚集索引的书签由聚集索引键变为RID。

 

要根据索引的使用频率定期整理索引碎片或是重建索引

    如果一个索引经常用于扫描,正如我们在第11篇文章中所说,那么外部碎片对于性能的影响就变得非常大。这时你就需要考虑在外部碎片到达10%的时候整理索引了。当外部碎片达到30%时就需要重建索引。对于OLTP环境来说,上面的值是一个分界点,这个点就是整理或重建索引的代价小于其带来的性能提升。

 

要经常更新索引的统计信息

    关键字是“经常”,也就是多久更新一次。通过了解跑在数据库上面的程序的负载之后,就知道该多久更新一次统计信息了。我已经在第14篇文章中讲述了为什么要定期更新索引。

 

总结

    上面的这些最佳实践是来自多个DBA多年来实践于不同环境所产生的。遵循这些指导方针可以帮助你创建更好的的索引。

分类: SQL Server 索引


本文转自CareySon博客园博客,原文链接http://www.cnblogs.com/CareySon/archive/2012/09/10/2678247.html,如需转载请自行联系原作者

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
相关文章
|
14天前
|
SQL 人工智能 算法
【SQL server】玩转SQL server数据库:第二章 关系数据库
【SQL server】玩转SQL server数据库:第二章 关系数据库
52 10
|
1月前
|
SQL 存储 数据库
sql事务、视图和索引
sql事务、视图和索引
14 0
|
24天前
|
SQL
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
17 0
|
14天前
|
SQL 算法 数据库
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
82 6
|
2天前
|
SQL 关系型数据库 MySQL
:“You have an error in your SQL syntax; check the manual that corresponds to your MySQL server versi
:“You have an error in your SQL syntax; check the manual that corresponds to your MySQL server versi
8 0
|
9天前
|
SQL 安全 网络安全
IDEA DataGrip连接sqlserver 提示驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接的解决方法
IDEA DataGrip连接sqlserver 提示驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接的解决方法
19 0
|
14天前
|
SQL 存储 数据挖掘
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例
服务器数据恢复环境: 一台安装windows server操作系统的服务器。一组由8块硬盘组建的RAID5,划分LUN供这台服务器使用。 在windows服务器内装有SqlServer数据库。存储空间LUN划分了两个逻辑分区。 服务器故障&初检: 由于未知原因,Sql Server数据库文件丢失,丢失数据涉及到3个库,表的数量有3000左右。数据库文件丢失原因还没有查清楚,也不能确定数据存储位置。 数据库文件丢失后服务器仍处于开机状态,所幸没有大量数据写入。 将raid5中所有磁盘编号后取出,经过硬件工程师检测,没有发现明显的硬件故障。以只读方式将所有磁盘进行扇区级的全盘镜像,镜像完成后将所
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例
|
16天前
|
SQL 数据库 索引
SQL索引失效原因分析与解决方案
SQL索引失效原因分析与解决方案
22 0
|
18天前
|
SQL 数据安全/隐私保护
SQL Server 2016安装教程
SQL Server 2016安装教程
21 1
|
18天前
|
SQL 安全 Java
SQL server 2017安装教程
SQL server 2017安装教程
16 1