回答
索引鍵列是索引的b-tree的一部分。包含的列不是。
取兩個指標:
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
而index2
是更適合此類型的查詢:
SELECT col2, col3 FROM table1 WHERE col1 = x
在第一個查詢中,index1
提供了一個快速識別感興趣的行的機制。查詢將(可能)作爲索引查找來執行,然後是書籤查找來檢索整行。
在第二個查詢中,index2
充當覆蓋索引。因爲索引提供了滿足查詢所需的所有數據,所以SQL Server根本不必命中基本表。在這種情況下,index1
也可以充當覆蓋索引。
如果你想要一個覆蓋索引,但不想將所有列添加到B樹,因爲你不在它們上面尋找,或者不能,因爲它們不是允許的數據類型(例如,XML ),請使用INCLUDE子句。
包括列不構成索引鍵的一部分,但它們對指數存在。本質上,這些值將被複制,因此存在一定的存儲開銷,但索引將覆蓋(即由查詢優化器選擇)更多查詢的可能性更大。這種重複也可以在查詢時提高性能,因爲數據庫引擎可以返回值而不必查看錶本身。
只有非聚簇索引可以包含列,因爲在聚簇索引中,每個列都被有效包含。
+1 IOW覆蓋索引的行密度更高,這意味着SQL需要獲取更少的頁面。 – StuartLC 2010-08-27 04:37:06
@nonnb:使用覆蓋索引,不需要書籤查找。是的,讀取的頁面更少,並且SQL Server不得不做更少的工作,但這是因爲它需要的所有信息都包含在索引中。對於其中的一些定義,「信息密度」可能更高。不過,不清楚你的行密度是什麼意思。 – 2010-08-27 04:43:02
讓我們來思考一下這本書。書中的每一頁都有頁碼。本書中的所有信息都是根據此頁碼順序呈現。在數據庫術語中,頁碼是聚集索引。現在想一想本書最後的詞彙表。這是按字母順序排列的,可讓您快速找到特定術語表所屬的頁碼。這表示包含術語表術語的非聚集索引作爲關鍵列。
現在假設每頁也在頂部顯示「章節」標題。如果您想查找詞彙術語的哪一章,則必須查找術語術語術語的下一頁 - 打開相應的頁面並查看頁面上的章節標題。這顯然代表了關鍵查找 - 當您需要從非索引列中查找數據時,您必須找到實際數據記錄(聚集索引)並查看此列值。包含的列在性能方面有所幫助 - 請考慮除詞彙表術語外每個章節標題包含的詞彙表。 如果您需要了解術語表的術語屬於哪一章 - 則不需要打開實際頁面 - 查找術語表時可以獲取它。
所以包含的列就像那些章節標題。非聚集索引(詞彙表)具有添加屬性作爲非聚集索引的一部分。索引不是按包含的列排序 - 它只是幫助加快查找的附加屬性(例如,因爲信息已在詞彙表索引中,所以不需要打開實際頁面)。
例子:
創建表腳本
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, 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, [email protected],@Details,@Details,@Details,@Details)
set @currentRow +=1;
END
SET NOCOUNT OFF
END
GO
使用上述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
現在運行下面的查詢
select UIDNO,FName,DOB, MaritalStatus, Detail1 from dbo.Profile
--Takes about 30-50 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.
現在拖放上述非聚集索引,並與下面的腳本
重新創建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
它會引發以下錯誤
消息1919年,級別16,狀態1,行 列「Detail1」表「dbo.Profile」是一類是無效的使用作爲索引中的關鍵列。
因爲我們不能使用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
現在運行下面的查詢創建一個非聚集索引
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 3-5 seconds and return 36,479 records.
http://social.msdn.microsoft.com/Forums/sqlserver/en-US/7fb76e54-4912-48fa-8816-56878e88a176/whats-the-difference-between-index-key-columns-and-include-columns - 當創造-的指數?論壇= sqldatabaseengine – mrd3650 2014-04-25 15:47:59
- 1. 散列VS索引
- 2. 多列索引VS多個索引
- 3. 散列索引vs倒排索引
- 4. 索引外鍵列
- 5. 單獨列索引VS多
- 6. MySQL的多個索引VS多列索引搜索
- 7. 索引,索引陣列
- 8. 包括與ActiveAdmin索引中的關係
- 9. 非主鍵列MySQL索引
- 10. 多列唯一索引鍵
- 11. 一列索引對2列索引
- 12. 未定義索引包括
- 13. 熊貓DataFrame.groupby包括索引
- 14. 軌如何添加在:包括了多個索引鍵關聯
- 15. NHibernate列表鍵列上的SQL索引?
- 16. 索引列
- 17. 索引varchar列
- 18. 列索引號
- 19. 索引5列
- 20. 索引多列
- 21. 索引多列
- 22. 索引列名
- 23. datagridview列索引
- 24. 索引表列
- 25. 多列上的非集羣索引VS單個索引中的多列
- 26. 創建一個列的索引Vs的上聚類列創建索引
- 27. 非主鍵列上的聚簇索引或非聚簇索引?
- 28. 聚集索引的外鍵VS主鍵
- 29. 主鍵vs主鍵索引速度
- 30. 綁定索引系列與索引
有輕微的性能改進如果您不需要的密鑰位於包含列中:https://logicalread.com/ tidbit-sql-server-indexing-part-1/ – Sun 2017-08-17 15:15:15