SQL Server 查询性能优化——创建索引原则(一)

 

     索引是什么?索引是提高查询性能的一个重要工具,索引就是把查询语句所需要的少量数据添加到索引分页中,这样访问数据时只要访问少数索引的分页就可以。但是索引对于提高查询性能也不是万能的,也不是建立越多的索引就越好。索引建少了,用WHERE子句找数据效率低,不利于查找数据。索引建多了,不利于新增、修改和删除等操作,因为做这些操作时,SQL SERVER除了要更新数据表本身,还要连带地立即更新所有的相关索引,而且过多的索引也会浪费硬盘空间。因此要建得恰到好处,这就需要经验了。

 

一:索引的基本目的

     索引的基本目的是在大量数据中找寻少量数据。你可以想像一下,若一本书有700页,就像数据表有700个数据页,而索引却有600个索引页,你会想用索引来查询书籍的内容吗?

     索引字段的值重复性越低越好,假设书籍中如“的”“了”这些在文章中重复性极高的字,每页都有一大堆,你会先翻索引页某个位置有“的”,翻回该页读取了“的”之后,再索引看下一个“的”,结果是在先前同一页的不同位置,又翻回书籍原页查看下一个“的”。

     那么怎么理解索引是从大量数据中寻找少量数据呢?下面我们举个例子来说明。

     如果一个数据表的记录平均长度为400字节,则100万条记录需要5万个数据页,其计算公式如下:

  1000000/8060/400=50000

  如果该数据表建立聚集索引,键值为4个字节长度,而ID的数据长度为13个字节,因此索引结构每条记录为20个字节。

  4(聚集索引键值)+13ID键值)+3(管理信息)=20

  以ID字段所建立的索引,100%填充率,则总分页数约为2482页,其计算方式如下:

  1000000/(8060/20)

  即使是使用80%的填充率来计算也只有3106页。其计算方式如下:

  1000000/((8060*0.8)/20)

  从上面可以看出如果是第一种情况,则索引页只占到总数据页的5%:

  2482/50000=0.04964 

  即使考虑取每页只填充80%的索引数据,第二种情况,索引页也只是占总数据页的6%:

  3106/50000=0.06212 

  再说如果查询条件中的字段建立索引,则由于索引键值数据都是以B-Tree有顺序的摆放,所以可采用二分查找找数据。也就是2N次方大于记录数,就可以找到该条数据。而220次方大于100万,因此最多找寻20次就可以找到该条记录。由于比较次数少,数据结构也小,节省访问硬盘与内在的资源,索引将大幅提升找寻数据的效率。SQL SERVER为提高访问与查找对比的效率,用来作索引的数据域键值愈小愈好,也就是要让分页尽量存更多的键值记录。

 

 注:

  如果未使用 UNIQUE 属性创建聚集索引,数据库引擎将向表自动添加一个 字节的 uniqueifier 列。必要时,数据库引擎将向行自动添加一个 uniqueifier 值以使每个键唯一。此列和列值供内部使用,用户不能查看或访问。

 

 

二:什么是索引

  在 SQL Server 中,索引是按 树结构进行组织的。如下图。

            

 

  您也可以把索引理解为一种特殊的目录。微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引、簇集索引)和非聚集索引(nonclustered index,也称非聚类索引、非簇集索引)。下面,举例来说明一下聚集索引和非聚集索引的区别:

  其实,新华字典的正文本身就是一个聚集索引。比如,我们要查按”字,就会很自然地翻开字典的前几页,因为按”的拼音是“an”,而按照拼音排序的新华字典是以英文字母“a”开头并以“z”结尾的,那么按”字就自然地排在字典的前部。如果您翻完了所有以“a”开头的部分仍然找不到这个字,那么就说明新华字典中没有这个字;同样的,如果查招”字,那也会将新华字典翻到最后部分,因为招”的拼音是“zhao。也就是说,新华字典的正文部分本身就是一个目录,您不需要再去查其他目录来找到您需要找的内容。我们把这种正文内容本身就是一种按照一定规则排列的目录称为聚集索引

  如果您碰到一个不认识的字,不知道它的发音,这时候,您就不能按照刚才的方法找到您要查的字,而需要去根据偏旁部首查到您要找的字,然后根据这个字后的页码直接翻到某页来找到您要找的字。但您结合部首目录检字表而查到的字的排序并不是真正的正文的排序方法,比如您查字,我们可以看到在查部首之后的检字表中的页码是672页,检字表中的上面是字,但页码却是63 页,的下面是字,页面是390页。很显然,这些字并不是真正的分别位于字的上下方,现在您看到的连续的驰、张、弩三字实际上就是他们在非聚集索引中的排序,是字典正文中的字在非聚集索引中的映射。我们可以通过这种方式来找到您所需要的字,但它需要两个过程,先找到目录中的结果,然后 再翻到您所需要的页码。我们把这种目录纯粹是目录,正文纯粹是正文的排序方式称为非聚集索引

 

通过以上例子,我们可以理解到什么是聚集索引非聚集索引。进一步引申一下

 

聚集索引

  聚集索引指的是数据表本身就是索引的一部分,就是指数据表本身就是聚集索引的子叶层,整个数据表的摆放顺序是按照你选定的键值由小到大排序,SQL SERVER  2000 之后的版本可指定数据由大到小排序。

  整个数据表按照键值字段由小到大排序,再搭配由键值字段加上指针的上层索引结构,也就是根节点和非子叶层级,形成整个聚集索引。因为数据表内实际摆放数据的方式只能遵循一种顺序,所以一个数据表只能有一个聚集索引。在指定聚集索引时,数据域本身并不需要唯一,或指定为唯一的聚集索引,SQL SERVER内部会自动为重复的键值建立4个字节的唯一标识。

  如果你的数据表有一列常常用来排序,另一列常常用来 范围查询,还有一列重复性非常高,则该用哪一列来做聚集索引。正确答案是依据哪个查询最重要,最常被用户执行。例如:你的老板一小时内多次执行某个查询当然比一个月执行一两次的查询来得重要。

  表(堆)创建聚集索引或删除和重新创建现有聚集索引时,要求数据库具有额外的可用工作区来容纳数据排序结果和原始表或现有聚集索引数据的临时副本。

  当堆或聚集表具有多个分区时,每个分区都有一个堆或 树结构,其中包含该指定分区的行组。例如,如果一个聚集表有 个分区,那么将有 个 树,每个分区一个。

 

  聚集索引( Clustered Index

  ·        聚集索引的叶节点就是实际的数据页

  ·        在数据页中数据按照索引顺序存储

  ·        行的物理位置和行在索引中的位置是相同的

  ·        每个表只能有一个聚集索引

  ·        聚集索引的平均大小大约为表大小的 5%左右

 

  要使用索引来更有效地排序查询数据,最直接的方式就是在你要排序的字段上建立聚集索引。在建立聚集索引之后,SQL SERVER会重新组织数据页,让其中的数据行按照聚集索引中键值的顺序存储。SQL SERVER不需要在硬盘上的数据一定要实际按照聚集索引排序,但在建立聚集索引时,会尝试在逻辑上排序数据的同时,也会在物理上让数据尽可能地排序。在索引子叶层级中的每个数据页都有一个指针指向索引分页的前一页与后一页,形成双向链接串行,在内部的系统数据表包含了各索引子叶层第一个分页的地址,为了保证数据在逻辑上是依照聚集索引的顺序存放的,SQL SERVER 只需要由第一个分页开始,并依照其连接串行一个接着一个依序寻找数据即可。如下图。

 

        

 

注:聚集表是有聚集索引的表。

 

 

非聚集索引

   非聚集索引是完全独立于数据表之外的结构,所以不会影响数据行的顺序,其子叶层包含索引行。每个索引行包含非聚集键值、行定位符和任意包含列或非键列。行定位符中存入的数据有两种类型:书签(BOOKMARK)或聚集索引的键值。如果数据表上建立了聚集索引,则行定位符中存入的数据就是聚集索引的键值。如果数据表没有建立聚集索引,则行定位符中存入的数据就是书签,即指向数据表中记录具体位置的ROWID,也就是文档编号、分页编号与页内记录编号(称之为SOLT编号)所组合成的值。通过该ROWID 在数据表内获取数据就称为书签查找 BOOKMARK LOOKUP。所以,一般通过非聚集索引查找到符合的键值后,还会搭配书签查找。

  当非聚集索引从结构中找到符合的记录时,虽然在子叶层该键值是由小到大排序,因此可能在一个分页上就有全部符合查询条件的键值,但因为数据表中数据行的摆放是没有按顺序的(或是说没有按照该非聚集索引的键值顺序摆放),所以真正符合记录的数据是散布在文档各处的,而SQL SERVER每次读取数据都是以数据页为单位,因此,找到一条记录所在位置后,要先将存放该条记录的分页读到内存中,再从该页读出记录。

  因为BOOKMARK LOOKUP是进行随机的I/O操作,当符合查询的记录很多时,通过非聚集索引访问将导致数据页读取非常频繁,就算两条记录在同一个分页,该分页也会被重复读两次,因此或符合的记录有N条,就需要读取数据表内的分页N页,虽然大部分的读取操作都是针对内存中的高速缓存,但记录数过多时一样没有效率,还不如数据表扫描,全部扫描一遍,把符合条件数据找出来。

  虽然 SQL 2005 以后的版本中已经不在提 BOOKMARK LOOKUP(但实际上却是换汤不换药),我们的很多搜索都是使用如下的搜索过程:先在非聚集中找,然后再在聚集索引中找。如下图。

        

 

 

  非聚集索引 ( Unclustered Index  

  ·        非聚集索引的页,不是数据,而是指向数据页的页。

  ·        若未指定索引类型,则默认为非聚集索引

  ·        叶节点页的次序和表的物理存储次序不同

  ·        每个表最多可以有 249个非聚集索引(一般认为每个表不应该超过10个索引)

  ·        在非聚集索引创建之前创建聚集索引(否则会引发索引重建)

 

  聚集索引与非聚集索引使用的情况:

 动作描述

使用聚集索引 

 使用非聚集索引

 外键列

 应

 应

 主键列

 应

 应

 列经常被分组排序(order by)

 应

 应

 返回某范围内的数据

 应

 不应

 小数目的不同值

 应

 不应

 大数目的不同值

 不应

 应

 频繁更新的列

 不应 

 应

 频繁修改索引列

 不应

 应

 一个或极少不同值

 不应

 不应

 

  今天就普及一下索引的一些基本知识,明天来说明怎么选择要创建索引的列,条件是什么,方法是什么。

转载于:https://www.cnblogs.com/chillsrc/archive/2012/09/19/2694313.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/361238.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WordPress强制跳转https教程

在互联网火热的今天,安全问题显得越来越重要,为了用户信息安全,很多热门网站都启用了https 有小伙伴就问:我启用了https,为什么访问的时候显示的还是http呢? 其实,有时候并不是因为我们ssl证书…

AEM中的单元测试(大声思考)

如果要在AEM中进行单元测试,这不是任何建议,而是各种思想的总结和一些可供选择的选项。 一段时间以前,我已经为客户进行了一些研究,这篇文章在很大程度上受到了这项工作的影响,但是很多上下文相关的东西已经被淘汰了。…

Java 8的装饰器模式

在最近的一篇文章中,我描述了装饰器模式如何拯救了我的一天。 我给出了一个小代码段,其中包含创建装饰器的最简单方法,但承诺Java 8会有更好的方法。 这里是: 用Java 8装饰 HyperlinkListener listener this::changeHtmlViewBa…

WPF中使用流文档灵活地显示内容

WPF中使用流文档灵活地显示内容 by: Markus Egger form: http://msdn.microsoft.com/msdnmag/issues/07/08/wpf/default.aspx?loczh Windows Presentation Foundation (WPF) 提供了一系列功能。事实上,功能…

canvas图表(4) - 散点图

原文地址:canvas图表(4) - 散点图 今天开始完成散点图,做完这一节,我的canvas图表系列就算是完成了,毕竟平时最频繁用到的就是这几类图表了:柱状,折线,饼图,散点。经过编写canvas图表…

Java8排序–性能陷阱

Java 8带来了lambda的所有优点,使我们能够使用声明式样式进行编程。 但这真的免费吗? 我们是否应该担心必须为新的编程功能付出的代价? 这是一个我们可能要担心的例子。 考虑对这个简单类的实例进行排序: private static class…

词频统计工程相关

&#xff08;the format of this article is from SkYjoKEr&#xff09; //开始干之前 模块1、WordClass 一个存放单词以及实现相关操作的类&#xff0c;其中单词以二元组<word, freq>的形式存储。 &#xff08;20min&#xff09; 2、WordCounter 完成单词统计&#xff0…

canvas图形编辑器

原文地址&#xff1a;http://jeffzhong.space/2017/11/02/drawboard/   使用canvas进行开发项目&#xff0c;我们离不开各种线段&#xff0c;曲线&#xff0c;图形&#xff0c;但每次都必须用代码一步一步去实现&#xff0c;显得非常麻烦。有没有一种类似于PS&#xff0c;CAD…

2015年Java 8强势开始

JDK 8从2015年开始&#xff0c;其博客文章和文章的受欢迎程度将激增。 这与Java本月自动升级到JDK 8恰好吻合。 在这篇文章中&#xff0c;我列出并简要描述了2015年已经发布的有关JDK 8的众多文章和文章。 JDK 8 Streams在最近的帖子中很受欢迎。 我在2015年发表的第一篇博文是…

富文本编辑器、日期选择器、软件天堂、防止XSS攻击、字体icon、转pdf

【超好用的日期选择器】 Layui&#xff1a;http://www.layui.com/laydate/ 备注&#xff1a;日期选择器&#xff0c;用过很多很多&#xff0c;自己也写过一些&#xff1b;相信这个简单而又不简单的选择器&#xff0c;能够给你多些美好的时光 【很不错的几个富文本编辑器】 …

GIS开源程序收集(转载)

分类包括&#xff1a;GIS基础函数库、GIS控件、GIS桌面程序、GIS数据引擎、WEBGIS浏览器端程序、WEBGIS服务器程序、GPS相关程序&#xff0c;其它分类 派系&#xff1a;“NET”派系&#xff0c;“C”派系&#xff0c;“Java”派系&#xff0c;脚本派系&#xff0c;其它派系 “N…

Sacrilege –自定义SWT滚动条

SWT是本机OS小部件之上的薄抽象层。 如果您打算将应用程序与OS外观很好地集成在一起&#xff0c;那将是一件非常好的事情。 但是&#xff0c;作为一种折衷方案&#xff0c;这种方法大大限制了样式功能。 特别是&#xff0c;我感觉到本机SW​​T滚动条通常会干扰更精细的视图布…

关键字屏蔽-正则

【问题】关键字屏蔽是社交类软件必做的功能&#xff0c;当然了&#xff0c;一般来讲都是产品的中后期来做&#xff1b;不同产品规定不一样&#xff0c;跟着产品运营走&#xff0c;可以的 【方法】我们从技术的角度来看到这个问题&#xff0c;实现一个功能后者说实现一个需求&a…

Sub-Projects in Xcode(Xcode中的子项目)

source:http://www.cocoanetics.com/2011/12/sub-projects-in-xcode/ translation:http://www.xiaojiayi.com/2012/08/15/xcode中的子项目&#xff08;译文&#xff09;/ is work! 转载于:https://www.cnblogs.com/snowleung/archive/2012/09/26/2703250.html

堆上与堆外的内存使用情况

总览 最近有人问我在Java中使用堆内存的好处和智慧。 面临相同选择的其他人可能会对这些答案感兴趣。 堆外内存没什么特别的。 线程堆栈&#xff0c;应用程序代码&#xff0c;NIO缓冲区都在堆外。 实际上&#xff0c;在C和C 中&#xff0c;您只有非托管内存&#xff0c;因为默…

从CSS实现正片叠底看=混合模式mix-blend-mode

兼容性&#xff1a;这个东西说多了也没意思&#xff0c;像HTML5和CSS3这种兼容性时刻变化的东东&#xff0c;我们最好在自己支持的设备上实验&#xff0c;不支持&#xff0c;就在想办法呗&#xff0c;这个东西就是为了方便和好玩 所有属性&#xff1a; mix-blend-mode: normal…

实现对gridview删除行时弹出确认对话框的四种方法

实现对gridview删除行时弹出确认对话框的四种方法 在.net2.0中&#xff0c;实现对gridview删除行时弹出确认对话框的四种方法 1&#xff0c;GridView中如何使用CommandField删除时&#xff0c;弹出确认框? 在VS2005提供的GridView中我们可以直接添加一个CommandField删除列&am…

我最喜欢的Java拼图2 + 1 = 4

这是我当前最喜欢的Java难题。 您如何获取代码来执行此操作&#xff1f; Integer b 2; Integer c 1;System.out.println("bc : " (bc) ); // output: bc : 4 !!Sytem.out.println&#xff08;&#xff09;没有技巧&#xff0c;即您将能够在调试器中看到相同的值。…

CSS3盒模型温故

CSS有一种基础设计模式叫盒模型&#xff0c;定义了Web页面中的元素是如何看做盒子来解析的。每一个盒子有不同的展示界面&#xff0c;下面就来介绍盒模型&#xff0c;主要有一下几种盒模型&#xff1a;inline、inline-block、block、table、absolute position、float。浏览器把…

SSL与WildFly 8和Undertow

我一直在研究WildFly 8的一些安全性主题&#xff0c;偶然发现了一些配置文档&#xff0c;这些文档没有很好地记录。 其中之一是新Web子系统Undertow的TLS / SSL配置。 有许多关于较旧的Web子系统的文档&#xff0c;并且确实仍然可以使用&#xff0c;但是这里是使用新方法进行配…