--聚簇索引的唯一性

--正式聚簇索引的顺序就是数据的物理存储顺序,所以一个表最多只能有一个聚簇索引,因为物理存储只能有一个顺序,

--正因为一个表最多只能有一个聚簇索引,所以它显得更为珍贵,一个表设置什么为聚簇索引对性能很关键。

--误区:把主键自动设为聚簇索引

--因为这是SQLServer的默认主键行为,你设置了主键,它就把主键设为聚簇索引,而一个表最多只能有一个聚簇索引,

--所以很多人就把其他索引设置为非聚簇索引。这个是最大的误区,甚至有的主键又是无意义的自动增量字段,

--那样的话Clustered index对效率的帮助,完全被浪费了。

--聚簇索引性能最好而且具有唯一性,所以非常珍贵,必须慎重设置,

--一般要根据这个表最常用的SQL查询方式来进行选择,某个字段作为聚簇索引,或组合聚簇索引,这个要看实际情况。

--事实上,建表的时候,先添加我们想要的聚簇索引,最后设置主键,

--SQLServer就会自动把主键设置为非聚簇索引,如果你已经设置了主键为聚簇索引,

--必须先删除主键,然后添加我们想要的聚簇索引,最后恢复设置主键即可。

--建立测试数据表:

CREATE TABLE [dbo].[Table1](

 [ID] [int] IDENTITY(1,1) NOT NULL,

 [Data1] [int] NOT NULL DEFAULT ((0)),

 [Data2] [int] NOT NULL DEFAULT ((0)),

 [Data3] [int] NOT NULL DEFAULT ((0)),

 [Name1] [nvarchar](50) NOT NULL DEFAULT (''),

 [Name2] [nvarchar](50) NOT NULL DEFAULT (''),

 [Name3] [nvarchar](50) DEFAULT (''),

 [DTAt] [datetime] NOT NULL DEFAULT (getdate()))

--插入10000条记录  

declare @i int

set @i = 1

while @i < 100000

begin

insert into Table1 ([Data1] ,[Data2] ,[Data3] ,[Name1],[Name2] ,[Name3])

values(@i, 2* @i,3*@i, CAST(@i AS NVARCHAR(50)), CAST(2*@i AS NVARCHAR(50)), CAST(3*@i AS NVARCHAR(50)))

set @i = @i + 1

end

update table1 set dtat = DateAdd (s, data1, dtat)  

--查询,查看统计数据

SET STATISTICS IO ON;

SET STATISTICS TIME ON;

SELECT * FROM Table1 WHERE Data1 = 2 ORDER BY DTAt DESC;

SET STATISTICS IO OFF;

SET STATISTICS TIME OFF;

--先在Table1设主键ID,系统自动为该主键建立了聚簇索引

ALTER TABLE Table1 ADD CONSTRAINT PK_Table1 PRIMARY KEY (ID)

--然后我们在Data1和DTat字段分别建立非聚簇索引:

CREATE NONCLUSTERED INDEX [N_Data1] ON [dbo].[Table1]

(

[Data1] ASC

)WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]

CREATE NONCLUSTERED INDEX [N_DTat] ON [dbo].[Table1]

(

[DTAt] ASC

)WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]

--查询,可以看到设立了索引反而没有任何性能的提升而且消耗的时间更多了,继续调整。

--删除所有非聚簇索引 并删除主键 这样所有索引都删除了 建立组合索引Data1和DTAt 最后加上主键

DROP INDEX Table1.N_Data1

DROP INDEX Table1.[N_DTat]

ALTER TABLE Table1 DROP CONSTRAINT PK_Table1

CREATE CLUSTERED INDEX [C_Data1_DTat] ON [dbo].[Table1]

(

[Data1] ASC,

[DTAt] ASC

)WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]

ALTER TABLE Table1 ADD CONSTRAINT PK_Table1 PRIMARY KEY (ID)

--小结以上的调优实践,要注意聚簇索引的选择。首先我们要找到我们最多用到的SQL查询,

--像本例就是那句类似的组合条件查询的情况,这种情况最好使用组合聚簇索引,而且最多用到的字段要放在组合聚簇索引的前面

--Index seek 为什么比 Index scan好?

--索引扫描也就是遍历B树,而seek是B树查找直接定位。