Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 2005 索引键列与索引包含列_Sql Server 2005_Tsql - Fatal编程技术网

Sql server 2005 索引键列与索引包含列

Sql server 2005 索引键列与索引包含列,sql-server-2005,tsql,Sql Server 2005,Tsql,有人能解释一下这个双索引键列和索引包含列吗 目前,我有一个索引,它有4个索引键列和0个包含列 感谢包含的列不构成索引键的一部分,但它们确实存在于索引中。基本上,这些值将被复制,因此存在存储开销,但索引覆盖(即被查询优化器选择)更多查询的可能性更大。这种复制还可以提高查询时的性能,因为数据库引擎可以返回值,而无需查看表本身 只有非聚集索引才能包含列,因为在聚集索引中,每一列都被有效地包含。索引键列是索引b树的一部分。不包含包含的列 取两个指标: CREATE INDEX index1 ON tab

有人能解释一下这个双索引键列和索引包含列吗

目前,我有一个索引,它有4个索引键列和0个包含列


感谢

包含的列不构成索引键的一部分,但它们确实存在于索引中。基本上,这些值将被复制,因此存在存储开销,但索引覆盖(即被查询优化器选择)更多查询的可能性更大。这种复制还可以提高查询时的性能,因为数据库引擎可以返回值,而无需查看表本身


只有非聚集索引才能包含列,因为在聚集索引中,每一列都被有效地包含。

索引键列是索引b树的一部分。不包含包含的列

取两个指标:

CREATE INDEX index1 ON table1 (col1, col2, col3)
CREATE INDEX index2 ON table1 (col1) INCLUDE (col2, col3)
index1
更适合这种查询:

SELECT * FROM table1 WHERE col1 = x AND col2 = y AND col3 = z
SELECT col2, col3 FROM table1 WHERE col1 = x
SELECT * FROM tableName WHERE column1 = x AND column1 = y AND column1 = z and column4=n
SELECT column1, column2 FROM tableName WHERE column1 = a
index2
更适合这种查询:

SELECT * FROM table1 WHERE col1 = x AND col2 = y AND col3 = z
SELECT col2, col3 FROM table1 WHERE col1 = x
SELECT * FROM tableName WHERE column1 = x AND column1 = y AND column1 = z and column4=n
SELECT column1, column2 FROM tableName WHERE column1 = a
在第一个查询中,
index1
提供了一种快速识别感兴趣行的机制。查询将(可能)作为索引查找执行,然后进行书签查找以检索整行

在第二个查询中,
index2
充当覆盖索引。SQL Server根本不必访问基表,因为索引提供了满足查询所需的所有数据<在这种情况下,代码>索引1也可以用作覆盖索引


如果您想要一个覆盖索引,但不想将所有列添加到b-树中,因为您不查找它们,或者因为它们不是允许的数据类型(例如XML),所以无法添加,请使用INCLUDE子句。

让我们考虑一下这本书。书中的每一页都有页码。本书中的所有信息都是基于此页码按顺序呈现的。用数据库术语来说,页码就是聚集索引。现在想想本书末尾的词汇表。这是按字母顺序排列的,允许您快速查找特定于页码的词汇表术语所属的。这表示以术语表术语作为键列的非聚集索引

现在假设每页的顶部都显示“章节”标题。如果您想在哪一章中找到术语表术语,您必须查找描述术语表术语的页面,然后打开相应页面,并查看页面上的章节标题。这显然代表了键查找——当您需要从非索引列中查找数据时,您必须找到实际的数据记录(聚集索引)并查看此列值。包含的列有助于提高性能—考虑一下术语表,其中每个章节的标题都包含术语表术语如果您需要找出术语表术语所属的章节-您不需要打开实际页面-您可以在查找术语表术语时找到它。

因此,包含的列与章节标题类似。非聚集索引(术语表)有一个附加属性作为非聚集索引的一部分。索引不是按包含的列排序的-它只是有助于加快查找速度的附加属性(例如,您不需要打开实际页面,因为信息已经在词汇表索引中)

示例:

创建表脚本

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
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, a page number is the clustered index. Now think about the glossary at the end of the book. This is in alphabetical order and allows 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 look up what page # describes glossary term, next - open the 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 the actual page - you can get it when you look up the glossary term.        So included columns are like those chapter titles. Non clustered Index (glossary) has an additional attribute as part of the non-clustered index. Index is not sorted by included columns - it just additional attributes that help to speed up the lookup (e.g. you don''t need to open the actual page because the 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
存储过程脚本

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
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, a page number is the clustered index. Now think about the glossary at the end of the book. This is in alphabetical order and allows 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 look up what page # describes glossary term, next - open the 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 the actual page - you can get it when you look up the glossary term.        So included columns are like those chapter titles. Non clustered Index (glossary) has an additional attribute as part of the non-clustered index. Index is not sorted by included columns - it just additional attributes that help to speed up the lookup (e.g. you don''t need to open the actual page because the 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
现在运行以下查询

select UIDNO,FName,DOB, MaritalStatus, Detail1 from dbo.Profile 
--Takes about 30-50 seconds and return 200,000 results.
select UIDNO,FName,DOB, MaritalStatus, Detail1 from dbo.Profile --Takes about 20-30 seconds and return 200,000 results.
问题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.
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.
现在删除上面的非聚集索引,并使用以下脚本重新创建

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
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
它将抛出以下错误

Msg 1919,16级,状态1,第1行 表“dbo.Profile”中的列“Detail1”的类型无效,无法用作索引中的键列

因为我们不能使用varchar(Max)数据类型作为键列。

现在使用以下脚本创建包含列的非聚集索引

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
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
现在运行以下查询

select UIDNO,FName,DOB, MaritalStatus, Detail1 from dbo.Profile 
--Takes about 30-50 seconds and return 200,000 results.
select UIDNO,FName,DOB, MaritalStatus, Detail1 from dbo.Profile --Takes about 20-30 seconds and return 200,000 results.
问题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.
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.

包含的列不构成索引键的一部分,但它们确实存在于索引中。基本上,这些值将被复制 下面以两种类型的索引和示例列为例

CREATE clustered INDEX NC_index1 ON tableName (column1, column1, column1,column4) CREATE clustered INDEX NC_index2 ON tableName (column1) INCLUDE (column2, column3,column4) 而NC_index2更适合这种查询:

SELECT * FROM table1 WHERE col1 = x AND col2 = y AND col3 = z
SELECT col2, col3 FROM table1 WHERE col1 = x
SELECT * FROM tableName WHERE column1 = x AND column1 = y AND column1 = z and column4=n
SELECT column1, column2 FROM tableName WHERE column1 = a

因为sql server不允许在数据类型(如XML、文本等)上创建索引

我想在其他答案中添加有关索引键列和包含列的更详细信息,以及使用包含列的好处。对于这个答案,我从Markus Winand发布于2019-04-30的一篇文章“密切关注索引包含条款”中获取了信息:

索引键列与包含列的区别的简要概述

要理解include子句,首先必须理解使用 索引最多影响三层数据结构:

  • B-树
  • B-树叶节点级的双链表
  • 桌子
前两个结构一起形成一个索引,因此它们可以 合并成单个项目,即“B-树索引”。 在一般情况下,数据库软件开始遍历B树以查找 叶节点级别的第一个匹配项(1)。然后,它跟随 双链接列表,直到找到所有匹配项(2)和 最后,它从表(3)中获取每个匹配项

当加载几行时,B-树对 整体努力。只要你需要拿一把 在表中的行中,此步骤处于领先地位。在任何一种情况下都很少或很少 许多行双链接列表通常是次要因素,因为它 相邻存储具有相似值的行,以便单个 读取操作可以获取100行甚至更多行。关于optimization>最通用的想法是,为了实现相同的目标,需要做的工作更少。什么时候