索引

什么是索引?

索引是一种磁盘上的数据结构,建立在表或视图的基础上。使用索引可以使数据的获取更快更高校,也会影响其他的一些性能,如插入或更新等。

索引主要分为两种类型:聚集索引和非聚集索引。

字典的目录就是一个索引,按照拼音查询想要的字就是聚集索引(物理连续,页码与目录一一对应),偏旁部首就是一个非聚集索引(逻辑连续,页码与目录不连续)。

聚集索引存储记录是物理上连续存在的,而非聚集索引是逻辑上的连续,物理存储并不连续。

聚集索引一个表中只能有一个,而非聚集索引一个表中可以有多个。

索引的利弊

使用索引是为了避免全表扫描,因为全表扫描是从磁盘上读取表的每一个数据页,如果有索引指向数据值,则只需要读少次数的磁盘就可以。

带索引的表在数据库中占用更多的空间,同样增、删、改数据的命令所需时间会更长。

索引的存储机制

书中的目录是一个字词以及所在的页码列表,数据库中的索引是表中的值以及各值存储位置的列表。

聚集索引是在数据库中新开辟一个物理空间,用来存放他排列的值,当有新数据插入时,他会重新排列整个物理存储空间。

非聚集索引只包含原表中的非聚集索引的列和指向实际物理表的一个指针。

数据表的基本结构

当一个新的数据表创建时,系统将在磁盘中分配一段以8k为单位的连续空间。当一个8k用完的时候,数据库指针会自动分配一个8k的空间,每个8k的空间称为一个数据页,并分配从0-7的页号,每个文件的第0页记录引导信息叫页头,每8个数据页由64k组成形成扩展区。全部数据页的组合形成堆。

SQL Server规定行不能跨越数据页,所以每行记录的最大数量只能是8k,这就是为什么char和varchar这两种字符类型容量要限制在8k以内的原因,存储超过8k的数据应使用text类型,其实text类型的字段值不能直接录入和保存,它是存储一个指针,指向由若干个8k的数据页所组成的扩展区,真正的数据其实放在这些数据页中。

什么情况下设置索引

1、定义主键的数据列(sql server默认会给主键一个聚集索引)。

2、定义有外键的数据列

3、对于经常查询的数据列

4、对于需要在指定范围内频繁查询的数据列

5、经常在where子句中出现的数据列

6、经常出现在关键字 order by、group by、distinct后面的字段。

什么情况下不要设置索引

1、查询中很少涉及的列,重复值比较多的列。

2、text、image、bit数据类型的列

3、经常存取的列

4、经常更新操作的表,索引一般不要超过3个、最多不要5个。虽说提高了访问速度,但会影响更新操作。

聚集索引

1、使用SSMS创建聚集索引

展开要创建索引的表->右击索引->选择新建索引->聚集索引->新建索引点添加->选择列->选择升序或降序->输入名字->确定。

默认情况下,生成主键的同时将自动创建一个聚集索引。

2、使用T-SQL创建聚集索引

use webDB
go
create clustered index index_name /*聚集索引名*/
on table_name
(
id desc
)
with(drop_existing=on); /*如果存在则删除*/

每张表或者视图只能包含一个聚集索引,因为聚集索引改变了数据存储与排列方式。无论是聚集还是非聚集索引,都将信息存储在平衡树或B-树中,B-树识别类似数据并将他们组合在一起,正是由于B-树中的检索基于键值,因此索引可以提升数据访问的速度。B-树将具有类似键的组合起来,所以数据库引擎只需搜索少量页面即可找到目标记录。

非聚集索引

每张表上可以有多个非聚集索引,可以在某个列上创建一个索引,也可以在已经是现有索引组成部分的多列上创建索引。

SSMS创建方法同上,T-SQL创建方法如下:

use webDB
go
create nonclustered index fei /*聚集索引名*/
on defualt
(
hits desc
)

添加索引选项

fillfactor:用于在创建索引时,每个索引页的数据占索引大小的百分比,默认100.当需要频繁修改表时,建议设置为70-80,不经常更新时建议90.

pad_index:用于索引中间级中每个页上保持开放的空间。不能设置值,他的值继承自fillfactor。

小例子

use webDB
go
create table ceshi --新建表
(
id int identity(1,1) primary key,
name varchar(20),
code varchar(20),
[date] datetime
) --插入10w条测试数据
declare @n int
set @n = 1
while @n <100000
begin
Insert into ceshi (name,code,[date])
values ('name'+cast(@n as varchar(20)),'code'+cast(@n as varchar(20)),getutcdate())
set @n=@n+1
end --查看索引情况
set statistics io on --查看磁盘io
set statistics time on --查看sql语句分析编译和执行时间
select * from ceshi --查看索引情况
exec sp_helpindex ceshi select * from ceshi where name = 'name1' --ctrl+l 查看执行计划 聚集索引扫描开销100%,考虑优化为索引查找,在name上建立非聚集索引 --建立非聚集索引
create index name_index on ceshi
(
name
)
--再次查看索引情况 多出来新建的非聚集索引
exec sp_helpindex ceshi --在运行上面的语句
select * from ceshi where name = 'name1'
--明显发现速度变快了 , ctrl+l 发现聚集索引和非聚集索引各占50%

管理索引

exec sp_helpindex ceshi --查看该表中的索引
exec sp_rename 'ceshi.name_index','new_name' --改名
drop index ceshi.new_name --删除索引
dbcc showcontig(ceshi,new_name) --检查碎片
dbcc indexdefrag(webDB,ceshi,new_name) --整理碎片
update statistics ceshi --更新表中所有索引的统计

表压缩

SQL Server的主要性能取决于磁盘I/O效率,SQL Server 2008提供了数据压缩功能来提高磁盘I/O效率。

表压缩意味着减小数据的磁盘占有量,所以压缩可以用在堆表、聚集索引的表、非聚集索引的表、索引视图、分区表上。

可压缩的数据类型

smallint、int、Bigint、decimal、numeric、real、float、money、smallmoeny、bit、datetime、datetime2、datetimeoffset、char、nchar、binary、rowversion。

SQLServer中有两种压缩类型:数据与备份

行压缩

压缩会改变数据的物理存储方式,但不需要对代码做任何修改。

行压缩流程:首先识别表中每一列的数据类型,然后转换为可变长度,最后将存储空间的请求总量减少到实际需求量。

如:固定长度的类型int、char、nchar等,在数据页中以不定长度的方式存储(存储真实数据长度)。

1、SSMS行压缩

表->右键->存储->管理压缩->对所有分区使用相同压缩类型->右侧 选择row->立即执行->完成。

在压缩堆表或聚集索引时并不同时包含非聚集索引,因此需要另外单独对非聚集索引进行操作。

索引->右键->存储->管理压缩->对所有分区使用相同压缩类型->右侧 选择row->立即执行->完成。

2、T-SQL行压缩

--在现有表进行压缩
--聚集
alter table ceshi rebuild with(data_compression=row) --非聚集
alter index new_name on ceshi rebuild with(data_compression=row) --在创建表时进行压缩
create table yasuo
(
id int primary key,
name varchar(50),
mail varchar(50)
)
with (data_compression=row)

创建时指定行压缩方式,这时并未发生改变。只要数据插入表中,该行即被压缩。

页压缩

页压缩通过执行额外的一些步骤增强了行压缩的功能。

页压缩步骤:行压缩、前缀压缩、字典压缩。

首先对于每一列将确定一个值,此值可以减少每一列中值的存储空间。一旦确定该值后,每一列的前缀值的行将被存储在页头中。所有的信息称为压缩信息,存储在页头之下。标识的值(前缀值)位于没列中,将由指向压缩信息部分中对应值的引用进行替换。

下一步字典压缩,搜索整个页面而非单个列,重复值被移动到页头的压缩信息部分,取而代之的是指向该值的引用。

在SSMS中页压缩步骤与行压缩步骤一致,只是选择压缩方式为Page。T-SQL中将row改成page即可。

需要注意

1、如果保留在内存中的数据是压缩的,一旦被选中,则必须先进行解压缩。

2、在插入新行时,数据也是行或页压缩的。

3、当更新或删除时,行压缩对象保留当前的压缩级别。但是页压缩可能需要重新计算,取决于发生变化的数据量。

用哪种压缩

需要频繁更新的对象应该使用行压缩。

只是执行读取操作的应该使用页压缩。

7、SQL Server索引、表压缩的更多相关文章

  1. 转: SQL Server索引的维护 - 索引碎片、填充因子

    转:http://www.cnblogs.com/kissdodog/archive/2013/06/14/3135412.html 实际上,索引的维护主要包括以下两个方面: 页拆分 碎片 这两个问题 ...

  2. SQL Server索引的维护 - 索引碎片、填充因子 <第三篇>

    实际上,索引的维护主要包括以下两个方面: 页拆分 碎片 这两个问题都和页密度有关,虽然两者的表现形式在本质上有所区别,但是故障排除工具是一样的,因为处理是相同的. 对于非常小的表(比64KB小得多), ...

  3. Sql server 系统表

    sql server系统表详细说明 SQL Server 用户库中系统表说明 名称 说明 备注 syscolumns 每个表和视图中的每列在表中占一行,存储过程中的每个参数在表中也占一行.   sys ...

  4. sql server 索引总结三

    一.非聚集索引维护 非聚集索引的行定位器值保持相同的聚集索引值,即使该聚集索引列物理上重新定位后,也是如此. 为了优化这个维护开销,SQL Server添加一个指向旧数据页的指针,以在页面分割之后指向 ...

  5. sql server 索引总结一

    一.存储结构 在SQL Server中,有许多不同的可用排列规则选项. 二进制:按字符的数字表示形式排序(ASCII码中,用数字32表示空格,用68表示字母"D").因为所有内容都 ...

  6. SQL Server 堆表行存储大小(Record Size)

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 堆表行记录存储格式(Heap) 案例分析(Case) 参考文献(References) 二.背 ...

  7. 【译】SQL Server索引进阶第八篇:唯一索引

    原文:[译]SQL Server索引进阶第八篇:唯一索引     索引设计是数据库设计中比较重要的一个环节,对数据库的性能其中至关重要的作用,但是索引的设计却又不是那么容易的事情,性能也不是那么轻易就 ...

  8. 千万级SQL Server数据库表分区的实现

    千万级SQL Server数据库表分区的实现 2010-09-10 13:37 佚名 数据库 字号:T | T 一般在千万级的数据压力下,分区是一种比较好的提升性能方法.本文将介绍SQL Server ...

  9. SQL Server索引 (原理、存储)聚集索引、非聚集索引、堆 <第一篇>

    一.存储结构 在SQL Server中,有许多不同的可用排列规则选项. 二进制:按字符的数字表示形式排序(ASCII码中,用数字32表示空格,用68表示字母"D").因为所有内容都 ...

  10. SQL Server 系统表简介

    SQL Server 系统表简介 系统目录是由描述SQL Server 系统的数据库.基表.视图和索引等对象的结构的系统表组成.SQL Server 经常访问系统目录,检索系统正常运行所需的必要信息. ...

随机推荐

  1. MyBatis学习(一)

    前言 再过一个月,转行做java web就满一年了.当初吸引我进入公司的,其实并不是java web,而是领导给我描述的hadoop生态圈.公司的hadoop集群以及大数据业务.可是进入公司后才发现, ...

  2. WebAPI学习点滴(二)

    刚开始学习WebApi就遇到了问题,在同一个API控制器中,如果两个方法的签名相同,比如 [HttpGet] public string GetString() { return "Hell ...

  3. coffeeScript中类的多态[学习篇]

    类的一大应用就是多态.多态是一个面向对象编程的高级术语----“一个东西可编程很多不同的东西,但不是任何东西”.[引自coffeescript深入浅出] class Shape constructor ...

  4. Datatables回调函数中文

    Datatables——回调函数 ------------------------------------------------- fnCookieCallback:还没有使用过 $(documen ...

  5. ecstore-app接口

    接口调用方式: 接口完整地址为:http://域名/index.php/wapapp/请求地址 比如获取商品信息就是 http://域名/index.php/wapapp/product.html 提 ...

  6. Linux下使用ping快速检测存活主机

    该shell脚本主要是通过ping来批量检测网段内存活主机,执行结果保存在脚本当前目录下的IPinfor目录中,写的比较匆忙,希望大家留下更好的建议. #!/usr/bin/env bash##### ...

  7. hibernate:Named query not known: findXXXX or XXXX is not mapped

    .hbm.xml文件所放的位置怎么看怎么都在spring配置的扫描路径中,就是会出现标题所示错误,查看log日志,的确也没发现XXXX被mapped的记录~ 参考解决方案: 在eclipse导出jar ...

  8. Javascript技巧

    Javascript数组转换为CSV格式 首先考虑如下的应用场景,有一个Javscript的字符型(或者数值型)数组,现在需要转换为以逗号分割的CSV格式文件.则我们可以使用如下的小技巧,代码如下: ...

  9. ruby 中%Q %q %W %w %x %r %s的用法

    %Q 用于替代双引号的字符串. 当你需要在字符串里放入很多引号时候, 可以直接用下面方法而不需要在引号前逐个添加反斜杠 (\") >> %Q(Joe said: "Fr ...

  10. MyBatis与Spring整合

    1.单独使用MyBatis 单独使用MyBatis,不结合其他框架,主要步骤是: 1.创建SqlSessionFactory对象 创建方法是通过SqlSessionFactoryBuilder这个类从 ...