36. SQL -- 聚集索引和非聚集索引(2)

关于聚集索引与非聚集索引的讨论:

A、区别:

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

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

B、关于索引的几个问题:

DEMO 分析:

一个学生表student,里面是学生号id,学生姓名,学生所在城市ID,学生成绩(总分)。

· 问:如果想按姓名查询,如何做优化?

· 答:在姓名字段上建立索引。

· 问:建立什么类型的索引?

· 答:建立非聚集索引。

· 问:为什么?

· 答:一般有范围查询的需求,可以考虑在此字段上创建聚集索引。

· 问:学分有重复性,在学分字段上创建聚集索引能行吗? ....沉思,不能创建吗?之前的项目好像真这样做过

· 答:应该可以吧。

· 问:聚集索引的约束是什么?

· 答:唯一性啊?

· 问:既然是唯一性,那么学分字段上还能创建聚集索引吗?....再次沉思,应该可以啊,但索引的约束又怎么说呢?

· 答:应该可以的,以前用过。

○1 :聚集索引的约束是唯一性,是否要求字段也是唯一的呢?

分析:如果认为是的朋友,可能是受系统默认设置的影响,一般我们指定一个表的主键,如果这个表之前没有聚集索引,同时建立主键时候没有强制指定使用非聚集索引,SQL 会默认在此字段上创建一个聚集索引,而主键都是唯一的,所以理所当然的认为创建聚集索引的字段也需要唯一,因此创建了聚集索引的列,并不一定要求其列字段值的唯一性。结论:聚集索引可以创建在任何一列你想创建的字段上,这是从理论上讲,实际情况并不能随便指定,否则在性能上会是恶梦。

○2:为什么聚集索引可以创建在任何一列上,如果此表没有主键约束,即有可能存在重复行数据呢?

粗一看,这还真是和聚集索引的约束相背,但实际情况真可以创建聚集索引,分析其原因是:如果未使用 UNIQUE 属性创建聚集索引,数据库引擎将向表自动添加一个四字节uniqueifier列。必要时,数据库引擎 将向行自动添加一个 uniqueifier 值,使每个键唯一。此列和列值供内部使用,用户不能查看或访问。

○3 :是不是聚集索引就一定要比非聚集索引性能优呢?

如果想查询学分在60-90 之间的学生的学分以及姓名,在学分上创建聚集索引是否是最优的呢?

答:否。既然只输出两列,我们可以在学分以及学生姓名上创建联合非聚集索引,此时的索引就形成了覆盖索引,即索引所存储的内容就是最终输出的数据,这种索引在比以学分为聚集索引做查询性能更好。

○4 :在数据库中通过什么描述聚集索引与非聚集索引的?

索引是通过二叉树的形式进行描述的,我们可以这样区分聚集与非聚集索引的区别:聚集索引的叶节点就是最终的数据节点,而非聚集索引的叶节仍然是索引节点,但它有一个指向最终数据的指针。

○5:在主键是创建聚集索引的表在数据插入上为什么比主键上创建非聚集索引表速度要慢?

有了上面第四点的认识,我们分析这个问题就有把握了,在有主键的表中插入数据行,由于有主键唯一性的约束,所以需要保证插入的数据没有重复。我们来比较下主键为聚集索引和非聚集索引的查找情况:聚集索引由于索引叶节点就是数据页,所以如果想检查主键的唯一性,需要遍历所有数据节点才行,但非聚集索引不同,由于非聚集索引上已经包含了主键值,所以查找主键唯一性,只需要遍历所有的索引页就行,这比遍历所有数据行减少了不少IO 消耗。这就是为什么主键上创建非聚集索引比主键上创建聚集索引在插入数据时要快的真正原因。

 

DEMO:有索引与无索引查询效率分析

A、堆表扫描:

create table tb_heap (co1 int identity (1,1),co2 char(10))

go

insert into tb_heap (co2)

values (‘demo‘)

go 1000

select * from tb_heap

显示预估的执行计划:

查询 → 显示预估的执行计划

显示占有的磁盘空间:

sp_spaceused tb_heap

B、聚集索引扫描:

create table tb_index (co1 int identity (1,1) primary key,co2 char(10))

go

insert into tb_index (co2)

values (‘demo‘)

go 1000

当在表中创建了主键约束后,将自动将主键创键为聚集索引,当全表查询时,查询方式为聚集索引扫描.

select * from tb_index

显示预估的执行计划:

显示占有的磁盘空间:

sp_spaceused tb_index

当在表中创建了主键约束后,将自动将主键创键为聚集索引,当带where语句执行条件查询时,查询方式为聚集索引查找.

select * from tb_index

where co1 = 10

显示预估的执行计划:

管理索引

根据数据库的功能,可以在数据库设计器中创建三种索引:唯一索引、主键索引和聚集索引。

唯一索引: 唯一索引是不允许其中任何两行具有相同索引值的索引。

当现有数据中存在重复的键值时,大多数数据库不允许将新创建的唯一索引与表一起保存。数据库还可能防止添加将在表中创建重复键值的新数据。例如,如果在employee 表中职员的姓(lname)上创建了唯一索引,则任何两个员工都不能同姓。

主键索引:

数据库表经常有一列或列组合,其值唯一标识表中的每一行。该列称为表的主键。在数据库关系图中为表定义主键将自动创建主键索引,主键索引是唯一索引的特定类型。该索引要求主键中的每个值都唯一。当在查询中使用主键索引时,它还允许对数据的快速访问。

聚集索引

在聚集索引中,表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引。如果某索引不是聚集索引,则表中行的物理顺序与键值的逻辑顺序不匹配。与非聚集索引相比,聚集索引通常提供更快的数据访问速度。

 

语法:

CREATE [UNIQUE] [CLUSTERED | NONCLUSTERED]

INDEX index_name ON {table | view } column [ ASC | DESC ][,...n])

[WITH [PAD_INDEX] [ [, ]FILLF ACTOR = fillfactor][ [, ] IGNORE_DUP_KEY]

[ [, ] DROP_EXISTING] [ [, ] STATISTICS_NORECOMPUTE]

[ [, ] SORT_IN_TEMPDB ]]

UNIQUE:表示唯一索引,可选。

CLUSTERED、NONCLUSTERED:表示聚集索引还是非聚集索引,可选。

FILLFACTOR:表示填充因子,指定一个0 到100 之间的值,该值指示索引页填满的空间所占的百分比。

注:数据类型为TEXT、NTEXT、IMAGE 或BIT 的列不能作为索引的列。 由于索引的宽度不能超过900 个字节,因此数据类型为CHAR、VARCHAR、BINARY 和VARBINARY的列的列宽度超过了900 字节,或数据类型为NCHAR、NVARCHAR 的列的列宽度超过了450 个字节时也不能作为索引的列。

创建主键索引:

创建tb_ha1 和tb_ha2 2 张表,其中tb_ha2 配置主键使用统计开关显示查询时间

--开启统计开关

set statistics profile off

set statistics io off

set statistics time off

--开启统计开关

set statistics profile on

set statistics io on

set statistics time on

创建一张普通表 tb_ha1

create table tb_ha1 (docno nvarchar(20), part nvarchar(30))

go

insert into tb_ha1

select LEFT (convert (nvarchar(128),newid()),20),left(convert

(nvarchar(128),newid()),30)

go 5000

select * from tb_ha1

开启统计开关,查看查询时间:

SQL Server 分析和编译时间:

CPU 时间= 0 毫秒,占用时间= 1 毫秒。

(5000 行受影响)

表‘tb_ha1‘。扫描计数1,逻辑读取75 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。

(2 行受影响)

SQL Server 执行时间:

CPU 时间= 31 毫秒,占用时间= 173 毫秒。

创建表tb_ha2,并定义主键索引:

create table tb_ha2 (docno nvarchar(20) primary key, part nvarchar(30))

go

insert into tb_ha2

select LEFT (convert (nvarchar(128),newid()),20),left(convert

(nvarchar(128),newid()),30)

go 5000

开启统计开关,查看查询时间:

Select * from tb_ha2

SQL Server 分析和编译时间:

CPU 时间= 0 毫秒,占用时间= 1 毫秒。

(5000 行受影响)

表‘tb_ha2‘。扫描计数1,逻辑读取108 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物

理读取0 次,lob 预读0 次。

(2 行受影响)

SQL Server 执行时间:

CPU 时间= 0 毫秒,占用时间= 132 毫秒。

LEFT (convert (nvarchar(128),newid()),20)

使用newid(一个随机数),转换数据类型为nvarchar(128),从左开始取值20 位.

创建唯一聚集索引:

DEMO:为tb_ha1 创建唯一聚集索引:

create unique CLUSTERED

index index_docno

on tb_ha1 (docno)

select * from tb_ha1

where docno = ‘0046CC15-B219-4745-B‘

检查表tb_ha1是否创建了索引:

sp_helpindex tb_ha1

创建一个非聚集索引:

DEMO:

create table tb_ha3 (docno nvarchar(20), part nvarchar(30))

go

insert into tb_ha3

select LEFT (convert (nvarchar(128),newid()),20),left(convert

(nvarchar(128),newid()),30)

go 5000

创建索引:

create nonclustered

index index_part

on tb_ha3 (part)

查看所创建的索引:

sp_helpindex tb_ha3

创建复合索引:

为表tb2 创建一个复合索引:

sp_help tb2

select * from tb2

为列ctoyid 及cBrandld 创建一个复合索引:

create

index index_cBr

on tb2 (ctoyid,cBrandld)

查看索引:

sp_helpindex tb2

使用图形化界面创建索引:

数据库 → 表 → 设计 → 列 → 右键 → 索引/键

索引重命名:

使用sp_rename:

语法 :

sp_rename

[ @objname = ] ‘object_name‘ ,

[ @newname = ] ‘new_name‘

[ , [ @objtype = ] ‘object_type‘ ]

删除索引:

用DROP INDEX命令删除索引

DROP INDEX 命令可以删除一个或多个当前数据库中的索引

语法:

DROP INDEX ‘tablename.indexname‘ [,...n]

DROP INDEX 命令不能删除由CREATETABLE 或ALTER TABLE 命令创建的PRIMARY KEY 或UNIQUE 约束索引。也不能删除系统表中的索引

DEMO:

drop index tb2.idx_ctoy

T-SQL 统一命名:

-- pk: 主键

-- fk:外键

-- idx: 索引

-- check:check 约束

时间: 2024-11-05 16:10:55

36. SQL -- 聚集索引和非聚集索引(2)的相关文章

SQL Server中的联合主键、聚集索引、非聚集索引

我们都知道在一个表中当需要2列以上才能确定记录的唯一性的时候,就需要用到联合主键,当建立联合主键以后,在查询数据的时候性能就会有很大的提升,不过并不是对联合主键的任何列单独查询的时候性能都会提升,但我们依然可以通过对联合主键中的首列除外的其他列建立非聚集索引来提高性能.本文将对联合主键.聚集索引.非聚集索引对查询性能的影响举例说明.步骤一,建立一个测试表,并且插入350万条以上的数据. /*创建测试数据表*/create table MyTestTable(id varchar(10)not n

SQL存储原理及聚集索引、非聚集索引、唯一索引、主键约束的关系(补)

索引类型 1.          唯一索引:唯一索引不允许两行具有相同的索引值 2.          主键索引:为表定义一个主键将自动创建主键索引,主键索引是唯一索引的特殊类型.主键索引要求主键中的每个值是唯一的,并且不能为空 3.          聚集索引(Clustered):表中各行的物理顺序与键值的逻辑(索引)顺序相同,每个表只能有一个 4.          非聚集索引(Non-clustered):非聚集索引指定表的逻辑顺序.数据存储在一个位置,索引存储在另一个位置,索引中包含指

35. SQL -- 聚集索引和非聚集索引(1)

索引概述: 用户对数据库最频繁的操作是进行数据查询.一般情况下,数据库在进行查询操作时需要对整个表进行数据搜索.当表中的数据很多时,搜索数据就需要很长的时间,这就造成了服务器的资源浪费.为了提高检索数据的能力,数据库引入了索引机制.数据库索引好比是一本书前面的目录,能加快数据库的查询速度. 例如这样一个查询: select * from table1 where id=44. 如果没有索引,必须遍历整个表,直到ID 等于44 的这一行被找到为止:有了索引之后(必须是在ID 这一列上建立的索引),

SQL Server索引 - 聚集索引、非聚集索引、非聚集唯一索引 <第八篇>

聚集索引.非聚集索引.非聚集唯一索引 我们都知道建立适当的索引能够提高查询速度,优化查询.先说明一下,无论是聚集索引还是非聚集索引都是B树结构. 聚集索引默认与主键相匹配,在设置主键时,SQL Server会默认在主键列创建聚集索引.但是可以手动更改为在任意一个列创建聚集索引,然后在另一个字段或多个字段上定义主键.这时主键将会被作为一个唯一的非聚集索引(唯一索引)被创建.通过指定NONCLUSTERED关键字就可以做到. CREATE TABLE MyTableKeyExample { Colu

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

一.存储结构 在SQL Server中,有许多不同的可用排列规则选项. 二进制:按字符的数字表示形式排序(ASCII码中,用数字32表示空格,用68表示字母"D").因为所有内容都表示为数字,所以处理起来速度最快,遗憾的是,它并不总是如人们所想象,在WHERE子句中进行比较时,使用该选项会造成严重的混乱. 字典顺序:这种排序方式与在字典中看到的排序方式一样,但是少有不同,可以设置大量不同的额外选项来决定是否区分大小写.音调和字符集. 1.平衡树(B-树) 平衡树或B-树仅是提供了一种以

SQL SERVER索引之聚集索引和非聚集索引的描述

索引是与表或视图关联的磁盘上结构,可以加快从表或视图中检索行的速度. 索引包含由表或视图中的一列或多列生成的键. 这些键存储在一个结构(B 树)中,使 SQL Server 可以快速有效地查找与键值关联的行. 表或视图可以包含以下类型的索引: 聚集 聚集索引根据数据行的键值在表或视图中排序和存储这些数据行. 索引定义中包含聚集索引列. 每个表只能有一个聚集索引,因为数据行本身只能按一个顺序排序. 只有当表包含聚集索引时,表中的数据行才按排序顺序存储. 如果表具有聚集索引,则该表称为聚集表. 如果

你能说出SQL聚集索引和非聚集索引的区别吗?

最近突然想起前一阵和一朋友的聊天,当时他问我的问题是一个非常普通的问题:说说SQL聚集索引和非聚集索引的区别. AD:WOT2015 互联网运维与开发者大会 热销抢票 其实对于非专业的数据库操作人员来讲,例如软件开发人员,在很大程度上都搞不清楚数据库索引的一些基本知识,有些是知其一不知其二,或者是知其然不知其所以然.造成这种情况的主要原因我觉的是行业原因,有很多公司都有自己的DBA团队,他们会帮助你优化SQL,开发人员即使不懂优化问题也不大,所以开发人员对这方面也就不会下太多功夫去了解SQL优化

SQL聚集索引和非聚集索引的区别

其实对于非专业的数据库操作人员来讲,例如软件开发人员,在很大程度上都搞不清楚数据库索引的一些基本知识,有些是知其一不知其二,或者是知其然不知其所以然.造成这种情况的主要原因我觉的是行业原因,有很多公司都有自己的DBA团队,他们会帮助你优化SQL,开发人员即使不懂优化问题也不大,所以开发人员对这方面也就不会下太多功夫去了解SQL优化,但如果公司没有这样的DBA呢,就只能靠程序员自己了. 最近突然想起前一阵和一朋友的聊天,当时他问我的问题是一个非常普通的问题:说说SQL聚集索引和非聚集索引的区别.

SQL有三个类型的索引,唯一索引 不能有重复,但聚集索引,非聚集索引可以有重复

重要: (1) SQL如果创建时候,不指定类型那么默认是非聚集索引 (2) 聚集索引和非聚集索引都可以有重复记录,唯一索引不能有重复记录. (3) 主键 默认是加了唯一约束的聚集索引,但是也可以在主键创建时,指定为唯一约束的非聚集索引,因此主键仅仅是默认加了唯一约束的聚集索引,不能说主键就是加了唯一约束的聚集索引 有点拗口,可以参考我的博客:主键就是聚集索引吗? 为列创建索引实际上就是为列进行排序,以方便查询.建立一个列的索引,就相当与建立一个列的排序. 主键是唯一的,所以创建了一个主键的同时,