当前位置:文档之家› SQLServer索引结构及其使用(三)

SQLServer索引结构及其使用(三)

SQLServer索引结构及其使用(三)
SQLServer索引结构及其使用(三)

SQLServer索引结构及其使用(三)

实现小数据量和海量数据的通用分页显示存储过程

建立一个 Web 应用,分页浏览功能必不可少。这个问题是数据库处理中十分常见的问题。经典的数据分页方法是:ADO 纪录集分页法,也就是利用ADO自带的分页功能(利用游标)来实现分页。但这种分页方法仅适用于较小数据量的情形,因为游标本身有缺点:游标是存放在内存中,很费内存。游标一建立,就将相关的记录锁住,直到取消游标。游标提供了对特定集合中逐行扫描的手段,一般使用游标来逐行遍历数据,根据取出数据条件的不同进行不同的操作。而对于多表和大表中定义的游标(大的数据集合)循环很容易使程序进入一个漫长的等待甚至死机。

更重要的是,对于非常大的数据模型而言,分页检索时,如果按照传统的每次都加载整个数据源的方法是非常浪费资源的。现在流行的分页方法一般是检索页面大小的块区的数据,而非检索所有的数据,然后单步执行当前行。

最早较好地实现这种根据页面大小和页码来提取数据的方法大概就是“俄罗斯存储过程”。这个存储过程用了游标,由于游标的局限性,所以这个方法并没有得到大家的普遍认可。

后来,网上有人改造了此存储过程,下面的存储过程就是结合我们的办公自动化实例写的分页存储过程:

CREATE procedure pagination1

(@pagesize int, --页面大小,如每页存储20条记录

@pageindex int --当前页码

)

as

set nocount on

begin

declare @indextable table(id int identity(1,1),nid int) --定义表变量

declare @PageLowerBound int --定义此页的底码

declare @PageUpperBound int --定义此页的顶码

set @PageLowerBound=(@pageindex-1)*@pagesize

set @PageUpperBound=@PageLowerBound+@pagesize

set rowcount @PageUpperBound

insert into @indextable(nid) select gid from TGongwen

where fariqi >dateadd(day,-365,getdate()) order by fariqi desc select O.gid,O.mid,O.title,O.fadanwei,O.fariqi from TGongwen O,@indextable t where O.gid=t.nid and t.id>@PageLowerBound

and t.id<=@PageUpperBound order by t.id

end

set nocount off

以上存储过程运用了SQL SERVER的最新技术――表变量。应该说这个存储过程也是一个非常优秀的分页存储过程。当然,在这个过程中,您也可以把其中的表变量写成临时表:CREATE TABLE #Temp。但很明显,在SQL SERVER中,用临时表是没有用表变量快的。所以笔者刚开始使用这个存储过程时,感觉非常的不错,速度也比原来的ADO的好。但后来,我又发现了比此方法更好的方法。

笔者曾在网上看到了一篇小短文《从数据表中取出第n条到第m条的记录的方法》,全文如下:

从publish 表中取出第 n 条到第 m 条的记录:

SELECT m-n+1 *

FROM publish

WHERE (id NOT IN

(SELECT n-1 id

FROM publish))

id 为publish 表的关键字

我当时看到这篇文章的时候,真的是精神为之一振,觉得思路非常得好。等到后来,我在作办公自动化系统(https://www.doczj.com/doc/3a17388437.html,+ C#+SQL SERVER)的时候,忽然想起了这篇文章,我想如果把这个语句改造一下,这就可能是一个非常好的分页存储过程。于是我就满网上找这篇文章,没想到,文章还没找到,却找到了一篇根据此语句写的一个分页存储过程,这个存储过程也是目前较为流行的一种分页存储过程,我很后悔没有争先把这段文字改造成存储过程:CREATE PROCEDURE pagination2

(

@SQL nVARCHAR(4000), --不带排序语句的SQL语句

@Page int, --页码

@RecsPerPage int, --每页容纳的记录数

@ID VARCHAR(255), --需要排序的不重复的ID号

@Sort VARCHAR(255) --排序字段及规则

)

AS

DECLARE @Str nVARCHAR(4000)

SET @Str=''SELECT ''+CAST(@RecsPerPage AS VARCHAR(20))+'' * FROM

(''+@SQL+'') T WHERE T.''+@ID+''NOT IN (SELECT ''+CAST((@RecsPerPage*(@Page-1)) AS VARCHAR(20))+'' ''+@ID+'' FROM (''+@SQL+'') T9 ORDER BY ''+@Sort+'') ORDER BY ''+@Sort

PRINT @Str

EXEC sp_ExecuteSql @Str

GO

其实,以上语句可以简化为:

SELECT 页大小 *

FROM Table1 WHERE (ID NOT IN (SELECT 页大小*页数 id FROM 表 ORDER BY id)) ORDER BY ID

但这个存储过程有一个致命的缺点,就是它含有NOT IN字样。虽然我可以把它改造为:SELECT 页大小 *

FROM Table1 WHERE not exists

(select * from (select top (页大小*页数) * from table1 order by id) b where b.id=a.id )

order by id

即,用not exists来代替not in,但我们前面已经谈过了,二者的执行效率实际上是没有区别的。既便如此,用结合NOT IN的这个方法还是比用游标要来得快一些。

虽然用not exists并不能挽救上个存储过程的效率,但使用SQL SERVER中的关键字却是一个非常明智的选择。因为分页优化的最终目的就是避免产生过大的记录集,而我们

在前面也已经提到了的优势,通过即可实现对数据量的控制。

在分页算法中,影响我们查询速度的关键因素有两点:和NOT IN。可以提高我们的查询速度,而NOT IN会减慢我们的查询速度,所以要提高我们整个分页算法的速度,就要彻底改造NOT IN,同其他方法来替代它。

我们知道,几乎任何字段,我们都可以通过max(字段)或min(字段)来提取某个字段中的或最小值,所以如果这个字段不重复,那么就可以利用这些不重复的字段的max或min 作为分水岭,使其成为分页算法中分开每页的参照物。在这里,我们可以用操作符“>”或“<”号来完成这个使命,使查询语句符合SARG形式。如:

Select top 10 * from table1 where id>200

于是就有了如下分页方案:

select top 页大小 *

from table1

where id>

(select max (id) from

(select top ((页码-1)*页大小) id from table1 order by id) as T

)

order by id

在选择即不重复值,又容易分辨大小的列时,我们通常会选择主键。下表列出了笔者用有着1000万数据的办公自动化系统中的表,在以GID(GID是主键,但并不是聚集索引。)为排序列、提取gid,fariqi,title字段,分别以第1、10、100、500、1000、1万、10万、25万、50万页为例,测试以上三种分页方案的执行速度:(单位:毫秒)

页码方案1 方案2 方案3 1 60 30 76 10 46 16 63 100 1076 720 130 500 540 12943 83 1000 17110 470 250 10000 24796 4500 140 100000 38326 42283 1553 250000 28140 128720 2330 500000 121686 127846 7168 从上表中,我们可以看出,三种存储过程在执行100页以下的分页命令时,都是可以信任的,速度都很好。但第一种方案在执行分页1000页以上后,速度就降了下来。第二种方案大约是在执行分页1万页以上后速度开始降了下来。而第三种方案却始终没有大的降势,后劲仍然很足。

在确定了第三种分页方案后,我们可以据此写一个存储过程。大家知道SQL SERVER 的存储过程是事先编译好的SQL语句,它的执行效率要比通过WEB页面传来的SQL语句的执行效率要高。下面的存储过程不仅含有分页方案,还会根据页面传来的参数来确定是否进行

数据总数统计。

--获取指定页的数据:

CREATE PROCEDURE pagination3

@tblName varchar(255), -- 表名

@strGetFields varchar(1000) = ''*'', -- 需要返回的列

@fldName varchar(255)='''', -- 排序的字段名

@PageSize int = 10, -- 页尺寸

@PageIndex int = 1, -- 页码

@doCount bit = 0, -- 返回记录总数, 非 0 值则返回

@OrderType bit = 0, -- 设置排序类型, 非 0 值则降序

@strWhere varchar(1500) = '''' -- 查询条件 (注意: 不要加 where)

AS

declare @strSQL varchar(5000) -- 主语句

declare @strTmp varchar(110) -- 临时变量

declare @strOrder varchar(400) -- 排序类型

if @doCount != 0

begin

if @strWhere !=''''

set @strSQL = "select count(*) as Total from [" + @tblName + "] where "+@strWhere else

set @strSQL = "select count(*) as Total from [" + @tblName + "]"

end

--以上代码的意思是如果@doCount传递过来的不是0,就执行总数统计。以下的所有代码都是@doCount为0的情况:

else

begin

if @OrderType != 0

begin

set @strTmp = "(select max"

set @strOrder = " order by [" + @fldName +"] asc"

end

if @PageIndex = 1

begin

if @strWhere != ''''

set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ "

from [" + @tblName + "] where " + @strWhere + " " + @strOrder else

set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ "

from ["+ @tblName + "] "+ @strOrder

--如果是第一页就执行以上代码,这样会加快执行速度

end

else

begin

--以下代码赋予了@strSQL以真正执行的SQL代码

set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " from ["

+ @tblName + "] where [" + @fldName + "]" + @strTmp + "(["+ @fldName + "]) from (select top " + str((@PageIndex-1)*@PageSize) + " ["+ @fldName + "]

from [" + @tblName + "]" + @strOrder + ") as tblTmp)"+ @strOrder if @strWhere != ''''

set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " from ["

+ @tblName + "] where [" + @fldName + "]" + @strTmp + "(["

+ @fldName + "]) from (select top " + str((@PageIndex-1)*@PageSize) + " ["

+ @fldName + "] from [" + @tblName + "] where " + @strWhere + " "

+ @strOrder + ") as tblTmp) and " + @strWhere + " " + @strOrder

end

end

exec (@strSQL)

GO

上面的这个存储过程是一个通用的存储过程,其注释已写在其中了。在大数据量的情况下,特别是在查询最后几页的时候,查询时间一般不会超过9秒;而用其他存储过程,在实践中就会导致超时,所以这个存储过程非常适用于大容量数据库的查询。笔者希望能够通过对以上存储过程的解析,能给大家带来一定的启示,并给工作带来一定的效率提升,同时希望同行提出更优秀的实时数据分页算法。

数据库索引的优缺点及使用时的注意事项

本文介绍了数据库索引,及其优、缺点。针对MySQL索引的特点、应用进行了详细的描述。分析了如何避免MySQL无法使用,如何使用EXPLAIN分析查询语句,如何优化MySQL索引的应用。 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它 们包含着对数据表里所有记录的引用指针。 注:[1]索引不是万能的!索引可以加快数据检索操作,但会使数据修改操作变慢。每修改数据记录,索引就必须刷新一次。为了在某种程序上弥补这一缺陷,许多SQL命令都有一个DELAY_KEY_WRITE项。这个选项的作用是暂时制止MySQL 在该命令每插入一条新记录和每修改一条现有之后立刻对索引进行刷新,对索引的刷新将等到全部记录插入/修改完毕之后再进行。在需要把许多新记录插入某个数据表的场合,DELAY_KEY_WRITE 选项的作用将非常明显。[2]另外,索引还会在硬盘上占用相当大的空间。因此应该只为最经常查询和最经常排序的数据列建立索引。注意,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。 从理论上讲,完全可以为数据表里的每个字段分别建一个索引,但MySQL把同一个数据表里的索引总数限制为16个。 1. InnoDB数据表的索引 与MyISAM数据表相比,索引对InnoDB数据的重要性要大得多。在InnoDB数据表上,索引对InnoDB数据表的重要性要在得多。在InnoDB数据表上,索引不仅会在搜索数据记录时发挥作用,还是数据行级锁定机制的苊、基础。"数据行级锁定"的意思是指在事务操作的执行过程中锁定正在被处理的个别记录,不让其他用户进行访问。这种锁定将影响到(但不限于)SELECT...LOCK IN SHARE MODE、SELECT...FOR UPDATE命令以及INSERT、UPDATE和DELETE命令。 出于效率方面的考虑,InnoDB数据表的数据行级锁定实际发生在它们的索引上,而不是数据表自身上。显然,数据行级锁定机制只有在有关的数据表有一个合适的索引可供锁定的时候才能发挥效力。 2. 限制 如果WEHERE子句的查询条件里有不等号(WHERE coloum != ...),MySQL将无法使用索引。 类似地,如果WHERE子句的查询条件里使用了函数(WHERE DAY(column) = ...),MySQL也将无法使用索引。 在JOIN操作中(需要从多个数据表提取数据时),MySQL只有在主键和外键的数 据类型相同时才能使用索引。

数据库索引概论及详解

记住, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中. 使用索引,在一般情况下,将能明显提高查询的性能,但系统为维护索引,也必将增加许多额外的开销。所以,何时应建立索引,查询时是否使用索引,对系统性能的影响将是非常大的。在这里,我想对这个问题谈一下自己的认识。 首先,在下列情况下,不适合建立索引: 1、表的规模不大,在这种情况下,直接查找表的开销比搜索索引 再定位的开销要小。 2、表被频繁更新,在这种情况下,维护索引的开销要大于使用索 引所带来的性能提高。 3、表上已经建立了许多索引。 4、用户的查询方式经常发生变化。 上述这些情况都是比较直观的,但是,即使建立了索引,在具体查 询时,系统也未必会使用该索引。 不管是何种数据库系统,其查询优化过程由两个层次构成:代数优 化(或称基于规则的优化)和物理优化(或称基于代价的优化)(部分 数据库系统可能不含物理优化过程)。 代数优化是使用一组预定义的规则来对查询进行优化,在这种优化 方式下,如果表上建有索引,系统将使用该索引。 物理优化是在代数优化的基础上,根据物理统计信息,来估计各种 执行方案的执行代价,从中选取一种最优(代价最小)的执行方案。在 这种优化方式下,如果表上建有索引,是否使用索引,将取决于查询的 “选中度”(selectivity)。 什么是选中度?举个例子,假设表中有一名为“年龄”的字段,有 一查询需要查出该表中所有“年龄”不超过50岁的记录,如果表中有70% 的记录满足这一条件,则称该查询的选中度为70。 当选中度超过某一预先给定的值P(P的大小取决于系统的具体实现) 时,遍历整个表的开销比搜索索引再定位的开销要小,此时系统将不使 用索引。 通过统计字段的值分布,可以估计查询的选中度,如果它大于P,系 统将不使用索引,直接遍历表。这是一种非常重要的统计信息,它还可 用于估计连接操作结果集的大小。 当然,当查询比较固定时,用户也可以根据自己对应用的理解预先估

数据库索引的作用及实例(精)

1. 1.索引作用 2. 在索引列上,除了上面提到的有序查找之外,数据库利用各种各样的快速定位技术, 能够大大提高查询效率。特别是当数据量非常大, 查询涉及多个表时,使用索引往往能使查询速度加快成千上万倍。 3. 4. 例如,有 3个未索引的表 t1、 t2、 t3,分别只包含列 c1、 c2、 c3,每个表分别含有 1000行数据组成,指为 1~1000的数值,查找对应值相等行的查询如下所示。 5. 6. SELECT c1,c2,c3 FROM t1,t2,t3 WHERE c1=c2 AND c1=c3 7. 8. 此查询结果应该为 1000行, 每行包含 3个相等的值。在无索引的情况下处理此查询, 必须寻找 3个表所有的组合, 以便得出与 WHERE 子句相配的那些行。而可能的组合数目为 1000×1000×1000(十亿,显然查询将会非常慢。 9. 10. 如果对每个表进行索引,就能极大地加速查询进程。利用索引的查询处理如下。 11. 12. (1从表 t1中选择第一行,查看此行所包含的数据。 13. 14. (2使用表 t2上的索引,直接定位 t2中与 t1的值匹配的行。类似,利用表 t3上的索引,直接定位 t3中与来自 t1的值匹配的行。

15. 16. (3 扫描表 t1的下一行并重复前面的过程, 直到遍历 t1中所有的行。 17. 18. 在此情形下,仍然对表 t1执行了一个完全扫描,但能够在表 t2和 t3上进行索引查找直接取出这些表中的行, 比未用索引时要快一百万倍。 19. 20. 利用索引, MySQL 加速了 WHERE 子句满足条件行的搜索,而在多表连接查询时,在执行连接时加快了与其他表中的行匹配的速度。 21. 22.2. 创建索引 23. 在执行 CREATE TABLE语句时可以创建索引, 也可以单独用 CREATE INDEX或 ALTER TABLE来为表增加索引。 24. 25.1. ALTER TABLE 26.ALTER TABLE用来创建普通索引、 UNIQUE 索引或 PRIMARY KEY索引。 27. 28. 29. 30.ALTER TABLE table_name ADD INDEX index_name (column_list 31. 32.ALTER TABLE table_name ADD UNIQUE (column_list 34.ALTER TABLE table_name ADD PRIMARY KEY (column_list 35.

数据库建立索引的原则

数据库建立索引的原则 使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或多列的值进行排序的一种结构,例如employee 表的姓(lname)列。如果要按姓查找特定职员,与必须搜索表中的所有行相比,索引会帮助您更快地获得该信息。 索引是一个单独的、物理的数据库结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。 索引提供指向存储在表的指定列中的数据值的指针,然后根据您指定的排序顺序对这些指针排序。数据库使用索引的方式与您使用书籍中的索引的方式很相似:它搜索索引以找到特定值,然后顺指针找到包含该值的行。 在数据库关系图中,您可以在选定表的“索引/键”属性页中创建、编辑或删除每个索引类型。当保存索引所附加到的表,或保存该表所在的关系图时,索引将保存在数据库中。 建立索引的优点 1.大大加快数据的检索速度; 2.创建唯一性索引,保证数据库表中每一行数据的唯一性; 3.加速表和表之间的连接; 4.在使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间。 索引的缺点 1.索引需要占物理空间。 2.当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度。 根据数据库的功能,可以在数据库设计器中创建三种索引:唯一索引、主键索引和聚集索引。有关数据库所支持的索引功能的详细信息,请参见数据库文档。 提示尽管唯一索引有助于定位信息,但为获得最佳性能结果,建议改用主键或唯一约束。有关这些约束的更多信息,请参见主键约束和唯一约束。 唯一索引

唯一索引是不允许其中任何两行具有相同索引值的索引。 当现有数据中存在重复的键值时,大多数数据库不允许将新创建的唯一索引与表一起保存。数据库还可能防止添加将在表中创建重复键值的新数据。例如,如果在employee 表中职员的姓(lname) 上创建了唯一索引,则任何两个员工都不能同姓。 有关唯一索引的更多信息,请参见创建唯一索引。 主键索引 数据库表经常有一列或列组合,其值唯一标识表中的每一行。该列称为表的主键。 在数据库关系图中为表定义主键将自动创建主键索引,主键索引是唯一索引的特定类型。该索引要求主键中的每个值都唯一。当在查询中使用主键索引时,它还允许对数据的快速访问。有关主键的更多信息,请参见定义主键。 聚集索引 在聚集索引中,表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引。 如果某索引不是聚集索引,则表中行的物理顺序与键值的逻辑顺序不匹配。与非聚集索引相比,聚集索引通常提供更快的数据访问速度。 一、索引 1. 概念:索引是揭示文献内容出处,提供文献查考线索的工具书。 2. 类型:种类很多,从不同的角度可以划分出不同的类型。按文种分,可以分为中文索引的外文索引;按收录范围分,可以分为综合性索引和专题性索引;按收录文献的时间分,可以分为近期索引和回溯性索引;按索引款目的标目分,可以分为题名索引、著者索引、语词索引、主题索引、分类索引等。 3. 功能:揭示文献的内容和指引读者查找信息 4. 作用:索引揭示了一书、一刊的基本情况,如篇目、文句。可以深入、完整、详细、系统地为读者提所需文献的具体线索。 铁律一:天下没有免费的午餐,使用索引是需要付出代价的。 索引的优点有目共睹,但是,却很少有人关心过采用索引所需要付出的成本。若数据库管理员能够对索引所需要付出的代价有一个充分的认识,也就不会那么随意到处建立索引了。

浅谈B-树以及数据库聚集索引、非聚集索引

浅谈B-树以及数据库聚集索引、非聚集索引 对数据库索引的关注从未淡出我的们的讨论,那么数据库索引是什么样的?聚集索引与非聚集索引有什么不同?这段时间,了解数据库索引的一些相关知识,又查阅了一些相关资料,希望本文对大家有一定的帮助,在此借此机会与 大家分享一些数据库聚集索引、数据库非聚集索引概念、实现过程、以及优缺点。有不少存疑的地方,诚心希望各位不吝赐教指正,共同进步。 我们常见的数据库系统,其索引使用的数据结构多是B-Tree或者B+Tree。例如,MySql使用的是B+Tree,Oracle及Sysbase使用的是B-Tree。所以在 最开始,简单地介绍一下B-Tree。 1.B-Tree 在严蔚敏编著的《数据结构》种对B-Tree有如下定义: B-Tree是一种平衡的多路查找树,它在文件系统中很有用,一棵m阶的 B-树,或为空树,或为满足下列特性的m叉树: 1)树中每个结点至多有m个孩子; 2)若根节点不是叶子节点,则至少有两棵子树; 3)除根结点和叶结点外,其它每个结点至少有m/2(上取整)个孩子; 4)所有叶结点在同一层,叶结点不包含任何关键字信息; 5)有K个关键字的非叶结点恰好包含K+1个孩子 另外,对于一个结点,其内部的关键字是从小到大排序的。以下是B-Tree (m=4)的样例:

对于每个结点,主要包含一个关键字数组key[],一个指针数组(指向儿子)son[]。在B-Tree内,查找的流程是:使用顺序查找(数组长度较短时)或折 半查找方法查找key[]数组,若找到关键字k,则返回该结点的地址及K在key[]中的位置;否则,可确定k在某个key[i]和key[i+1]之间,则从son[i]所指的子结点继续查找,直到在某结点中查找成功;或直至找到叶结点且叶结点中的查 找仍不成功时,查找过程失败。 接着,我们使用以下图片演示如何生成B-Tree(m=4,依次插入1~6):从图可见,当我们插入关键字4时,由于原结点已经满了,故进行分裂,基本 按一半的原则进行分裂,然后取出中间的关键字2,升级(这里是成为根结点)。其它的依类推,就是这样一个大概的过程。

数据库索引的作用及实例

1.1.索引作用 2.在索引列上,除了上面提到的有序查找之外,数据库利用各种各样的 快速定位技术,能够大大提高查询效率。特别是当数据量非常大,查询涉及多个表时,使用索引往往能使查询速度加快成千上万倍。 3. 4.例如,有3个未索引的表t1、t2、t3,分别只包含列c1、c2、c3,每 个表分别含有1000行数据组成,指为1~1000的数值,查找对应值相等行的查询如下所示。 5. 6.SELECT c1,c2,c3 FROM t1,t2,t3 WHERE c1=c2 AND c1=c3 7. 8.此查询结果应该为1000行,每行包含3个相等的值。在无索引的情况 下处理此查询,必须寻找3个表所有的组合,以便得出与WHERE子句相配的那些行。而可能的组合数目为1000×1000×1000(十亿),显然查询将会非常慢。 9. 10. 如果对每个表进行索引,就能极大地加速查询进程。利用索引的查询 处理如下。 11. 12.(1)从表t1中选择第一行,查看此行所包含的数据。 13. 14.(2)使用表t2上的索引,直接定位t2中与t1的值匹配的行。类似,利 用表t3上的索引,直接定位t3中与来自t1的值匹配的行。 15. 16.(3)扫描表t1的下一行并重复前面的过程,直到遍历t1中所有的行。 17. 18. 在此情形下,仍然对表t1执行了一个完全扫描,但能够在表t2和t3 上进行索引查找直接取出这些表中的行,比未用索引时要快一百万倍。 19. 20. 利用索引,MySQL加速了WHERE子句满足条件行的搜索,而在多表连 接查询时,在执行连接时加快了与其他表中的行匹配的速度。 21. 22.2. 创建索引 23.在执行CREATE TABLE语句时可以创建索引,也可以单独用CREATE INDEX 或ALTER TABLE来为表增加索引。 24. 25.1.ALTER TABLE 26.ALTER TABLE用来创建普通索引、UNIQUE索引或PRIMARY KEY索引。 27. 28. 29. 30.ALTER TABLE table_name ADD INDEX index_name (column_list) 31. 32.ALTER TABLE table_name ADD UNIQUE (column_list)

数据库索引原理

数据库索引原理 SQL SERVER(下称 SQLS)为例,将数据库管理中难于理解的“索引原理”问题给各位朋友作一个深入浅出的介绍。其他的数据库管理系统如Oracle、Sybase等,朋友们可以融会贯通,举一反三。 一、数据表的基本结构 建立数据库的目的是管理大量数据,而建立索引的目的就是提高数据检索效率,改善数据库工作性能,提高数据访问速度。对于索引,我们要知其然,更要知其所以然,关键在于认识索引的工作原理,才能更好的管理索引。为认识索引工作原理,首先有必要对数据表的基本结构作一次全面的复习。 SQLS当一个新表被创建之时,系统将在磁盘中分配一段以8K为单位的连续空间,当字段的值从内存写入磁盘时,就在这一既定空间随机保存,当一个8K用完的时候,SQLS指针会自动分配一个8K的空间。这里,每个8K空间被称为一个数据页(Page),又名页面或数据页面,并分配从0-7的页号,每个文件的第0页记录引导信息,叫文件头(File header);每8个数据页(64K)的组合形成扩展区(Extent),称为扩展。全部数据页的组合形成堆(Heap)。 SQLS规定行不能跨越数据页,所以,每行记录的最大数据量只能为8K。这就是char和varchar这两种字符串类型容量要限制在8K以内的原因,存储超过8K的数据应使用text类型,实际上,text类型的字段值不能直接录入和保存,它只是存储一个指针,指向由若干8K的文本数据页所组成的扩展区,真正的数据正是放在这些数据页中。页面有空间页面和数据页面之分。 当一个扩展区的8个数据页中既包含了空间页面又包括了数据或索引页面时,称为混合扩展(Mixed Extent),每张表都以混合扩展开始;反之,称为一致扩展(Uniform Extent),专门保存数据及索引信息。 表被创建之时,SQLS在混合扩展中为其分配至少一个数据页面,随着数据量的增长,SQLS可即时在混合扩展中分配出7个页面,当数据超过8个页面时,则从一致扩展中分配数据页面。 空间页面专门负责数据空间的分配和管理,包括:PFS页面(Page free space):记录一个页面是否已分配、位于混合扩展还是一致扩展以及页面上还有多少可用空间等信息;GAM页面(Global allocation map)和SGAM页面(Secodary global allocation map):用来记录空闲的扩展或含有空闲页面的混合扩展的位置。SQLS综合利用这三种类型的页面文件在必要时为数据表创建新空间; 数据页或索引页则专门保存数据及索引信息,SQLS使用4种类型的数据页面来管理表或索引:它们是IAM页、数据页、文本/图像页和索引页。 在WINDOWS中,我们对文件执行的每一步操作,在磁盘上的物理位置只有系统(system)才知道;SQL SERVER沿袭了这种工作方式,在插入数据的过程中,不但每个字段值在数据页面中的保存位置是随机的,而且每个数据页面在“堆”中的排列位置也只有系统(system)才知道。 这是为什么呢?众所周知,OS之所以能管理DISK,是因为在系统启动时首先加载了文件分配表:FAT(File Allocation Table),正是由它管理文件系统并记录对文件的一切操作,系统才得以正常运行;同理,作为管理系统级的SQL SERVER,也有这样一张类似FAT的表存在,它就是索引分布映像页:IAM(Index Allocation Map)。 IAM的存在,使SQLS对数据表的物理管理有了可能。

正确合理使用数据库中的索引

正确合理使用数据库中的索引 索引是数据库中重要的数据结构,它的根本目的就是为了提高查询效率。现在大多数的数据库产品都采用IBM最先提出的ISAM索引结构。 索引的使用要恰到好处,其使用原则如下: ●在经常进行连接,但是没有指定为外键的列上建立索引,而不经常连接的字段则由优化器自动生成索引。 ●在频繁进行排序或分组(即进行group by或order by操作)的列上建立索引。 ●在条件表达式中经常用到的不同值较多的列上建立检索,在不同值少的列上不要建立索引。比如在雇员表的“性别”列上只有“男”与“女”两个不同值,因此就无必要建立索引。如果建立索引不但不会提高查询效率,反而会严重降低更新速度。 ●如果待排序的列有多个,可以在这些列上建立复合索引(compound index)。 ●使用系统工具。如Informix数据库有一个tbcheck工具,可以在可疑的索引上进行检查。在一些数据库服务器上,索引可能失效或者因为频繁操作而使得读取效率降低,如果

一个使用索引的查询不明不白地慢下来,可以试着用tbcheck工具检查索引的完整性,必要时进行修复。另外,当数据库表更新大量数据后,删除并重建索引可以提高查询速度。 (1)在下面两条select语句中: select * from table1 where field1<=10000 and field1>=0; select * from table1 where field1>=0 and field1<=10000; 如果数据表中的数据field1都>=0,则第一条select语句要比第二条select语句效率高的多,因为第二条select语句的第一个条件耗费了大量的系统资源。 第一个原则:在where子句中应把最具限制性的条件放在最前面。 (2)在下面的select语句中: select * from tab where a=… and b=… and c=…; 若有索引index(a,b,c),则where子句中字段的顺序应和索引中字段顺序一致。 第二个原则:where子句中字段的顺序应和索引中字段顺序一致。

关于数据库索引的探讨

关于数据库索引的探讨 作者:杨军莉 来源:《电子世界》2013年第06期 【摘要】现在企业之间数据交流的各种数据量的急剧增长,且要求数据处理及时,这对数据库的处理能力方面提出了更高的要求。数据库索引可以有效地提高数据的查询处理效率,如何合理地设置索引并优化索引,则要考虑到方方面面的要求,本文通过对数据库的索引技术进行了研究,论述如何合理设置索引,以期给数据库设计者和系统开发者提供参考。 【关键词】数据库索引;聚集索引;非聚集索引;查询优化 由于计算机网络技术的迅猛发展,企业间数据交流的各种数据量的急剧增长,不但要求处理的结果要准确,而且也要求处理速度及时,这对数据库的处理能力能力方面提出了更高的要求,如何设置有效的数据库索引达到数据库优化是本文要讨论的重点。 应用索引的过程其实类似于查新华字典,比照数据库的概念,新华字典里的拼音检字法和部首检字法就是新华字典的两种不同的索引,而新华字典的正文则相当于表同时创建索引并不会改变表中的数据的物理位置,它只是创建了一个新的数据结构指向数据表。比起逐一查阅字典正文查找某一个具体的汉字,显然不管使用哪种检字法都可以很快地在字典正文中找到这个汉字,这就是使用索引的给我们带来的好处。如何准确高效地从海量的信息中查询到想要的数据,已成为数据库设计人员的首要任务。 所以我们可以从逻辑上简单地认为,索引是一个单独的、物理的数据结构,它主要包含两列内容,第一列是从表或视图中的列或列的组合所生成的键值的集合,且根据键值以升序或降序排列。这一列类似于新华字典的音序,它以字母升序排列,即A在最前,而Z在最后。索引的另外一列则是指向表中这些值的数据页的逻辑指针的集合。这一列则类似于对应音序的页码。索引依赖于表,作为表的组成部分,由数据库系统自动维护,是对数据库表中一个或多个列的值进行排序的数据结构,不同的索引对应不同的排序方法。一个表的存储是由两部分组成的,一部分是用来存放数据的数据页面,另一部分是用来存放索引的索引索引页面,通常索引页面比数据页面小得多。 假设表中的数据在磁盘上存储是有序的,那么当在数据库在进行插入数据、删除数据和更新数据时,则一定会导致数据的顺序会发生变化,为了保证数据的连续性和有序性,就需要重新移动数据,改变它们的物理位置,而种移动将会导致增大磁盘的I/O操作,使得整个数据库运行非常缓慢;使用索引的主要目的是使数据逻辑有序。为了实现数据逻辑有序,实际上索引的物理结构是一个双向链表,使用双向链表来保证数据的逻辑顺序,如果要对表中的一个已有结点进行更新则仅需修改该节点的前驱和后继,而且无需修改该节点的物理位置;如果要在两个节点中插入一个新的节点只需修改节点的前驱和后继,而且无需修改新节点的物理位置;如

数据库索引 index 介绍

数据库索引index 介绍 2010-05-04 对数据库索引的关注从未淡出我的们的讨论,那么数据库索引是什么样的?聚集索引与非聚集索引有什么不同?希望本文对各位同仁有一定的帮助。有不少存疑的地方,诚心希望各位不吝赐教指正,共同进步。 B-Tree 我们常见的数据库系统,其索引使用的数据结构多是B-Tree或者B+Tree。例如,MsSql使用的是B+Tree,Oracle及Sysbase使用的是B-Tree。所以在最开始,简单地介绍一下B-Tree。 B-Tree不同于Binary Tree(二叉树,最多有两个子树),一棵M阶的B-Tree满足以下条件:另外,对于一个结点,其内部的关键字是从小到大排序的。以下是B-Tree(M=4)的样例: 对于每个结点,主要包含一个关键字数组Key[],一个指针数组(指向儿子)Son[]。在B-Tree内,查找的流程是:使用顺序查找(数组长度较短时)或折半查找方法查找Key[]数组,若找到关键字K,则返回该结点的地址及K在Key[]中的位置;否则,可确定K在某个Key[i]和Key[i+1]之间,则从Son[i]

所指的子结点继续查找,直到在某结点中查找成功;或直至找到叶结点且叶结点中的查找仍不成功时,查 找过程失败。 接着,我们使用以下图片演示如何生成B-Tree(M=4,依次插入1~6): 从图可见,当我们插入关键字4时,由于原结点已经满了,故进行分裂,基本按一半的原则进行分裂,然后取出中间的关键字2,升级(这里是成为根结点)。其它的依类推,就是这样一个大概的过程。 数据库索引 在数据库中,索引的含义与日常意义上的“索引”一词并无多大区别(想想小时候查字典),它是用于提高数据库表数据访问速度的数据库对象。 数据页,而不是遍历所有数据页。 。 当然,众所周知,虽然索引可以提高查询速度,但是它们也会导致数据库系统更新数据的性能下降,因为大部分数据更新需要同时更新索引。 一条索引记录中包含的基本信息包括:键值(即你定义索引时指定的所有字段的值)+逻辑指针(指向数据页或者另一索引页)。

数据库索引的原理到底是什么

数据库索引的原理到底是什么? 中小企业MIS系统的管理基本上由两大部份组成,一是前台的可视化操作,二是后台的数据库管理。网管对前台的管理和维护工作包括保障网络链路通畅、处理MIS终端的突发事件以及对操作员的管理、培训等,这是网管们日常做得最多、最辛苦的功课;然而MIS系统架构中同等重要的针对数据库的管理、维护和优化工作,现实中似乎并没有得到网管朋友的足够重视,看起来这都是程序员的事,事实上,一个网管如果能在MIS设计期间就数据表的规范化、表索引优化、容量设计、事务处理等诸多方面与程序员进行卓有成效的沟通和协作,那么日常的前台管理工作将会变得大为轻松,因为在某种意义上,数据库管理系统就相当于操作系统,在系统中占有同样重要的位置。 这正是SQL SERVER等数据库管理系统和dBASEX、ACCESS等数据库文件系统的本质区别,所以,对数据库管理系统操作能力的强弱在某种程度上也折射出了网管的水平——个人认为,称得上优秀的Admin,至少应该是一个称职的DBA(数据库管理员)。 下面以SQL SERVER(下称SQLS)为例,将数据库管理中难于理解的“索引原理”问题给各位朋友作一个深入浅出的介绍。其他的数据库管理系统如Oracle、Sybase等,朋友们可以融会贯通,举一反三。 一、数据表的基本结构 建立数据库的目的是管理大量数据,而建立索引的目的就是提高数据检索效率,改善数据库工作性能,提高数据访问速度。对于索引,我们要知其然,更要知其所以然,关键在于认识索引的工作原理,才能更好的管理索引。 为认识索引工作原理,首先有必要对数据表的基本结构作一次全面的复习。 SQLS当一个新表被创建之时,系统将在磁盘中分配一段以8K为单位的连续空间,当字段的值从内存写入磁盘时,就在这一既定空间随机保存,当一个8K用完的时候,SQLS指针会自动分配一个8K的空间。这里,每个8K空间被称为一个数据页(Page),又名页面或数据页面,并分配从0-7的页号,每个文件的第0页记录引导信息,叫文件头(File header);每8个数据页(64K)的组合形成扩展区(Extent),称为扩展。全部数据页的组合形成堆(Heap)。 SQLS规定行不能跨越数据页,所以,每行记录的最大数据量只能为8K。这就是char和varchar这两种字符串类型容量要限制在8K以内的原因,存储超过8K的数据应使用text 类型,实际上,text类型的字段值不能直接录入和保存,它只是存储一个指针,指向由若干8K的文本数据页所组成的扩展区,真正的数据正是放在这些数据页中。 页面有空间页面和数据页面之分。 当一个扩展区的8个数据页中既包含了空间页面又包括了数据或索引页面时,称为混合扩展(Mixed Extent),每张表都以混合扩展开始;反之,称为一致扩展(Uniform Extent),专门保存数据及索引信息。

数据库建立索引的必要性

数据库效率优化----建立合适的索引 我们都知道使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或多列的值进行排序的一种结构,例如employee 表的姓(lname)列。如果要按姓查找特定职员,与必须搜索表中的所有行相比,索引会帮助您更快地获得该信息。 索引提供指向存储在表的指定列中的数据值的指针,然后根据您指定的排序顺序对这些指针排序。数据库使用索引的方式与您使用书籍中的索引的方式很相似:它搜索索引以找到特定值,然后顺指针找到包含该值的行。索引占用磁盘空间,并且降低添加、删除和更新行的速度。在多数情况下,索引用于数据检索的速度优势大大超过它的。 首先讲述下为什么索引会增加速度,数据库在执行一条Sql语句的时候,默认的方式是根据搜索条件进行全表扫描,遇到匹配条件的就加入搜索结果集合。如果我们对某一字段增加索引,查询时就会先去索引列表中一次定位到特定值的行数,大大减少遍历匹配的行数,所以能明显增加查询的速度。那么在任何时候都应该加索引么?这里有几个反例:1、如果每次都需要取到所有表记录,无论如何都必须进行全表扫描了,那么是否加索引也没有意义了。2、对非唯一的字段,例如“性别”这种大量重复值的字段,增加索引也没有什么意义。3、对于记录比较少的表,增加索引不会带来速度的优化反而浪费了存储空间,因为索引是需要存储空间的,而且有个致命缺点是对于update/insert/delete的每次执行,字段的索引都必须重新计算更新。 那么在什么时候适合加上索引呢?我们看一个mysql手册中举的例子,这里有一条sql 语句: SELECT https://www.doczj.com/doc/3a17388437.html,panyID, https://www.doczj.com/doc/3a17388437.html,panyName FROM Companies c, User u WHERE https://www.doczj.com/doc/3a17388437.html,panyID = u.fk_companyID AND c.numEmployees >= 0 AND https://www.doczj.com/doc/3a17388437.html,panyName LIKE '%i%' AND u.groupID IN (SELECT g.groupID FROM Groups g WHERE g.groupLabel = 'Executive') 这条语句涉及3个表的联接,并且包括了许多搜索条件比如大小比较,Like匹配等。在没有索引的情况下Mysql需要执行的扫描行数是77721876行。而我们通过在companyID 和groupLabel两个字段上加上索引之后,扫描的行数只需要134行。在Mysql中可以通过Explain Select来查看扫描次数。可以看出来在这种联表和复杂搜索条件的情况下,索引带来的性能提升远比它所占据的磁盘空间要重要得多。 那么索引是如何实现的呢?大多数DB厂商实现索引都是基于一种数据结构——B树。因为B树的特点就是适合在磁盘等直接存储设备上组织动态查找表。B树的定义是这样的:一棵m(m>=3)阶的B树是满足下列条件的m叉树: 1、每个结点包括如下作用域(j, p0, k1, p1, k2, p2, ... ki, pi) 其中j是关键字个数,p是孩子指针 2、所有叶子结点在同一层上,层数等于树高h 3、每个非根结点包含的关键字个数满足[m/2-1]<=j<=m-1

数据库索引的作用和优点缺点

为什么要创建索引呢?这是因为,创建索引可以大大提高系统的性能。 第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。 第二,可以大大加快数据的检索速度,这也是创建索引的最主要的原因。 第三,可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。 第四,在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。 第五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。 也许会有人要问:增加索引有如此多的优点,为什么不对表中的每一个列创建一个索引呢?这种想法固然有其合理性,然而也有其片面性。虽然,索引有许多优点,但是,为表中的每一个列都增加索引,是非常不明智的。这是因为,增加索引也有许多不利的一个方面。 第一,创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。 第二,索引需要占物理空间,除了数据表占数据空间之外,每一

个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。 第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。 索引是建立在数据库表中的某些列的上面。因此,在创建索引的时候,应该仔细考虑在哪些列上可以创建索引,在哪些列上不能创建索引。一般来说,应该在这些列上创建索引,例如: 在经常需要搜索的列上,可以加快搜索的速度; 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构; 在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度; 在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的; 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间; 在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。

相关主题
文本预览
相关文档 最新文档