Pet*_*hia 117
索引键列是索引的b树的一部分.包含的列不是.
拿两个索引:
CREATE INDEX index1 ON table1 (col1, col2, col3)
CREATE INDEX index2 ON table1 (col1) INCLUDE (col2, col3)
Run Code Online (Sandbox Code Playgroud)
index1 更适合这种查询:
SELECT * FROM table1 WHERE col1 = x AND col2 = y AND col3 = z
Run Code Online (Sandbox Code Playgroud)
而index2更适合这种查询:
SELECT col2, col3 FROM table1 WHERE col1 = x
Run Code Online (Sandbox Code Playgroud)
在第一个查询中,index1提供了一种快速识别感兴趣的行的机制.查询将(可能)作为索引查找执行,然后执行书签查找以检索完整行.
在第二个查询中,index2充当覆盖索引.SQL Server根本不需要访问基表,因为索引提供了满足查询所需的所有数据.index1在这种情况下,它也可以作为覆盖指数.
如果你想要一个覆盖索引,但又不想将所有列添加到b-tree中,因为你没有寻找它们,或者因为它们不是允许的数据类型(例如,XML)而不能,所以请使用INCLUDE条款.
Ban*_*yan 13
让我们来看看这本书.书中的每个页面都有页码.本书中的所有信息都是根据此页码顺序显示的.在数据库术语中,页码是聚簇索引.现在想想本书末尾的术语表.这是按字母顺序排列的,允许您快速查找特定词汇表术语所属的页码.这表示非聚集索引,其中词汇表术语为关键列.
现在假设每个页面也在顶部显示"章节"标题.如果要查找词汇表术语的哪一章,则必须查找哪个页面#描述术语表术语,然后打开相应页面并查看页面上的章节标题.这清楚地表示密钥查找 - 当您需要从非索引列中查找数据时,您必须找到实际数据记录(聚簇索引)并查看此列值.包含的列有助于提高性能 - 考虑每个章节标题所包含的词汇表以及词汇表术语.如果您需要找出词汇表术语所属的章节 - 您不需要打开实际页面 - 您可以在查找词汇表术语时获取它.
所以列出的列就像那些章节标题.非聚集索引(词汇表)具有添加属性作为非聚集索引的一部分.索引不按包含的列排序 - 它只是有助于加快查找的其他属性(例如,您不需要打开实际页面,因为信息已经在词汇表索引中).
例:
创建表脚本
CREATE TABLE [dbo].[Profile](
[EnrollMentId] [int] IDENTITY(1,1) NOT NULL,
[FName] [varchar](50) NULL,
[MName] [varchar](50) NULL,
[LName] [varchar](50) NULL,
[NickName] [varchar](50) NULL,
[DOB] [date] NULL,
[Qualification] [varchar](50) NULL,
[Profession] [varchar](50) NULL,
[MaritalStatus] [int] NULL,
[CurrentCity] [varchar](50) NULL,
[NativePlace] [varchar](50) NULL,
[District] [varchar](50) NULL,
[State] [varchar](50) NULL,
[Country] [varchar](50) NULL,
[UIDNO] [int] NOT NULL,
[Detail1] [varchar](max) NULL,
[Detail2] [varchar](max) NULL,
[Detail3] [varchar](max) NULL,
[Detail4] [varchar](max) NULL,
PRIMARY KEY CLUSTERED
(
[EnrollMentId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
Run Code Online (Sandbox Code Playgroud)
存储过程脚本
CREATE Proc [dbo].[InsertIntoProfileTable]
As
BEGIN
SET NOCOUNT ON
Declare @currentRow int
Declare @Details varchar(Max)
Declare @dob Date
set @currentRow =1;
set @Details ='Let''s think about the book. Every page in the book has the page number. All information in this book is presented sequentially based on this page number. Speaking in the database terms, page number is the clustered index. Now think about the glossary at the end of the book. This is in alphabetical order and allow you to quickly find the page number specific glossary term belongs to. This represents non-clustered index with glossary term as the key column. Now assuming that every page also shows "chapter" title at the top. If you want to find in what chapter is the glossary term, you have to lookup what page # describes glossary term, next - open corresponding page and see the chapter title on the page. This clearly represents key lookup - when you need to find the data from non-indexed column, you have to find actual data record (clustered index) and look at this column value. Included column helps in terms of performance - think about glossary where each chapter title includes in addition to glossary term. If you need to find out what chapter the glossary term belongs - you don''t need to open actual page - you can get it when you lookup the glossary term. So included column are like those chapter titles. Non clustered Index (glossary) has addition attribute as part of the non-clustered index. Index is not sorted by included columns - it just additional attributes that helps to speed up the lookup (e.g. you don''t need to open actual page because information is already in the glossary index).'
while(@currentRow <=200000)
BEGIN
insert into dbo.Profile values( 'FName'+ Cast(@currentRow as varchar), 'MName' + Cast(@currentRow as varchar), 'MName' + Cast(@currentRow as varchar), 'NickName' + Cast(@currentRow as varchar), DATEADD(DAY, ROUND(10000*RAND(),0),'01-01-1980'),NULL, NULL, @currentRow%3, NULL,NULL,NULL,NULL,NULL, 1000+@currentRow,@Details,@Details,@Details,@Details)
set @currentRow +=1;
END
SET NOCOUNT OFF
END
GO
Run Code Online (Sandbox Code Playgroud)
使用上述SP,您可以一次插入200000条记录.
您可以看到"EnrollMentId"列上有聚簇索引.
现在在"UIDNO"列上创建一个非聚集索引.
脚本
CREATE NONCLUSTERED INDEX [NonClusteredIndex-20140216-223309] ON [dbo].[Profile]
(
[UIDNO] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)
现在运行以下查询
select UIDNO,FName,DOB, MaritalStatus, Detail1 from dbo.Profile
--Takes about 30-50 seconds and return 200,000 results.
Run Code Online (Sandbox Code Playgroud)
查询2
select UIDNO,FName,DOB, MaritalStatus, Detail1 from dbo.Profile
where DOB between '01-01-1980' and '01-01-1985'
--Takes about 10-15 seconds and return 36,479 records.
Run Code Online (Sandbox Code Playgroud)
现在删除上面的非聚集索引并使用以下脚本重新创建
CREATE NONCLUSTERED INDEX [NonClusteredIndex-20140216-231011] ON [dbo].[Profile]
(
[UIDNO] ASC,
[FName] ASC,
[DOB] ASC,
[MaritalStatus] ASC,
[Detail1] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)
它会抛出以下错误
消息1919,级别16,状态1,行1列'dbo.Profile'中的列'Detail1'是一种无效用作索引中的键列的类型.
因为我们不能使用varchar(Max)数据类型作为键列.
现在使用以下脚本创建包含列的非聚集索引
CREATE NONCLUSTERED INDEX [NonClusteredIndex-20140216-231811] ON [dbo].[Profile]
(
[UIDNO] ASC
)
INCLUDE ( [FName],
[DOB],
[MaritalStatus],
[Detail1]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)
现在运行以下查询
select UIDNO,FName,DOB, MaritalStatus, Detail1 from dbo.Profile --Takes about 20-30 seconds and return 200,000 results.
Run Code Online (Sandbox Code Playgroud)
查询2
select UIDNO,FName,DOB, MaritalStatus, Detail1 from dbo.Profile
where DOB between '01-01-1980' and '01-01-1985'
--Takes about 3-5 seconds and return 36,479 records.
Run Code Online (Sandbox Code Playgroud)
包含的列不构成索引键的一部分,但它们确实存在于索引中.本质上,这些值将被复制,因此存在开销,但您的索引更有可能覆盖(即由查询优化器选择)更多查询.此复制还可以在查询时提高性能,因为数据库引擎可以返回值而无需查看表本身.
只有非聚簇索引才能包含列,因为在聚簇索引中,每列都被有效地包含在内.
| 归档时间: |
|
| 查看次数: |
18830 次 |
| 最近记录: |