索引的概念和创建索引例子

1 索引的概念

索引是一个单独的、物理的数据库结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。表的存储由两部分组成,一部分用来存放数据页面,另一部分存放索引页面。通常,索引页面相对于数据页面来说小得多。数据检索花费的大部分开销是磁盘读写,没有索引就需要从磁盘上读表的每一个数据页,如果有索引,则只需查找索引页面就可以了。所以建立合理的索引,就能加速数据的检索过程。

SQL Server采用B-树结构的索引,根据索引的顺序与数据表的物理顺序是否相同可以分为:聚簇索引(clustered index)和非聚簇索引(nonclustered index)。

(1)聚簇索引重新组织表中的数据以按指定的一个或多个列的值排序。聚簇索引的叶节点包含实际的数据,因此用它查找数据很快,但每个表只能建一个聚簇索引。

(2)非聚簇索引不重新组织表中的数据,它的叶节点中存储了组成非聚簇索引的列的值和行定位指针。一个表可以建249 个非聚簇索引。

通俗的说,汉语字典的正文就是一个建立在拼音基础上的聚簇索引,以英文字母“a”开头并以“z”结尾。比如,我们要查“阿”字,就会翻开字典的第一页,因为“阿”的拼音是“a”,所以排在字典的前面。如果您翻完了所有以“a”开头的部分仍然找不到这个字,那么就说明字典中没有这个字。同样的,如果查“做”字,就会把字典翻到最后。

字典的“偏旁部首”是非聚簇索引。比如我们要查“阿”字,在查部首之后,看到部首检字表中“阿”的页码是1页,“阿”的上面是“际”字,但页码却是277页,“阿”的下面是“陇”字,页码是416页。很显然,这些字并不是真正的分别位于“阿”字的上下方,现在看到的连续的“际、阿、陇”三字实际上就是他们在非聚簇索引中的排序,是字典正文中的字在非聚簇索引中的映射。

2 索引的使用

1)聚簇索引的使用

在聚簇索引下,数据在物理上按顺序排在数据页上,重复值也排在一起,因而在那些包含范围检查(between、<、<=、>、>=)或使用group by、order by的查询时,一旦找到具有范围中第一个键值的行,具有后续索引值的行必然连在一起,不必进一步搜索,避免了大范围扫描,可以大大提高查询速度。

聚簇索引的侯选列是:

u        经常按范围存取的列,如date>”20050101” and date< “20050131”;

u        经常在where子句中使用并且插入是随机的主键列;

u        在group by或order by中使用的列;

u        在连接操作中使用的列。

2)非聚簇索引的使用

由于非聚簇索引的叶级点不包含实际的数据,因此它检索效率较低,但一个表只能建一个聚簇索引,当用户需要建立多个索引时就需要使用非聚簇索引了。在建立非聚簇索引时,要权衡索引对查询速度的加快与降低修改速度之间的利弊。

在下面情况中使用非聚簇索引:

u        常用于集合函数(如Sum,....)的列;

u        常用于join, order by, group by的列;

u        查寻出的数据不超过表中数据量的20%。

3)创建索引需要注意的要点

1)    慎重选择作为聚簇索引的列

默认情况下,SQL Server用主键创建聚簇索引。这种做法常常造成聚簇索引的浪费。通常,我们会为每个表建立一个ID列,以区分每条数据,并且该列是自动增大的,步长一般为1。如果我们把这个列设为主键,SQL Server会将此列默认为聚簇索引。这样做可以使数据在数据库中按ID进行物理排序,但这种做法在实际应用中意义并不大。根据前面谈到的聚簇索引的定义和使用情况可以看出,使用聚簇索引的最大好处就是能够根据查询要求,迅速返回某个范围内的数据,避免全表扫描。在实际应用中,因为ID号是自动生成的,我们并不知道每条记录的ID号,所以我们不太可能用ID号来进行查询。这就使聚簇索引成为摆设,造成资源浪费。其次,让每个值都不同的ID列作为聚簇索引也不符合“大数目的不同值情况下不应建立聚簇索引”规则。

一般情况下,数据库应用系统进行数据检索都离不开“ 用户名(代码)”、“日期”字段。以笔者所用的HIS系统(医院管理信息系统)为例,我们进行费用、处方、检查单等信息检索时需要根据“住院号”和“日期”这两个字段来返回特定范围内的数据。下面我们分几种情况观察在不同索引条件下查询相同内容所用的时间。

假设病人费用表名为“brfy”,其中住院号字段名为“zyh”,日期字段名为“riqi”,要求是从表brfy中检索zyh为“028246”的病人2005年3月1日到20日的费用,对应的SQL语句如下:

Select * from brfy where zyh=’028246’ and riqi>=’20050301’ and riqi<=’20050320’;

第一种情况,用ID列建立聚簇索引,不为zyh和riqi建立索引,查询时间为87秒。

第二种情况,用ID列建立聚簇索引,为zyh和riqi两列建立非聚簇索引(zyh在前),查询时间为33秒。

第三种情况,用zyh和riqi两列建立聚簇索引(zyh在前),查询时间为2秒。

由以上分析可以看出聚簇索引是非常宝贵的,应该为经常用于检索某个范围内数据的列或group by、order by等子句的列建立聚簇索引,这样能够极大的提高系统性能。

2)    重视以多个列创建的索引中列的顺序问题

一些用户认为只要合理的选择列建立索引,不必关心列的顺序就可以提高检索速度,这种观点是错误的。多列索引中列的先后顺序应该和实际应用中where、group by或order by等子句里列的放置位置相同。参考上面举的例子,在第二、第三种情况下,如果把riqi放在zyh前面,执行上述SQL语句就不会用到这两个索引,检索的时间也会变得很长。

3 索引的维护

数据库系统运行一段时间后,随着数据行的插入、删除和数据页的分裂,索引对系统的优化性能就会大大降低。这时候,我们需要对索引进行分析和重建。

SQL Server使用DBCC SHOWCONTIG确定是否需要重建表的索引。在 SQL Server的查询分析器中输入命令:

Use database_name

Declare @table_id int

Set @table_id=object_id ('Employee')

Dbcc showcontig (@table_id)

在命令返回的参数中Scan Density 是索引性能的关键指示器,这个值越接近100%越好,一般在低于90%的情况下,就需要重建索引。重建索引可以使用DBCC DBREINDEX,使用方式如下:

dbcc dbreindex('表名', 索引名, 填充因子)       /*填充因子一般为90或100*/

如果重建后,Scan Density还没有达到100%,可以重建该表的所有索引:

dbcc dbreindex('表名', '', 填充因子)

在良好的数据库设计基础上,有效地使用索引是数据库应用系统取得高性能的基础。然而,任何事物都具有两面性,索引也不例外。索引的建立需要占用额外的存储空间,并且在增、删、改操作中也会增加一定的工作量,因此,在适当的地方增加适当的索引并从不合理的地方删除次要的索引,将有助于优化那些性能较差的数据库应用系统。实践表明,合理的索引设计是建立在对各种查询的分析和预测上的,只有正确地使索引与程序结合起来,才能产生最佳的优化方案。


1.创建表并插入数据

在Sql Server2008中创建测试数据库Test,接着创建数据库表并插入数据,sql代码如下:

复制代码
USE Test
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'emp_pay')DROP TABLE emp_pay
GO
USE Test
IF EXISTS (SELECT name FROM sys.indexes WHERE name = 'employeeID_ind')DROP INDEX emp_pay.employeeID_ind
GO
USE Test
GO
CREATE TABLE emp_pay
(employeeID int NOT NULL,base_pay money NOT NULL,commission decimal(2, 2) NOT NULL
)
INSERT emp_payVALUES (1, 500, .10)
INSERT emp_pay VALUES (2, 1000, .05)
INSERT emp_pay VALUES (6, 800, .07)
INSERT emp_payVALUES (5, 1500, .03)
INSERT emp_payVALUES (9, 750, .06)
复制代码

执行完上述sql代码以后我们会发现在Test数据库中多出了一张emp_pay表,数据库表的内容如下图所示:

2.无索引查找

从上图我们可以看出数据库中存储的数据排列顺序与我们插入的先后顺序一致。接下来我们查询employeeID=5的字段,执行如下sql代码:

USE Test
SELECT * FROM emp_pay where employeeID=5

在SQL SERVER MANAGEMENT STUDIO中我们点击“显示估计的查询计划”,会出现如下图所示的查询计划图:

其中表扫描的内容为:

3.创建索引

接下来我们为上述表添加聚集唯一索引,代码如下:

SET NOCOUNT OFF
CREATE UNIQUE CLUSTERED INDEX employeeID_indON emp_pay (employeeID)
GO

在执行完上述创建索引的代码以后,我们再次查询emp_pay的数据内容,如下图所示:

从上图我们可以发现数据内容已经按照employeeID进行了排序。

我们继续执行前面关于employeeID=5的查询,点击“显示估计的执行计划”,出现如下图所示内容:

聚集索引查找的内容为:

总结:

当我们为数据库表中的某一个字段创建索引,并且在查询语句中where子句中用到这样一个字段,那么查询效率会有所提高,我们上述实验因为数据量的关系查询效率提高不明显。

补充

我们上面添加的索引是唯一聚集索引,因此当插入的数据在employeeID字段出现重复时会报错。假如我们在创建索引之前数据字段出现重复,那么就不能创建唯一索引。

创建索引以后的排序(PS:2012-5-28)

执行如下sql语句

update emp_pay set employeeID=7 where employeeID=1;

然后再次执行全表查询,我们发现查询结果如下所示:

只要我们更新了employeeID,那么最后的更新结果都会按照employeeID的值进行升序排序。这是因为我们在employeeID上创建了索引的缘故。

删除索引(PS:2012-6-4)

我们可以通过sql server management studio这个工具删除索引,也可以通过sql语句进行索引的删除,假设我们要求删除在前面创建的索引employeeID_ind,那么sql语句如下代码所示:

DROP INDEX employeeID_ind ON emp_pay;

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

主索引和二级索引区别,并创建一个二级索引

透明表索引有两种&#xff1a;分别是主索引和二级索引。 主索引是在我们创建表激活后由系统自动创建的&#xff0c;这个我们不能修改&#xff1b;二级索引可以我们自己创建。主索引是表的主键&#xff0c;二级索引可以根据你自己需要用到表的任何字段的组合来创建。在使用二级索…

【个人笔记】Photoshop打开图片为”索引颜色“模式

如下图&#xff1a; 遇到这种问题无法编辑&#xff0c;”图像“——”模式“——将”索引颜色“改为”RGB颜色“ 然后就可以编辑了。

Axure9汉化

Axure9汉化 Axure下载安装后是英文版本&#xff0c;使用的时候会有点别扭&#xff0c;看一个单词需要反应一段时间&#xff0c;影响工作效率。 下面就是如何汉化的步骤&#xff1a;1-5 1、首先我们需要根据你的版本下载汉化包&#xff0c;打开axure ,点击help--About Axure …

若干tif文件转换成pdf

方案1&#xff1a; &#xff08;1&#xff09;用imageJ把多个tif文件弄成一个整合的tif文件&#xff1b; &#xff08;2&#xff09;然后用smaurt打开&#xff0c;另存为pdf 失败告终。 方案二&#xff1a;留个坑&#xff0c;没找到合适的解决方案。

华为OD机试真题B卷 Java 实现【寻找关键钥匙】,附详细解题思路

一、题目描述 小强正在参加《密室逃生》游戏&#xff0c;当前关卡要求找到符合给定 密码K&#xff08;升序的不重复小写字母组成&#xff09;的箱子&#xff0c;并给出箱子编号&#xff0c;箱子编号为1~N。 每个箱子中都有一个字符串s&#xff0c;字符串由大写字母&#xff0…

LC-1130. 叶值的最小代价生成树(贪心、区间DP、单调栈)

1130. 叶值的最小代价生成树 难度中等272 给你一个正整数数组 arr&#xff0c;考虑所有满足以下条件的二叉树&#xff1a; 每个节点都有 0 个或是 2 个子节点。数组 arr 中的值与树的中序遍历中每个叶节点的值一一对应。每个非叶节点的值等于其左子树和右子树中叶节点的最大…

人工智能粒子群优化三大算法

粒子群优化是以邻域原理&#xff08;neighborhood principle&#xff09;为基础进行操作的&#xff0c;该原理来源于社会网络结构研究中。驱动粒子群优化的特性是社会交互作用。群中的个体&#xff08;粒子&#xff09;相互学习&#xff0c;而且基于获得的知识移动到更相似于它…

Golang每日一练(leetDay0082) 用队列实现栈、用栈实现队列

目录 225. 用队列实现栈 Implement Stack Using Queues &#x1f31f; 232. 用栈实现队列 Implement Queue Using Stacks &#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 …

PS07海报截剪和切片(标尺使用),PS08图框工具(剪贴蒙版),PS09吸管工具组(颜色取样)

PS07海报截剪和切片&#xff08;标尺使用&#xff09; PS08图框工具&#xff08;剪贴蒙版&#xff09;PS09吸管工具组&#xff08;颜色取样&#xff09;

ps制作太极图

最终效果&#xff1a; 操作步骤&#xff1a; (1)、 新建文件-800*800px&#xff0c;打开标尺&#xff0c;新建参考线、得到中心点。 ctrlr 打开标尺&#xff0c; 学会 拉 标尺线&#xff0c; 拉出两条标尺线&#xff0c;让其水平、垂直相交。 (2)、 椭圆选框-以中心点绘制正圆…

用ps制作太极图

操作步骤&#xff1a; (1)、 新建文件-800*800px&#xff0c;打开标尺&#xff0c;新建参考线、得到中心点。 ctrlr 打开标尺&#xff0c; 学会 拉 标尺线&#xff0c; 拉出两条标尺线&#xff0c;让其水平、垂直相交。 (2)、 椭圆选框-以中心点绘制正圆&#xff08;按AltShi…

ps中怎样测量标尺线之间的距离及怎样切换距离单位

2019独角兽企业重金招聘Python工程师标准>>> 首先说一下&#xff0c;我用ps还不是很熟练&#xff0c;所以都是初级的问题&#xff0c;希望各位ps大神莫喷~~首先说一下怎么找到标尺呢&#xff1f;打开ps后&#xff0c;最上面有一个视图&#xff0c;点击后将标尺选项前…

前端ps基本操作

在还原设计时,我们需要使用 photoshop打开sd格式的设计,作为的工程师,我们不要太多的ps技巧,只需要了 一些简单的基本操作即可 1、alt 滚轮缩放放图片 2、空格鼠标左健拖动图片 3、shiftm切换选取工具,使用鼠标左键选择,ctrld可以取消选取 4、F8查看信息,可以查看选取内容的…

2.ps基本操作

提示&#xff1a;文章写完后&#xff0c;ps基本操作。 1、ps安装包 阿里云盘分享https://www.aliyundrive.com/s/XWxksTdanpW获取码&#xff1a;mp74 ps安装包 https://www.aliyundrive.com/s/XWxksTdanpW 提取码: mp74 点击链接保存&#xff0c;或者复制本段内容&#xff0c;打…

photoshop标尺工具_RulersGuides.js – Web上的Photoshop样式标尺和指南

关于Photoshop的最好的事情之一是其易于使用的指导线 &#xff0c;可以从标尺上拉出。 这些指南可以使放置物品和正确放置天平时的设计过程变得更加容易。 令我们非常高兴的是&#xff0c; 马克罗利奇 &#xff08; Mark Rolich &#xff09;实现了此特殊功能&#xff0c;以便…

chatgpt赋能python:Python中输入的全面介绍

Python中输入的全面介绍 在Python编程语言中&#xff0c;输入是指程序要求用户将内容输入到程序中进行处理。输入函数为input()&#xff0c;它允许用户直接在程序中输入数据。本文将全面介绍Python中输入的用法&#xff0c;包括如何使用input()函数、如何进行输入的类型转换以…

软件测试总结

软件生命周期(SDLC)的六个阶段 1、问题的定义及规划 此阶段是软件开发方与需求方共同讨论&#xff0c;主要确定软件的开发目标及其可行性。 2、需求分析 在确定软件开发可行的情况下&#xff0c;对软件需要实现的各个功能进行详细分析。需求分析阶段是一个很重要…

pr片头、滚动与开放式字幕制作

pr字幕与滚动字幕制作&#xff1a; 片头字幕&#xff1a;点击文字工具&#xff08;Ctrl鼠标左键 打点&#xff09; 开放式字幕&#xff1a;新建序列-字幕 滚动字幕&#xff1a;旧版标题-滚动选项

ckeditor动态显示隐藏工具栏指定的按钮

客户说工具栏太复杂了&#xff0c;但是有时候又能用到&#xff0c;所以给了个需求&#xff0c;做一个按钮能实现显示或隐藏按钮 好吧&#xff0c;客户是上帝&#xff0c;开搞 思路&#xff1a;ckeditor添加一个自定义按钮&#xff0c;里面方法实现display&#xff1a;none样式…