http://hi.baidu.com/hlwang/blog/item/d8ccb67750ba6c18b051b98a.html
http://hi.baidu.com/hlwang/blog/item/d8ccb67750ba6c18b051b98a.html
SQL索引
一、索引的概念
索引就是加快检索表中数据的方法。数据库的索引类似于书籍的索引。在书籍中,索引允许用户不必翻阅完整个书就能迅速地找到所需要的信息。在数据库中,索引也允许数据库程序迅速地找到表中的数据,而不必扫描整个数据库。
二、索引的特点
1.索引可以加快数据库的检索速度
2.索引降低了数据库插入、修改、删除等维护任务的速度
3.索引创建在表上,不能创建在视图上
4.索引既可以直接创建,也可以间接创建
5.可以在优化隐藏中,使用索引
6.使用查询处理器执行SQL语句,在一个表上,一次只能使用一个索引
7.其他
三、索引的优点
1.创建唯一性索引,保证数据库表中每一行数据的唯一性
2.大大加快数据的检索速度,这也是创建索引的最主要的原因
3.加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
4.在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
5.通过使用索引,可以在查询的过程中使用优化隐藏器,提高系统的性能。
四、索引的缺点
1.创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加
2.索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大
3.当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度
五、索引分类
1.直接创建索引和间接创建索引
直接创建索引: CREATE INDEX mycolumn_index ON mytable (myclumn)
间接创建索引:定义主键约束或者唯一性键约束,可以间接创建索引
2.普通索引和唯一性索引
普通索引:CREATE INDEX mycolumn_index ON mytable (myclumn)
唯一性索引:保证在索引列中的全部数据是唯一的,对聚簇索引和非聚簇索引都可以使用
CREATE UNIQUE COUSTERED INDEX myclumn_cindex ON mytable(mycolumn)
3.单个索引和复合索引
单个索引:即非复合索引
复合索引:又叫组合索引,在索引建立语句中同时包含多个字段名,最多16个字段
CREATE INDEX name_index ON username(firstname,lastname)
4.聚簇索引和非聚簇索引(聚集索引,群集索引)
聚簇索引:物理索引,与基表的物理顺序相同,数据值的顺序总是按照顺序排列
CREATE CLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn) WITH
ALLOW_DUP_ROW(允许有重复记录的聚簇索引)
非聚簇索引:CREATE UNCLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn)
六、索引的使用
1.当字段数据更新频率较低,查询使用频率较高并且存在大量重复值是建议使用聚簇索引
2.经常同时存取多列,且每列都含有重复值可考虑建立组合索引
3.复合索引的前导列一定好控制好,否则无法起到索引的效果。如果查询时前导列不在查询条件中则该复合索引不会被使用。前导列一定是使用最频繁的列
4.多表操作在被实际执行前,查询优化器会根据连接条件,列出几组可能的连接方案并从中找出系统开销最小的最佳方案。连接条件要充份考虑带有索引的表、行数多的表;内外表的选择可由公式:外层表中的匹配行数*内层表中每一次查找的次数确定,乘积最小为最佳方案
5.where子句中对列的任何操作结果都是在sql运行时逐列计算得到的,因此它不得不进行表搜索,而没有使用该列上面的索引;如果这些结果在查询编译时就能得到,那么就可以被sql优化器优化,使用索引,避免表搜索(例:select * from record where substring(card_no,1,4)=’5378’
&& select * from record where card_no like ’5378%’)任何对列的操作都将导致表扫描,它包括数据库函数、计算表达式等等,查询时要尽可能将操作移至等号右边
6.where条件中的’in’在逻辑上相当于’or’,所以语法分析器会将in ('0','1')转化为column='0' or column='1'来执行。我们期望它会根据每个or子句分别查找,再将结果相加,这样可以利用column上的索引;但实际上它却采用了"or策略 ",即先取出满足每个or子句的行,存入临时数据库的工作表中,再建立唯一索引以去掉重复行,最后从这个临时表中计算结果。因此,实际过程没有利用 column上索引,并且完成时间还要受tempdb数据库性能的影响。in、or子句常会使用工作表,使索引失效;如果不产生大量重复值,可以考虑把子句拆开;拆开的子句中应该包含索引
7.要善于使用存储过程,它使sql变得更加灵活和高效
在创建聚集索引之前,应先了解您的数据是如何被访问的。可考虑将聚集索引用于:
包含大量非重复值的列。
使用下列运算符返回一个范围值的查询:BETWEEN、>、>=、< 和 <=。
被连续访问的列。
返回大型结果集的查询。
经常被使用联接或 GROUP BY 子句的查询访问的列;一般来说,这些是外键列。对 ORDER BY 或 GROUP BY 子句中指定的列进行索引,可以使 SQL Server 不必对数据进行排序,因为这些行已经排序。这样可以提高查询性能。
OLTP 类型的应用程序,这些程序要求进行非常快速的单行查找(一般通过主键)。应在主键上创建聚集索引。
聚集索引不适用于:
频繁更改的列
这将导致整行移动(因为 SQL Server 必须按物理顺序保留行中的数据值)。这一点要特别注意,因为在大数据量事务处理系统中数据是易失的。
宽键
来自聚集索引的键值由所有非聚集索引作为查找键使用,因此存储在每个非聚集索引的叶条目内。
普通索引可按需创建,但不是索引越多就越好!!
搜到了这么一段,试问说得有道理不:)
如果column保存了高度相关的数据,并且常常被顺序访问时,最好使用clustered索引,这是因为如果使用clustered索引,SQL Server会在物理上按升序(默认)或者降序重排数据列,这样就可以迅速的找到被查询的数据。同样,在搜寻控制在一定范围内的情况下,对这些 column也最好使用clustered索引。这是因为由于物理上重排数据,每个表格上只有一个clustered索引。 与上面情况相反,如果columns包含的数据相关性较差,你可以使用nonculstered索引。你可以在一个表格中使用高达249个nonclustered索引——尽管我想象不出实际应用场合会用的上这么多索引。
当表格使用主关键字(primary keys),默认情况下SQL Server会自动对包含该关键字的column(s)建立一个独有的cluster索引。很显然,对这些column(s)建立独有索引意味着主关键字的唯一性。当建立外关键字(foreign key)关系时,如果你打算频繁使用它,那么在外关键字cloumn上建立nonclustered索引不失为一个好的方法。如果表格有clustered索引,那么它用一个链表来维护数据页之间的关系。相反,如果表格没有clustered索引,SQL Server将在一个堆栈中保存数据页。
提高查询速度的几点经验- SQL SERVER 2000/20052007-12-07 13:24提高查询速度的几点经验:
1、首先深刻理解需求,灵活合理设计库表结构,这非一日之功今日暂不作讨论重点。
2、库表中是否有blob与text型,这两种数据类型通过页链,存储在不同的数据页上。
查询速度慢是很正常的事情。对于这两种类型的特殊部分还有很多,例如在不能有相同的记录,更谈不上查询的速度问题。
3、库表索引的建立与使用是提高查询速度最重要的手段,正常情况下是程序在运行过程中自动使用索引,但是根据其特殊需要也可以在程序中指定索引。
select /+ using index 索引名 +/ into:变量 from 表名
索引的建立与使用当然也有很多规则,希望大家不要建垃圾索引。与索引关系很大的就是临时库了,因为索引的原理之一就是重新排序,数据库系统默认的临时库(一般为2M)太少,会出错误提示的。另一个是在标中使用索引是会出问题的。
说的非常好,但我想补充一些,我记得SQL优化索引的规则中,还有一条是:多表关联查询时,记录少的表放在最前面(包括放在=左边)。
不知说的对不对,请大家指教。。。
4、数据库使用内存的分配,高速缓存的使用也是很重要的,我使用的数据库为Sybase,配置方法为sp_configure
5、SQL语句的写法不同,查询的速度影响也很大。(第三种查询方式最快,但还不是最快的。)
表titles中的记录多于表titleauthor
SELECT title_id, title FROM titles, titleauthor
WHERE title.title_id = titleauthor.title_id
AND titleauthor.title_id = 'T81002'
SELECT title_id, title FROM titles, titleauthor
WHERE title.title_id = titleauthor.title_id
AND title.title_id = 'T81002'
SELECT title_id, title FROM titles, titleauthor
WHERE title.title_id = titleauthor.title_id
AND title.title_id = 'T81002'
AND titleauthor.title_id = 'T81002'
6、灵活使用数据共享,会产生意想不到的效果。
80万条数据,20秒内查询搞定是很正常的事情。
聚簇索引是一种对磁盘上实际数据重新组织以按指定的一个或多个列的值排序。由于聚簇索引的索引页面指针指向数据页面,所以使用聚簇索引查找数据几乎总是比使用非聚簇索引快。每张表只能建一个聚簇索引,并且建聚簇索引需要至少相当该表120%的附加空间,以存放该表的副本和索引中间页,所以要将临时库扩容。
在聚簇索引下,数据在物理上按顺序排在数据页上,重复值也排在一起,因而在那些包含范围检查(between、、>=)或使用group
by或order
by的查询时,一旦找到具有范围中第一个键值的行,具有后续索引值的行保证物理上毗连在一起而不必进一步搜索,避免了大范围扫描,可以大大提高查询速度。
在一个频繁发生插入操作的表上建立聚簇索引时,不要建在具有单调上升值的列(如IDENTITY)上,否则会经常引起封锁冲突。
在聚簇索引中不要包含经常修改的列,因为码值修改后,数据行必须移动到新的位置。
只有两个或三个值的列,如男性和女性(是或否),从不会从索引中得到好处。
鉴于索引加快了查询速度,但减慢了数据更新速度的特点。可通过在一个段上建表,而在另一个段上建其非聚簇索引,而这两段分别在单独的物理设备上来改善操作性能。
因为大量的索引在插入、修改和删除操作时比没有索引花费更多的系统时间
选择聚簇索引应基于where子句和连接操作的类型。聚簇索引的侯选列是:
● 主键列,该列在where子句中使用并且插入是随机的。
● 按范围存取的列,如pri_order > 100 and pri_order < 200 。
● 在group by或order by中使用的列。
● 不经常修改的列。
● 在连接操作中使用的列。
游标是中的使用select /+using index
索引名+/一定要万分注意,经过索引后的库表已经重新排序,数据的顺序在程序执行过程中确实改变了,是否符合自已的编程需要。
要提高查询的效率,则where中的条件要尽可能的写全。如一条查询语句中用到了两个表,则除了将两个表的关联处理好以外,还要将两个表的关联字段均和变量联系起来。
如:
select * from dec,mst where dec.id = mst.id and dec.id =
:ls_id and mst.id = :ls_id;
而不是 select * from dec,mst where dec.id = mst.id and dec.id =
:ls_id;
或
select * from dec,mst where dec.id = mst.id and mst.id =
:ls_id;
1、SQL
Server缺省情况下建立的索引是非聚簇索引,由于非聚簇索引不重新组织表中的数据,而是对每一行存储索引列值并用一个指针指向数据所在的页面。换句话说非聚簇索引具有在索引结构和数据本身之间的一个额外级。一个表如果没有聚簇索引时,可有250个非聚簇索引。每个非聚簇索引提供访问数据的不同排序顺序。在建立非聚簇索引时,要权衡索引对查询速度的加快与降低修改速度之间的利弊。
2、对更新频繁的表来说,表上的非聚簇索引比聚簇索引和根本没有索引需要更多的额外开销。对移到新页的每一行而言,指向该数据的每个非聚簇索引的页级行也必须更新,有时可能还需要索引页的分理。
缺省情况下,tempdb数据库是放置在master设备上,容量为2M,而临时数据库是活动最为平凡的数据库常常被用来排序、创建临时表、重格式化等操作,所以tempdb的优化应该受到特别的关注:
第一步:调整临时库的位置
1、tempdb数据库缺省放在master设备上,将临时数据库发在分离的设备上是更可取的。
2、打开tempdb数据库,从段上删除master设备 。
第二步:将临时数据库与高速缓冲进行绑定。
由于临时表的创建、使用,临时数据库会频繁地使用数据缓存,所以应为临时数据库创建高速缓存,从而可以使其常驻内存并有助于分散I/O:
1、创建命名高速缓存
sp_cacheconfig “tempdb_cache”,”10m”,”mixed”
2、重新启动server
3、捆绑临时数据库到tempdb_cache高速缓存
sp_bindcache “tempdb_cache”, tempdb
4、若有大的I/O,配置内存池
第三步:优化临时表
大多数临时表的使用是简单的,很少需要优化。但需要对临时表进行复杂的访问则
应通过使用多个过程或批处理来把表的创建和索引分开。以下技术可以改善临时表的优化
1、在临时表上创建索引
2、把对临时表的复杂的使用分散到多个批处理或过程中,以便为优化器提供信息(举例说明,就是有一个操作复杂的存储过程,将这个复杂的存储过程分解成若干个简单的存储过程,然后执行操作。)