`
zyj479236238
  • 浏览: 461 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

索引整理

阅读更多
首先提1个问题:
1, SELECT A,B,C,D FROM TABLE WHERE A=1;
有一个问题一直没搞懂,希望高手指点:被查询的列是否利用索引?
我现在的理解是:不利用,只有当查询条件中有一个组合索引且被查列被包含在组合索引中形成了索引覆盖时被查询的列才利用到索引。

简述
    Sql Server中的数据是按页(4KB)存放的,索引就是为了方便寻找数据而编排的内部方法,它会被固定的放在索引页中(索引页也是一个数据页),通过索引我们大大减少查找数据的时间

索引的优缺点
优点
1, 加快访问速度。
2, 加强行的唯一性
缺点
1, 因为索引需要存储在索引页中,所以带索引的表会花费更多的数据库空间。
2, 因为在操作数据库时(修改列属性,修改表属性,修改数据库属性,复制表等)会对索引进行更新,故在此时带索引的表会花费更多的时间。
注:很多地方说需要对一个表的属性进行修改或者复制某一个表等操作会花费很多的时间,那么这个时候就可以考虑先删除该表的索引然后操作完成后重新创建
3, 2的一个衍生,就是在对表进行新增修改删除等操作时,因为也必须对索引表进行增删改所以速度会慢一点。

    索引类型
1,唯一索引(Unique)(Sql Server, MySql):唯一索引不允许两行具有相同的值
2,主键索引(primary) (Sql Server, MySql):主键索引是唯一索引的一个特殊表现形式,当定义一个字段为主键时会自动为其加上主键索引,主键索引要求字段中每一个值都是唯一的且不能为空。
3,聚集索引(Clustered)(Sql Server):表中各行的物理顺序与键值的逻辑(索引)顺序相同,每个表只能有一个。
4,非聚焦索引(Non-Clustered)(Sql Server):非聚焦索引指定表的逻辑顺序。数据存储在一个位置,索引存储在另一个位置,索引中包含指向存储位置的指针。可以有多个(最多249个)
5,普通索引(Normal)(MySql):分为单例索引和组合索引
6,全文索引(Full Text)(MySql):全文索引用于容量较大的字符串的索引。


详解:
唯一索引(Unique)
唯一索引很简单,就是必须是唯一的,被列为唯一索引的值会被强制唯一化。在创建主键索引的时候会被强制创建唯一索引。

注:在创建唯一约束时会自动创建唯一索引。所以为了达到更好的性能,建议使用主键约束或者唯一约束 (关于主键约束和唯一约束,在约束文件中寻找)
主键索引(primary)
主键索引是特殊的唯一索引,在查询时利用主键索引时会加快访问数据的速度。
聚焦索引(Clustered)
聚焦索引是指 表中数据的物理行与键值逻辑(索引)顺序相同。即如果物理数据行(字段Field)内容为 a,b,c,d,e,f,g,h,I 而索引为1,2,3,4,5,6,7,8,9。那么索引1所指向的数据就是a,索引2指向的数据就是b。。。以此类推,可以退出  h就是在c的后面,d就是在a的前面。
每一个表只允许存在一个聚焦索引。聚焦索引比非聚焦索引的搜索速度更快。

注:由于聚焦索引时物理行与键值逻辑相对应的,所以在使用>= , <=,>,<,between等函数时会比非聚焦索引快很多。因为数据库只需要找到这个字段的某一个值然后就根据这个值往后或往前进行搜索即可,如果用非聚焦索引就必须对全表进行扫描。
非聚焦索引(Non-Clustered)
非聚焦索引的物理行与键值逻辑(索引)的顺序是不相对的。
普通索引(Normal)
普通的索引。MySql中允许两种:1,单例索引。2,组合索引。当使用多个列进行索引的时候,建议使用组合索引。
组合索引是将几个字段组合成一个索引,但是有先后顺序的,通常第一个字段被称为:前导列。如果在一个SELECT语句中,前导列没有被用到,而其他索引对象被用到了,这个组合索引也是不会被利用的。
全文索引(Full Text)
全文索引,使用于长篇的Text。比如一些表中Remark。(当然如果Remark只有1,2行也就没必要了,直接用普通的就OK了)
索引的触发
创建索引的基本原则
需要创建索引
1, 该列用于频繁的搜索
2, 该列用于对数据的排序
不要创建索引
1, 列中值得多样性较低(即用DISTINCT以后发现只有几个不一样的值)
2, 表内容较小。(因为对于较小表进行索引搜索比 搜查整张表更不划算)
索引场景(SQL SERVER)
注:一般是按照索引才进行Sql语句的编写,但是这里为了让自己更好的理解索引的作用特地用Sql来创建索引。

表Record有62W条数据
SQL1:select count(*) from record where date > '19991201' and date < '19991214'and amount > 2000
SQL2:select date,sum(amount) from record group by date
SQL3:select count(*) from record where date > '19990901' and place in ('BJ','SH')

索引策略:
1, 在date上加上非聚焦索引;
SQL1:25秒
SQL2:55秒
SQL3:27秒
讲解:大量的date数据(肯定有大量重复当然也可以没有---操,屁话),由于非聚焦索引的物理列和键值逻辑不是相对应的,所以必须进行全表扫描,效率当然慢。

2, 在date上加上聚焦索引;
SQL1:14秒
SQL2:28秒
SQL3:14秒
讲解:相对于策略一,在date上加上了聚焦索引,让物理行与键值逻辑进行了一一对应这样明显的3条语句就变快了。因为系统不需要进行全表扫描。
注:小弟不懂,难道在增加聚焦索引的时候就保证了date是按照一个逻辑(大小)顺序的吗?如果不是按照一个逻辑(大小)顺序那么即使是聚焦索引页必须要扫描全表的啊。请大侠解答

3, 在place,date,amount加上组合索引;
SQL1:26秒
SQL2:27秒
SQL3:1秒
讲解:组合索引的特点就是有一个前导列(这里是place),SQL1和SQL2没有用到place这个前导列,所以无法使用这个组合索引比较慢,SQL3用到了place和date大大加快了搜索速度。

4, 在date,place,amount加上组合索引
SQL1:<1秒
SQL2:<11秒
SQL3:<1秒
讲解:和策略三相比,将date作为了前导列充分利用了组合索引使得三条SQL语句都充分利用索引,搜索速度大大加快了。
注:原文中说,SQL1和SQL3形成了索引覆盖。因为使性能达到了最优;但是按照索引覆盖的定义是SELECT的语句中数据列只要从索引中就可以获取就算索引覆盖,但是SQL1和SQL3中都用了COUNT(*)这样也能默认为索引覆盖吗?或者说 被SELECT的字段不能利用索引?

总结:
1, 在有大量重复值且经常用到范围查询时(>=,<=,>,<,between)时最好建立聚焦索引。
2, 经常存取多列,而且这些列都含有重复数据请使用组合索引
3, 组合索引的前导列必须是查询最频繁的列,且尽量做到关键查询的索引覆盖
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics