你谈到的效率 用索引 看下下面的试试全文索引create table testIndex ( id int identity(1,1) primary key, nm varchar(100) unique not null, sex varchar(10) ) create UNIQUE index UQ__testIndex__0DAF0CB0 on testindex(nm)insert into testindex select 'aaabbb','m' union all select 'bbb','w' union all select 'ccc','w' union all select 'ddd','m' insert into testindex select '麦蒂未伤愈中途退出训练复出时间再度成疑','北京' go --创建全文目录 sp_fulltext_catalog 'abc','create' go --创建全文索引(‘表名‘,’创建/删除‘,’全文目录名‘,’约束名‘) sp_fulltext_table 'testindex','create','abc','UQ__testIndex__0DAF0CB0' go --添加列到全文索引(‘表名‘,’列名‘,’添加/删除‘) sp_fulltext_column 'testindex','nm','add' go --建立全文索引 --activate,是激活表的全文检索能力,也就是在全文目录中注册该表 execute sp_fulltext_table 'testindex','activate' go --填充全文索引目录 execute sp_fulltext_catalog 'abc','start_full' go--检查全文目录填充情况 While fulltextcatalogproperty('abc','populateStatus')<>0 begin--如果全文目录正处于填充状态,则等待30秒后再检测一次 waitfor delay '0:0:30' end--全文目录填充完成后,即可使用全文目录检索 SELECT * FROM testindex WHERE CONTAINS(nm, '麦蒂') /*id nm sex ----------- --------------------------------------------- ------------------------------------------------ ---------- 5 麦蒂未伤愈中途退出训练复出时间再度成疑 北京(所影响的行数为 1 行) */ insert into testindex select '麦蒂未伤愈中途退出训练复出时间再度成疑12121','北京' go SELECT * FROM testindex WHERE CONTAINS(nm, '麦蒂') -----No result /*id nm sex ----------- --------------------------------------------- ------------------------------------------------ ---------- 5 麦蒂未伤愈中途退出训练复出时间再度成疑 北京(所影响的行数为 1 行) */ go--填充全文索引目录 execute sp_fulltext_catalog 'abc','start_full' go --检查全文目录填充情况 While fulltextcatalogproperty('abc','populateStatus')<>0 begin--如果全文目录正处于填充状态,则等待30秒后再检测一次 waitfor delay '0:0:30' end SELECT * FROM testindex WHERE CONTAINS(nm, '麦蒂')go /*id nm sex ----------- ---------------------------------------------------------------------------------------------------- ---------- 6 麦蒂未伤愈中途退出训练复出时间再度成疑12121 北京 5 麦蒂未伤愈中途退出训练复出时间再度成疑 北京(所影响的行数为 2 行)*/ sp_fulltext_table 'testindex','drop' go sp_fulltext_catalog 'abc','drop' go drop table testIndex
在看下 这个偶看 Z老大的书 做的笔记 --索引是对是数据库表中一个或多个列的值进行排序的结构 /* (1)聚集索引 聚集索引基于数据行的键值在表内排序和存储这些数据 只有当表包含聚集索引时,表中的数据行才按排序顺序存储.如果表具有聚集索引,则该表称为聚集表,每个表只能有一个聚集索引,因为数据行只能按照一个顺序存储 (2)非聚集索引 非聚集索引独立存储非聚集索引包含非聚集索引键值并且该键值项都指向该键值的数据行的指针 从非聚集索引中的索引行指向数据行的指针称为行定位器,行定位器的结构取决与数据页是存储在堆中还是在聚集表中,对于堆,行定位器是指向行的指针.对于聚集表,行定位器是聚集索引键,允许为表建立多个非聚集索引 (3)索引的存储与检索 SQL Server以页为数据存储的基本单位,每个夜页的大小为8KB,每页的开始部分是96字节的页首. 聚集索引和非聚集索引的在B数结构上的差异主要在于B数的叶节点: 对应聚集索引而言,它是与表中的数据行在一起的,而对于非聚集索引,索引数据是单独存放的,它的叶节点是索引行数据 (4)索引的检索(5)统计 在建立索引的时候,SQL会自动的为索引定义中的第一个列创建统计 当数据库的auto_create_statistics设置为ON时,SQL查询优化器会根据查询条件在相关的列上自动建立统计 create statistics语句手工创建统计 通过表或索引视图已提供列或一组列创建组状图和关联密度组 */ --统计的重要性 alter database Test set auto_create_statistics off, auto_update_statistics on go if object_id('tb') is not null drop table tb create table tb ( id int identity(1,1) primary key, [Name] char(7000), sex nchar(1) ) insert tb([Name],sex) select top 1000 '',N'男' from dbo.syscolumns C1,dbo.syscolumns C2 --select * from tb update tb set sex='女' where id>900 create index index_tb on tb(id,sex) go--在没有统计的情况下 set statistics io on --打开磁盘活动信息 select * from tb where sex=N'女' set statistics io off--在有统计的情况下,查看磁盘活动信息 create statistics ON_tb on tb(sex) set statistics io on select * from tb where sex=N'女' set statistics io off drop statistics tb.ON_tb alter database Test set auto_create_statistics on goset statistics io on --打开磁盘活动信息 select * from tb where sex=N'女' set statistics io offselect * from sysindexes where id=object_id('tb') create table tb ( id int identity(1,1) primary key, [Name] char(7000), sex nchar(1) ) insert tb([Name],sex) select top 5000 '',N'男' from dbo.syscolumns C1,dbo.syscolumns C2update tb set sex=N'女' where id>4000 create index IX_tb on dbo.tb(id,sex) create index IX_tb2 on dbo.tb(sex,id)set statistics io on --打开磁盘活动信息 select * from tb where sex=N'男' set statistics io on select * from dbo.tb with(index(IX_tb2)) where id>4000 and sex='女'select * from dbo.tb with(index(IX_tb)) where id>4000 and sex='女' set statistics io off
不对哦??当我删了那个聚集索引时,主键也跟着删除了,如何留住主键只删聚集索引呢??? 由于不能Sql Server Management studio用直接删聚集索引,所以我用的" alter table tableb drop constraint PK_tableb"
看来错了。楼主说的没错,聚集索引删除,主键也删除了。 if object_id('[tb]') is not null drop table [tb] go create table [tb]([Name] varchar(10)) alter table tb alter column name varchar(10) not null --修改字段为非空值约束 alter table tb add constraint pk_tb primary key (name) --新增主键约束 sp_helpindex tb --查看索引,发现索引名跟主键名一致 alter table tb drop constraint pk_tb --删除索引 sp_helpconstraint tb --查看约束,发现没有主键约束了。从新分析楼主的需求,发现SQL主键跟聚集索引是同在的,不能也不需要改变这个设置。
if object_id('[tb]') is not null drop table [tb] go create table [tb](id int primary key,[Name] varchar(10)) create unique index idx_uqe_name on tb(name) --创建唯一非聚集索引就行了。
谢谢顾老大,测试结果与你的回答稳合。create table tb_test(id int not null,col int)create unique clustered index idx_tb_test_col on tb_test(col)alter table tb_test add constraint pk_tb_test_id primary key (id)sp_helpindex tb_test /* index_name index_description index_keys --------------- ---------------------------- ----------------- idx_tb_test_col clustered, unique located on PRIMARY col (col为聚集索引) pk_tb_test_id nonclustered, unique, primary key located on PRIMARY id (主键变成了非聚集索引) */
用索引
看下下面的试试全文索引create table testIndex
(
id int identity(1,1) primary key,
nm varchar(100) unique not null,
sex varchar(10)
)
create UNIQUE index UQ__testIndex__0DAF0CB0
on testindex(nm)insert into testindex
select 'aaabbb','m' union all
select 'bbb','w' union all
select 'ccc','w' union all
select 'ddd','m'
insert into testindex
select '麦蒂未伤愈中途退出训练复出时间再度成疑','北京'
go
--创建全文目录
sp_fulltext_catalog 'abc','create'
go
--创建全文索引(‘表名‘,’创建/删除‘,’全文目录名‘,’约束名‘)
sp_fulltext_table 'testindex','create','abc','UQ__testIndex__0DAF0CB0'
go
--添加列到全文索引(‘表名‘,’列名‘,’添加/删除‘)
sp_fulltext_column 'testindex','nm','add' go
--建立全文索引
--activate,是激活表的全文检索能力,也就是在全文目录中注册该表
execute sp_fulltext_table 'testindex','activate'
go
--填充全文索引目录
execute sp_fulltext_catalog 'abc','start_full'
go--检查全文目录填充情况
While fulltextcatalogproperty('abc','populateStatus')<>0
begin--如果全文目录正处于填充状态,则等待30秒后再检测一次
waitfor delay '0:0:30'
end--全文目录填充完成后,即可使用全文目录检索
SELECT * FROM testindex WHERE CONTAINS(nm, '麦蒂') /*id nm sex
----------- --------------------------------------------- ------------------------------------------------ ----------
5 麦蒂未伤愈中途退出训练复出时间再度成疑 北京(所影响的行数为 1 行)
*/
insert into testindex
select '麦蒂未伤愈中途退出训练复出时间再度成疑12121','北京'
go
SELECT * FROM testindex WHERE CONTAINS(nm, '麦蒂')
-----No result
/*id nm sex
----------- --------------------------------------------- ------------------------------------------------ ----------
5 麦蒂未伤愈中途退出训练复出时间再度成疑 北京(所影响的行数为 1 行)
*/
go--填充全文索引目录
execute sp_fulltext_catalog 'abc','start_full'
go
--检查全文目录填充情况
While fulltextcatalogproperty('abc','populateStatus')<>0
begin--如果全文目录正处于填充状态,则等待30秒后再检测一次
waitfor delay '0:0:30'
end
SELECT * FROM testindex WHERE CONTAINS(nm, '麦蒂')go
/*id nm sex
----------- ---------------------------------------------------------------------------------------------------- ----------
6 麦蒂未伤愈中途退出训练复出时间再度成疑12121 北京
5 麦蒂未伤愈中途退出训练复出时间再度成疑 北京(所影响的行数为 2 行)*/
sp_fulltext_table 'testindex','drop'
go
sp_fulltext_catalog 'abc','drop'
go
drop table testIndex
这个偶看 Z老大的书
做的笔记
--索引是对是数据库表中一个或多个列的值进行排序的结构
/*
(1)聚集索引
聚集索引基于数据行的键值在表内排序和存储这些数据
只有当表包含聚集索引时,表中的数据行才按排序顺序存储.如果表具有聚集索引,则该表称为聚集表,每个表只能有一个聚集索引,因为数据行只能按照一个顺序存储
(2)非聚集索引
非聚集索引独立存储非聚集索引包含非聚集索引键值并且该键值项都指向该键值的数据行的指针
从非聚集索引中的索引行指向数据行的指针称为行定位器,行定位器的结构取决与数据页是存储在堆中还是在聚集表中,对于堆,行定位器是指向行的指针.对于聚集表,行定位器是聚集索引键,允许为表建立多个非聚集索引
(3)索引的存储与检索
SQL Server以页为数据存储的基本单位,每个夜页的大小为8KB,每页的开始部分是96字节的页首.
聚集索引和非聚集索引的在B数结构上的差异主要在于B数的叶节点:
对应聚集索引而言,它是与表中的数据行在一起的,而对于非聚集索引,索引数据是单独存放的,它的叶节点是索引行数据
(4)索引的检索(5)统计
在建立索引的时候,SQL会自动的为索引定义中的第一个列创建统计
当数据库的auto_create_statistics设置为ON时,SQL查询优化器会根据查询条件在相关的列上自动建立统计
create statistics语句手工创建统计
通过表或索引视图已提供列或一组列创建组状图和关联密度组
*/
--统计的重要性
alter database Test
set
auto_create_statistics off,
auto_update_statistics on
go
if object_id('tb') is not null drop table tb
create table tb
(
id int identity(1,1) primary key,
[Name] char(7000),
sex nchar(1)
)
insert tb([Name],sex) select top 1000 '',N'男' from dbo.syscolumns C1,dbo.syscolumns C2
--select * from tb
update tb set sex='女' where id>900
create index index_tb on tb(id,sex)
go--在没有统计的情况下
set statistics io on --打开磁盘活动信息
select * from tb where sex=N'女'
set statistics io off--在有统计的情况下,查看磁盘活动信息
create statistics ON_tb on tb(sex)
set statistics io on
select * from tb where sex=N'女'
set statistics io off
drop statistics tb.ON_tb
alter database Test
set
auto_create_statistics on
goset statistics io on --打开磁盘活动信息
select * from tb where sex=N'女'
set statistics io offselect * from sysindexes where id=object_id('tb')
create table tb
(
id int identity(1,1) primary key,
[Name] char(7000),
sex nchar(1)
)
insert tb([Name],sex) select top 5000 '',N'男' from dbo.syscolumns C1,dbo.syscolumns C2update tb set sex=N'女' where id>4000
create index IX_tb on dbo.tb(id,sex)
create index IX_tb2 on dbo.tb(sex,id)set statistics io on --打开磁盘活动信息
select * from tb where sex=N'男'
set statistics io on
select * from dbo.tb with(index(IX_tb2)) where id>4000 and sex='女'select * from dbo.tb with(index(IX_tb)) where id>4000 and sex='女'
set statistics io off
http://topic.csdn.net/u/20090422/16/d37a2b46-54fb-4be6-96c7-2ae004ca0c42.html
动作描述 使用聚集索引 使用非聚集索引
-----------------------------------------------------------
列经常被分组排序 应 应
返回某范围内的数据 应 不应
一个或极少不同值 不应 不应可是SQL自动给它生成了聚集索引,因为它上面是主键,这又怎么回事呢
不对哦??当我删了那个聚集索引时,主键也跟着删除了,如何留住主键只删聚集索引呢???
由于不能Sql Server Management studio用直接删聚集索引,所以我用的" alter table tableb drop constraint PK_tableb"
if object_id('[tb]') is not null drop table [tb]
go
create table [tb]([Name] varchar(10))
alter table tb alter column name varchar(10) not null --修改字段为非空值约束
alter table tb add constraint pk_tb primary key (name) --新增主键约束
sp_helpindex tb --查看索引,发现索引名跟主键名一致
alter table tb drop constraint pk_tb --删除索引
sp_helpconstraint tb --查看约束,发现没有主键约束了。从新分析楼主的需求,发现SQL主键跟聚集索引是同在的,不能也不需要改变这个设置。
提供高度唯一性。 两者的比较下面是一个简单的比较表 主键 聚集索引
用途 强制表的实体完整性 对数据行的排序,方便查询用
一个表多少个 一个表最多一个主键 一个表最多一个聚集索引
是否允许多个字段来定义 一个主键可以多个字段来定义 一个索引可以多个字段来定义
是否允许 null 数据行出现 如果要创建的数据列中数据存在null,无法建立主键。 创建表时指定的 PRIMARY KEY 约束列隐式转换为 NOT NULL。
没有限制建立聚集索引的列一定必须 not null . 也就是可以列的数据是 null参看最后一项比较
是否要求数据必须唯一 要求数据必须唯一 数据即可以唯一,也可以不唯一。看你定义这个索引的 UNIQUE 设置。 (这一点需要看后面的一个比较,虽然你的数据列可能不唯一,但是系统会替你产生一个你看不到的唯一列)
创建的逻辑 数据库在创建主键同时,会自动建立一个唯一索引。 如果这个表之前没有聚集索引,同时建立主键时候没有强制指定使用非聚集索引,则建立主键时候,同时建立一个唯一的聚集索引
如果未使用 UNIQUE 属性创建聚集索引,数据库引擎 将向表自动添加一个四字节 uniqueifier 列。 必要时,数据库引擎 将向行自动添加一个 uniqueifier 值,使每个键唯一。此列和列值供内部使用,用户不能查看或访问。
参考:下面这个帖子中大力的回复:http://topic.csdn.net/t/20021212/16/1255429.html
go
create table [tb](id int primary key,[Name] varchar(10))
create unique index idx_uqe_name on tb(name) --创建唯一非聚集索引就行了。
可加快查询速度.建议创建表时,先考虑主键的约束逻辑,再考虑索引,查询速度等因素.
那是因为你在定义主健前,并没有给表建聚集索引。我在28楼第二行已经说过了。 当然,这个只是针对于sqlserver(oracle下好像也是). sybase下,即便一个表没有聚集索引,建了主健后,也不会自动给主健指定的列加聚集索引。
/*
index_name index_description index_keys
--------------- ---------------------------- -----------------
idx_tb_test_col clustered, unique located on PRIMARY col (col为聚集索引)
pk_tb_test_id nonclustered, unique, primary key located on PRIMARY id (主键变成了非聚集索引)
*/
1. 主键最好建在一个字段上(满足了这条就满足了2NF的要求)
2. 主键最好建在一个整数型(类似int)的字段上,这是速度最快的
3. 如果必须要见复合主键,也是可以的,比如<Column1, Column2>作为复合主键。但是你在select语句的where
子句中,这两个字段出现的顺序一定要和定义主键时一致,即必须是...where Column1 = ... and Column2 = ...,否则主键失效,所以不仅索引要建正确,还要使用正确。
4. 还有很多其他的技巧,请看:
http://blog.csdn.net/pathuang68/archive/2009/04/16/4084116.aspx
原理是想通的。