索引
索引提供指针以指向存储在表中指定的数据,就好比一本字典中的目录,无需翻阅整本字典,利用目录就可以快速的定位查找到所需信息。使用索引可以大大提高数据库查询的速度。
索引的分类
sqlserver中有多种索引类型。
按存储结构区分:“聚集索引”,“非聚集索引”。
按数据唯一性区分:“唯一索引”,“非唯一索引”。
按键列个数区分:“单一索引”,“复合索引”。
- sqlserver默认情况下建立的索引是非聚集索引
类型 | 描述 |
---|---|
聚集索引 | 将表中的数据在物理上按序重新排列,因为排序只有一种排法,所以一个表只能建立一个聚集索引。 这就好比所有的汉字,我们按照拼音顺序只能生产一种字典,我们按照拼音顺序排列成字典。然后当我们想查找 张 字时,自然而然会翻到字典的后百页,然后再根据字母顺序查找。如果找完了z 字母开头的汉字没有找到张 ,则字典不存在张 |
非聚集索引 | 非聚集索引不重新组织表中的数据,具有独立于数据行的结构,对每个键值都创建一个指向该键值的指针。 好比我们对所有汉字不进行排序,而是根据部首偏旁创建一个指向当前汉字的指针。当遇到一个我们不认识的汉字 张 ,我们不知道它的发音,所以我们选择使用张 的偏旁部首``弓 来查找,如下图所示可以找到张 610 所以根据这个610 定位到张 所在的位置。可以看到 张 上面弟 94 下面 弧 188 ,并没有排过序。 |
唯一索引 | 不允许有相同数据列的索引 |
非唯一索引 | 普通索引 |
单一索引 | 针对一列的索引 |
复合索引 | 也叫组合索引,针对多列的索引 |
偏旁部首表
聚集索引
在每个数据页的末尾,都有一个“行偏移量”的数组,这个数组记录了每一个数据行的开头在页面中的起始位置,即每行数据开头应该从页头偏移多少个字节。
聚合索引按照物理顺序重排并不会重排数据行的顺序,而是修改行偏移量的顺序。
如先插入三条数据1,2,10 对应的偏移分别为100,200,300。
这时候插入一条数据8(偏移位置为150),大于2且小于10。数据库并不会把8移动到2,10中间。而是修改行偏移量数组,将8的行偏移量移动2和10的中间。
复合索引查询
- 使用复合索引在查询的时候,最好将条件顺序按照索引的顺序排序,这样效率最高。
CREATE INDEX index_columns ON person(name,age,zz) ;
如上述的复合索引这样查询效率最高:
SELECT * FROM person WHERE name=name AND age=age AND zz=zz
如下情况上述的复合索引起作用:
1.查询name 2.查询name,age 3.查询name,age,zz
如下情况上述的复合索引不起作用:
1.查询age 2.查询zz 3.查询age,zz
聚集和非聚集索引的使用场景
使用场景 | 聚集索引 | 非聚集索引 |
---|---|---|
列经常分组排序 | √ | √ |
返回某范围内的数据 | √ | × |
很少的不同值 | × | × |
小数目不同值 | √ | × |
大数目不同值 | × | √ |
频繁更新的列 | × | √ |
外键列 | √ | √ |
主键列 | √ | √ |
频繁修改索引列 | × | √ |
主键和索引
在sqlserver中如果设置了主键,数据库会自动创建聚集索引(除非聚集索引已存在)。主键的创建必须依赖于索引,可以主键的创建时候也可以声明为非聚集的。
聚合索引主键
**1. ** 创建一个带主键的表
CREATE TABLE person
(
id INT IDENTITY(1,1) NOT NULL,
name varchar(10),
age numeric(3,0),
zz varchar(100),
CONSTRAINT pk_person PRIMARY KEY(id)
);
**2. ** 尝试添加一个聚集索引
CREATE CLUSTERED INDEX index_person_name ON person(name);
非聚合索引主键
**1. ** 创建一个带非聚合索引主键的表
CREATE TABLE person
(
id INT IDENTITY(1,1) NOT NULL,
name varchar(10),
age numeric(3,0),
zz varchar(100),
CONSTRAINT pk_person PRIMARY KEY NONCLUSTERED(id)
);
**2. ** 尝试添加一个聚集索引
CREATE CLUSTERED INDEX index_person_name ON person(name);
添加成功
**3. ** 尝试删除聚合索引
DROP INDEX index_person_name ON person
**4. ** 尝试删除非聚合索引
DROP INDEX index_person_name ON person
使用
通常,我们会在每个表中都建立一个自增id列,以区分每条数据。这样可以让数据库中的数据按照id物理排序。但是由于id是自动生成的,我们并不知道每条数据的id号。
所以在实践中无法根据id来检索,由于每个表只能有一个聚集索引,所以聚集索引的就弥足珍贵。这样使用聚集索引就操成了浪费。
我们也可以把需要提高查询速度的字段建立一个复合索引都放到聚集索引中